Module Structure
Agent Teams 在 durable 子代理之上增加团队身份、共享任务 DAG 和成员间消息;它不复制 Agent 执行器,而是组合 BackgroundAgentManager 与 TaskListManager。
Directory Layout
packages/cli/src/agent/teams/— 团队核心TeamRuntime.ts— 创建、成员启动、鉴权、消息和状态投影TeamStore.ts— 团队配置与 tombstone 持久化TeamTaskGraph.ts— 通用任务列表到依赖图的投影TeamMailbox.ts— durable 点对点/广播邮箱TeamCoordinator.ts— 成员成功后的任务完成与解除阻塞TeamEvents.ts— 跨表面事件契约
packages/cli/src/tools/builtin/team/— 六个团队工具适配器packages/cli/src/server/routes/team.ts— Hono 团队 API 与 feature gatepackages/cli/web/src/components/chat/TeamPanel.tsx— Web 成员、任务和消息面板packages/cli/src/ui/components/TeamProgress.tsx— TUI 团队进度投影
Key Entry Points
TeamRuntime.create()inpackages/cli/src/agent/teams/TeamRuntime.ts— 持久化团队、任务并启动所有成员TeamRuntime.claimTask()inpackages/cli/src/agent/teams/TeamRuntime.ts— 带 actor/owner 校验的原子认领TeamRuntime.sendMessage()inpackages/cli/src/agent/teams/TeamRuntime.ts— durable 消息与即时 steeringTeamCoordinator.completeMemberWork()inpackages/cli/src/agent/teams/TeamCoordinator.ts— 成员成功后的任务图推进createTeamTools()inpackages/cli/src/tools/builtin/team/teamTools.ts— Agent 可调用的团队能力集合
Gotchas
- 团队成员不是任意并行 worker:每个成员都是绑定 lead session、canonical workspace、team ID 和共享 task-list ID 的后台子代理;缺任一身份时访问应按“team 不存在”失败,不能泄露跨会话团队 (
packages/cli/src/agent/teams/TeamRuntime.ts,packages/cli/src/agent/subagents/AgentSessionStore.ts) TeamCreate启动中途失败会取消已启动成员并把团队标为 deleted,但不会物理删除目录;同名再次创建会获得数字后缀而不是复用 tombstone 名称 (packages/cli/src/agent/teams/TeamRuntime.ts,packages/cli/src/agent/teams/TeamStore.ts)- 任务依赖只能引用本次声明中更早的序号,这一限制在创建成员前校验并天然阻止前向依赖和环;绕过
TeamRuntime直接写共享任务列表会失去该保证 (packages/cli/src/agent/teams/TeamRuntime.ts) - 成员只有以
completed + result.success=true结束时,协调器才自动完成其所有in_progress任务;failed/cancelled 成员留下的任务不会被伪装成完成 (packages/cli/src/agent/teams/TeamCoordinator.ts) - 团队状态先看是否仍有 running 成员,因此“一个成员失败、另一个仍运行”仍显示 running;全部 worker 完成但任务图未全部完成时最终状态是 failed (
packages/cli/src/agent/teams/TeamRuntime.ts) - 未指定工具列表表示成员拥有全部工具,因此默认使用 worktree;显式只读工具集留在父 workspace,显式含 Edit/Write/ApplyPatch/Bash 的角色也默认 worktree (
packages/cli/src/agent/teams/TeamRuntime.ts) - teammate 不能创建嵌套 team,因为所有 child Agent 都被宿主强制 blacklist
TeamCreate,不能只靠成员 prompt 中的约束 (packages/cli/src/agent/subagents/BackgroundAgentManager.ts,packages/cli/src/agent/subagents/SubagentExecutor.ts) SendMessage先持久化 mailbox 再尝试注入目标成员 steering;只有 runtime 接受后才写deliveredAt,因此离线或尚未启动的成员会在onStarted阶段补收 (packages/cli/src/agent/teams/TeamRuntime.ts,packages/cli/src/agent/teams/TeamMailbox.ts)deliveredAt与acknowledgedAt是不同语义:即时注入只表示已投递,成员仍需通过TeamInbox显式确认;不能用其中一个字段替代另一个 (packages/cli/src/agent/teams/TeamMailbox.ts)- 团队消息正文被包装成“不可信 teammate input”,不能授权工具或覆盖系统策略;接收者必须把它当协作数据而不是控制指令 (
packages/cli/src/agent/teams/TeamMailbox.ts) TeamDelete默认取消运行中的成员,但实现只写deletedAt;Web/TUI 通过过滤 deleted 状态隐藏团队,磁盘记录仍保留用于审计 (packages/cli/src/agent/teams/TeamRuntime.ts,packages/cli/web/src/components/chat/TeamPanel.tsx)
Architecture
TeamStore保存团队和成员静态定义,成员动态状态从AgentSessionStore投影,任务状态来自独立TaskListManager,消息来自 mailbox;任何单一文件都不是完整团队快照 (packages/cli/src/agent/teams/TeamStore.ts,packages/cli/src/agent/teams/TeamRuntime.ts)- 共享任务图使用 team name 作为
taskListId,TeamTaskGraph只负责把通用pending/in_progress/completed转成pending/blocked/running/completed并计算反向依赖 (packages/cli/src/agent/teams/TeamTaskGraph.ts) - 任务认领通过
TaskListManager.claimNextAvailable()的进程内 keyed mutex、文件锁和原子写组合完成;候选必须未阻塞且未分配或已分配给当前成员,再按优先级和 ID 选择 (packages/cli/src/tools/builtin/task/TaskListManager.ts,packages/cli/src/agent/teams/TeamTaskGraph.ts) - 团队事件始终发布到 lead SessionRef,TUI、Web 和 ACP 从同一事件/快照投影成员、任务和消息;成员自己的 LoopEvent 仍由子代理 bridge 负责 (
packages/cli/src/agent/teams/TeamEvents.ts,packages/cli/src/agent/teams/TeamRuntime.ts) - 团队完成由“所有 worker terminal + 所有任务 completed”共同决定,不以 lead 是否收到成员摘要作为完成依据 (
packages/cli/src/agent/teams/TeamRuntime.ts)
Decisions
- 团队层复用 durable subagent 和任务列表,而不是引入第二套执行器与 DAG 存储;这让进程恢复、Provider 准入和 worktree 交付沿用子代理语义 (
packages/cli/src/agent/teams/TeamRuntime.ts,packages/cli/src/agent/teams/TeamTaskGraph.ts,git:402cd82a) - mailbox 采用每团队单文件、
0600原子写和 keyed mutex,并设置 8 MiB 总上限与 32 KiB 单消息上限;超限时拒绝写入而不是截断协作消息 (packages/cli/src/agent/teams/TeamMailbox.ts) - 团队工具虽然归类为 read-only 以便在受限模式中协调,但
TeamCreate、SendMessage和TeamDelete都有 durable 副作用,因此并发安全分别显式标注而不依赖 ToolKind 推断 (packages/cli/src/tools/builtin/team/teamTools.ts)
Patterns
- 成员 prompt 固定注入团队目的、共享 task graph、workspace 和 peer-messaging 状态,并要求任务完成后原子认领下一项;角色自己的 system prompt 仍由 Subagent 配置提供 (
packages/cli/src/agent/teams/TeamRuntime.ts) TeamTaskClaim和TeamInbox可从 teammate 的ExecutionContext.taskListId/sessionId推断身份,lead 或 HTTP 调用则必须显式提供 owner 信息 (packages/cli/src/tools/builtin/team/teamTools.ts,packages/cli/src/server/routes/team.ts)- Web 面板只在 feature 开启、存在当前 SessionRef 且拥有非空团队列表时渲染;deleted team 在状态源和界面两层过滤,刷新后仍从 durable 快照恢复 (
packages/cli/web/src/components/chat/TeamPanel.tsx,packages/cli/src/agent/teams/TeamRuntime.ts)