Agent Team 实现
配置、任务与运行分别管理
设计以具备分工、沟通和结果判断能力的 LLM 为基础,由 harness 让这些决策能够执行并被观察。产品原则与模型兼容边界见协调模型。
四组概念具有不同生命周期:
| 概念 | 含义 |
|---|---|
| AgentTeam 目录 | 可复用的团队配置与专家角色。 |
| 频道成员列表 | 会话可用的 agent;加入频道不会自动启动团队执行。 |
| Runtime Team | 由 team_create 创建、由 team_dissolve 关闭的工作会话。 |
| Member / Task / Run | 持久化成员拥有一个逻辑任务,可以执行多轮物理运行。 |
运行团队保持 active 时,已交付成员仍可被唤醒。持久化指身份和记录,不代表唤醒时自动恢复上轮完整对话。
聊天宿主与成员复用 agent loop
runChatTurn 构造 Lead 的运行环境、工具与 instructions。系统 Lead 拥有 team 工具且频道存在其他成员时,会获得 TEAM_LEAD_OVERLAY 与成员列表。宿主侧接线将服务注册到 teamServicesRegistry,并向上下文写入团队身份。
| 组件 | 职责 |
|---|---|
team.tool.ts | 校验模型调用,将成员名称转换为内部身份。 |
TeamCoordinator | 持久化团队、任务、消息、交付与依赖状态变化。 |
TeamExecutionService | 启动独立的 runAgentLoop 成员运行,管理运行归属并处理退出。 |
team-wake-router.ts | 将事件转换为 Lead 或成员的唤醒请求和 UI 状态更新。 |
team-mailbox.ts | 将协调者收件箱正文注入 Lead 的逐步提醒。 |
成员执行独立于 TaskOrchestrator,使用 kind: "member"、TEAM_MEMBER_INSTRUCTIONS 和成员特化 instructions。Lead 与成员共享 workspace,但运行上下文和模型历史相互独立。任务说明应指定不同输出路径,避免并发覆盖。
当前双方都能看到五个 team 工具。成员调用 team_create、team_replan 或 team_dissolve 会被拒绝。成员工具集排除嵌套委派和直接向用户提问的工具;需要用户判断的问题经 Lead 转达。
创建时只启动依赖已满足的工作
以下示例假设工具成员列表包含所用 agent 类型。实际任务说明需要提供输入路径和验收标准。
{
"name": "认证模块审查",
"output_language": "Chinese",
"members": [
{
"name": "Reviewer",
"agentType": "general",
"title": "审查认证边界",
"prompt": "读取 /workspace/src/auth,审查会话过期与授权边界。将证据和发现写入 /workspace/auth-review.md,不修改源码。"
},
{
"name": "Verifier",
"agentType": "general",
"title": "复核发现",
"prompt": "读取上游审查和引用的源码,逐项复核,将报告写入 /workspace/auth-verified.md,区分已确认问题与不确定项。",
"dependsOn": ["Reviewer"]
}
]
}
team_create 单次接受 1–8 个成员,校验名称和依赖环,并为每个成员创建一个逻辑任务。这是创建调用的输入限制,不代表 team_replan.add 对团队累计成员数实施同样限制。
就绪任务进入 in_progress,启动动作延迟到 Lead 本轮提交后执行。依赖未满足的任务保持 blocked,不会启动模型运行。依赖完成后,任务变为 claimable,由成员运行时自动推进到 in_progress,模型无需调用 claim 工具。开始工作时记录所依赖的任务版本。
Lead 可以通过 team_replan 追加后来明确的工作,创建时无须预测完整流程。
事件推进工作,无需轮询
| 事件 | 调度效果 |
|---|---|
| 消息 | 唤醒接收者;运行中的成员可以在下一步读取。 |
| 任务完成 | 唤醒就绪下游;没有就绪下游且没有任务处于 in_progress 时,唤醒 Lead。 |
| 任务失败或取消 | 唤醒 Lead,处理恢复或决策。 |
| 团队解散 | 通知 Lead。 |
| 任务创建、领取或普通成员状态变化 | 更新状态,不仅为状态变化启动模型。 |
team_status 对双方都立即返回,每轮最多调用一次。它不是 long-poll;即使调用者仍在同一轮,并行执行也可能改变底层状态。
工具结果可能包含供 UI 使用的 teamId、成员 ID 和任务 ID。模型输入使用名称,不需要传入 teamId。状态响应中的任务状态位于成员的 work 内,成员状态与任务状态不能混用。
消息可以纠偏,也可以明确结束本轮等待
消息先持久化,再发送唤醒事件。唤醒事件延迟到发送者本轮结束;已在运行的接收者可能在此前就读取消息。因此,延迟唤醒不代表发送者整个回合具有事务性。
Lead 与成员在步骤开始前消费收件箱,将消息正文保留在接收消息的本轮提醒中。成员提醒还包含当前任务、修订要求和上游摘要及文件路径。
成员必须获得答复才能继续时,使用:
{
"to": "Coordinator",
"content": "需要验证哪个部署区域?当前进展已写入 /workspace/notes.md。",
"wait_for_reply": true
}
该调用在工具步骤边界停止本轮,不完成也不判失败。不要在同一步同时调用 complete 或执行无关工作。普通消息不会停止发送者。Lead 用普通消息答复,后续消息可以启动成员的新一轮运行。退出补偿会检查清理期间到达的回复,避免回复被旧运行锁阻挡后无人处理。
本轮通过局部标记停止运行,正常结束后在现有运行记录中持久化 finishReason: "waiting"。重启与普通唤醒路径先检查最近完成的运行和未读消息;没有新消息时,已提交的等待继续保持。释放锁后再次检查,可处理判断期间到达的消息。逻辑任务仍为 in_progress,UI 可能继续显示为有未完成工作。记录提交前崩溃仍按中断运行恢复,当前也没有实现完整对话恢复或按问题匹配回复。
交付、修订与取消具有不同含义
成员在任务完成后调用 complete({ summary, paths })。简短结论可以使用 paths: []。任何提交路径无效时,交付被阻止,下游保持阻塞。有效交付会记录结果、刷新依赖并发送 task_completed,成功后结束成员本轮运行。
team_replan 支持三种操作:
add:以新名称创建成员并声明依赖,可以依赖已交付成员。revise:使用原成员和任务身份重新打开已交付工作,并推进版本。已交付下游进入stale,随后按依赖顺序重做。修订前,下游必须已经交付或取消。cancel:取消未完成工作及依赖分支。失败根任务保留失败记录,未完成下游被清理。替代节点不会自动继承或转接旧依赖。
Replan 顺序执行,不是事务。名称、图和取消后依赖会在修改前校验,修订也会按调用顺序预演;导致后续操作失效的重复或相互影响的修订会在写入前被拒绝。并发变化或基础设施错误仍可能留下部分变更,重试前应先检查状态。
Lead 检查并验收结果,在没有后续工作时关闭团队,再最终交付。Lead 的 complete 不会自动关闭团队。用户 Stop/Clear 路径也会显式停止活跃成员。
六张表区分任务历史与执行历史
服务端定义 team、team_member、team_task、team_task_delivery、team_message 和 team_member_message。任务交付保留修订历史;成员运行记录物理轮次、触发原因、结束原因和用量。各宿主的仓储适配器实现共享核心契约。
进程内运行记录、唤醒锁、运行归属与心跳用于防止重复归属并支持清理。这些机制保障执行,不判断模型结果是否正确,也不合并冲突的文件写入。
客户端由工具结果初始化团队状态,team:state-update 传递任务与成员状态变化,team:member-part 传递成员流式内容,快照恢复用于重新打开历史会话。UI 事件是持久状态的展示,不是调度事实来源。
契约验证与模型质量分别评估
本轮针对团队服务和停止条件的回归套件共 60 项测试,覆盖消息正文注入、明确等待、SDK 循环停止、回复补偿、失败分支清理、已完成依赖和缺失产物拒绝。TypeScript 与格式检查通过。
这些是包含模拟模型的确定性验证,不代表真实模型的质量与成本已经得到验证。后续评测应覆盖独立工作、依赖交接、中途求助、相关修订、失败恢复,以及无需委派的简单请求。剩余边界见协调模型。