Chorus v0.24.0: 你的 Agent 们,终于算个团队

接了三四个 Agent 进 Chorus 之后,实际跑起来往往还是一个 Agent 包圆:它写方案,它写代码,它再 review 自己写的代码。所谓“独立评审”,是同一个会话里 spawn 出来的子 Agent,由作者自己下发任务提示,自然也容易漏掉作者漏掉的东西。

想把活分开,就得自己盯着派。谁手上空着,谁有对应权限,第一轮是谁评的,这轮还得找同一个人。这些判断每次都要重做一遍。

还有一个更隐蔽的。即便把评审交给另一个 Agent,如果它恰好也是这条线的开发者,它会带着完整的开发记忆来做评审。看着是换了人,其实没换脑子。

v0.24.0 把团队固定成一份配置。角色配一次,绑到项目上,派活有工具给人选,评审跑在自己的会话里。

团队只管派活,不发权限

在设置里的 Agent 团队中按角色组队,四个角色:产品(product)、开发(development)、评审(review)、负责人(lead)。同一个 Agent 可以兼多个角色,团队也允许先存成空的。然后在项目设置的团队标签页里把它绑到这个项目上。

界面上那两句提示不是免责声明,是这个功能的边界。存下一支团队不会派出任何活;这份配置只有你和你的 Agent 能读,角色也不授予任何权限或项目访问权。团队只管一件事,谁来干。

所以“能不能接这个角色的活”是算出来的,不是勾出来的。Agent 得是你自己的,持有该角色需要的权限,并且在这个项目上有协作权限。不满足的成员仍然留在角色列表里,带着原因显示,不会被悄悄删掉。列表另外给出在线和当前负载,离线不等于不合格,只是现在忙不忙。

查看者可以打开并保存自己的团队配置,但往角色里加人和把 Idea 交出去都要项目编辑者权限。每个角色的权限要求、成员状态怎么读、绑定怎么解,都在把智能体组织成团队里。

谁是这条线的统筹者

绑好团队之后,把一个 Idea 指派给你自己的某个 Agent,这条线就算 Team 托管了。这个被指派的 Agent 就是它的统筹者,不要求是负责人。这条线上你自己的 Agent 在托管的父 Idea 下再派子 Idea,子 Idea 同样进入托管。

托管状态不存在任何一张表里,是读的时候才算出来的。服务端看这条 Idea 是谁派给谁的、被派的 Agent 归谁、这个人在这个项目上绑了哪支团队,再加上 Idea 的血缘和活动记录。所以没有新表,没有迁移,老数据升上来也不用补。

团队不改变谁能批、谁能验。服务端的门还是老样子,审批看 proposal:admin,验证看 task:admin,没有多出一道团队闸门。

变的是统筹者该怎么做:任务要等本轮评审给出 PASS 或 PASS WITH NOTES、必需的验收标准全过,才由它收掉;方案只有在人类对这条 Idea 开过 YOLO 时才允许它自己批,没开 YOLO 就在 PASS 之后 @ 人类请批,自己不动手。

派活之前先问一句

统筹者不自己猜该找谁,而是问 chorus_recommend_team_agent。

它先排掉不合格的,再排掉离线的,剩下的人里优先找上一轮给过 VERDICT 的那个,都没有就看谁手上最闲。真打平了,它不替你拍板,返回 lead_decision,让统筹者在候选里挑。

另外三种结果照字面做就行:recommended 直接用,paused 停下来找人,manual 则是这条线没法自动路由,回到手动派活。

推荐出来的是自己,就在同一轮里认领并开始。派给自己的任务不会产生唤醒。

评审的请求走 chorus_request_review,正文由服务端拼好,只把那一个评审者唤进它的评审会话,手写一条评论是开不出评审会话的。

评审者保持只读,每轮只发一条 VERDICT 评论,里面只 @ 一个人,就是下一步该动手的那个。每个实体最多评三轮。

要注意评审推荐不排除任何人,写代码的那个也可能被推回来评;评审角色空着或全员离线时,工具会退回统筹者,让它当轮用对应的 reviewer 子 Agent 兜底。这是刻意留的降级路径,不是默认形态。

评审的那个 Agent,不该记得自己写过代码

根子在 daemon 身上。一个键被当成两样东西用,既是 Chorus 会话的业务键,又是唤醒队列里的排队车道,而这个键就是 Agent 的直属 Idea。于是评审唤醒一到,恢复出来的还是那条开发会话。

现在服务端按唤醒的目的来选会话锚点。Idea 层面的活还在 Idea 锚点上,指派、澄清、写方案、统筹交接都算,人类在 Idea 会话里下的指令也算。

任务唤醒走 task:<taskUuid>,发给这个任务当前的承接者;承接者本人就是统筹者时,只有指派和打回走任务锚点,其余留在它的 Idea 会话里。团队评审请求走 review:task|proposal|idea:<uuid>。锚点跟着唤醒一起由服务端下发,daemon 拿它当车道,也拿它当后端会话的锚点。

这么一拆,评审唤醒就不会再 resume 开发会话,某个目标的第一轮评审一定是新会话。同一个评审者对同一个目标复审时,resume 的是它自己那条评审会话。

顺带,一个 Agent 能同时推两个任务

同一条车道原先还有个副作用,一个 Agent 在同一个 Idea 上的所有唤醒都排在里面,几个本来互不相干的任务只能一个接一个跑。锚点拆开之后,不同锚点可以并发,受 Agent 原有的 maxConcurrency 约束。

界面上也能看出来。任务和评审现在各自是一条子对话,挂在它那条 Idea 的对话下面,标成“任务:标题”和“评审:标题”,各有自己的记录、运行状态和打断恢复控件。指令仍然在 Idea 的对话里发。

这次改的是 Chorus CLI daemon 这条路径。OpenClaw、Hermes 和 dsh 的原生路由不在范围内,它们仍然每个 Idea 一条对话;没升级的旧 daemon 也会退回原来的路由,别指望那边有任务和评审的隔离。界面上这些对话怎么排,在线智能体总览里能看到。

子 Agent 不等于第二双眼睛

多 Agent 编排是现在工具链普遍在走的方向,Claude Code 的 Agent Teams 和各家的 subagent 都在这条路上。主流做法是一个会话 spawn 出子 Agent,跑在同一个进程里,用同一套凭据和权限,由父会话下发任务提示,父会话一结束它们也跟着没了。

它们有自己的上下文窗口,但没有自己的身份,也留不下自己的会话。

这种形态很好用,拆活、并行、省上下文都靠它。但代码是谁写的,子 Agent 就是谁 spawn 的,任务提示也是那个人写的。

Chorus 的团队成员是独立认证的 Agent,各自有自己的权限集合和自己的会话。隔离做在会话锚点上,不是靠提示词叮嘱它“请忘掉刚才写的代码”。

Quick Task 也能挂到 Idea 上了

以前 Quick Task 要么挂在一个已批准的方案下,要么就那么飘着。现在它可以直接链到同项目的某一条 Idea 上,MCP 和 REST 两边的任务接口都接受 ideaUuid。链接随时能改,也能清掉。主题型 Idea 不收任务,它只负责归拢派生出来的子 Idea。

链上之后这些任务会出现在 Idea 上,并计入它的进度。Idea 的状态也改成统一推导,不再只看方案任务。具体怎么点,将快速任务关联到想法里有步骤。

顺手修掉一个坑。一条链上的 Quick Task 如果比方案任务先完成,整条 Idea 的代码评审就提前开跑了。现在 Claude Code、Codex/TRAE、Kiro 和 Hermes 的 post-verify 钩子都拿服务端推导出来的 Idea 状态做判断,Idea 真完成了才提醒。

这一版还补了依赖的安全更新,修掉 Next.js 和 DOMPurify 的漏洞,并覆盖 zod、body-parser、undici 和 devalue,把 root 的高危审计清掉。


本版七套插件和四个 npm 发布包统一到 0.24.0。

只要团队里有合格且在线的评审成员,现在给你 review 代码的就是另一个独立认证的成员,评审这件事由服务端给它新开一条会话。它确实不记得自己写过这段代码。