多 Agent 协作

两种协作强度使用不同协议

aibuddy 没有把所有委派都抽象成同一种“多 Agent”。边界明确、只需返回一次结果的工作使用 task 子 Agent;存在依赖、成员通信或重新规划的工作使用 Agent Team。两者共享真实工作区,但生命周期和协调协议不同。

维度task 子 AgentAgent Team
生命周期一次运行,提交结果后结束由事件多次唤醒,持续到交付或解散
输入自包含的委派说明初始任务、依赖和后续 inbox 消息
协调运行中不能向主 Agent 追问Lead 与成员、成员之间可发送持久消息
调度独立调用可在同一步并发只有依赖满足的成员才会启动
返回摘要、产物路径、状态和步数版本化任务交付与完整团队状态

Agent Team 的三层协作架构 成员拥有隔离运行轨迹,团队通过持久任务图、消息、修订和运行所有权协调,文件与交付物写入共享工作区,最终由 Lead 验收。 推理轨迹隔离,协调状态持久化,工作产物共享 模型并发只发生在可运行节点;任务事实不依赖任何单个成员的上下文。 运行层 · 每个成员拥有独立上下文与执行轨迹 Lead 拆分 · 重规划 · 最终验收 成员 A 隔离运行轨迹 成员 B 隔离运行轨迹 成员 C 依赖满足后启动 持久团队状态 PostgreSQL / SQLite 是事实来源,路由决策读取最新一致快照 DAG 与任务状态 依赖 · 条件领取 持久 inbox 先写入 · 后唤醒 版本化交付 修订 · 依赖版本 运行所有权 runId · heartbeat 事件唤醒 条件满足 共享工作区 文件 · 代码 · 可检查产物 所有成员直接读写;并发修改仍需预先划分所有权 Lead 验收 整合 · 验证 · 收敛 事件负责推进,仓储负责事实,工作区负责产物。

这种区分避免为简单委派引入团队状态,也避免用一次性调用勉强承载需要等待、沟通和修订的长期协作。

子 Agent 隔离运行轨迹,但共享真实工作区

task 会为子 Agent 创建新的运行上下文、压缩状态和工具集合。它只接收委派说明,不继承主 Agent 的完整对话,也不能在执行途中向主 Agent 请求补充信息。因此,委派必须给出足以独立工作的目标、输入边界、允许修改的范围、预期产物和验收条件。

运行上下文隔离不等于文件系统隔离。子 Agent 与主 Agent 一对一共享当前沙箱和工作区;生成的文件不需要复制或转换路径,主 Agent 可以直接检查。多个子 Agent 并发写入时必须预先划分文件或目录,系统不会自动合并对同一目标的修改。

子 Agent 的实时步骤会作为界面事件转发,并在结束后保存为可重新打开的执行记录,但不会进入主 Agent 的模型上下文。运行期间由心跳维持父工具调用;结束时,只有 complete 产生的摘要、经过验证的产物路径、跳过项、状态和步数返回主 Agent。用户可以检查执行过程,主上下文则只承担交付信息。

Agent Team 把协调状态放进持久任务图

Agent Team 在一次 team_create 中声明成员与依赖。运行时先检查成员名称唯一性、依赖目标和有向无环图;校验通过后才写入团队、成员和任务。team_create 单次最多接受 8 个执行成员,这不代表追加成员时实施团队累计数量限制;每个成员负责一个逻辑任务。模型通过稳定的成员名称协作,不需要处理内部 UUID 或 teamId。

团队状态以持久化仓储为事实来源。服务端使用 PostgreSQL,桌面端使用 SQLite;图计算每次从仓储读取最新成员与任务记录,不维护另一份可能漂移的长期内存图。任务领取使用条件更新,把 claimable 原子推进为 in_progress,避免并发运行重复领取同一工作。

成员状态与任务状态分开记录:成员可以是 spawning、working、idle、done、failed 或 cancelled;任务可以是 pending、blocked、stale、claimable、in_progress、completed、failed 或 cancelled。分开建模后,“成员当前没有运行”不再被误判为“任务已经完成”。

事件唤醒只启动真正可运行的成员

依赖未满足的成员保持 idle,不会先启动一个模型进程等待上游。任务完成事件到达后,路由器重新读取最新快照;只有任务为 claimable 且所有依赖再次核验为 completed 的成员才会被唤醒。这层复核防止预计算状态过期后错误启动下游。

事件路由遵循任务图,而不是每次变化都唤醒 Lead:

事件唤醒目标
定向或广播消息对应接收者;广播排除发送者
任务完成此刻真正可运行的下游成员
任务失败、取消或团队解散Lead
没有下游可运行且无人执行Lead,由其判断已完成还是发生阻塞
任务创建、领取、普通状态变化只更新状态,不额外启动模型

team_status 立即返回,每轮最多一次以防轮询;并行工作仍可能改变状态。成员必须获得答复才能继续时,使用 team_send_message 的 wait_for_reply: true,结束本轮但保留未完成任务。正常结束的等待会记录为 finishReason: "waiting",没有新消息时恢复路径保持等待;记录提交前崩溃仍按中断运行恢复。

每个成员步骤开始前,运行时会注入当前身份、未读消息和可领取任务。身份提醒使用固定键覆盖更新,因此可以每步强化角色边界而不在上下文中重复累积。

消息、交付与文件承担不同职责

team_send_message 适合传递决策、阻塞原因和少量上下文,不用于承载大型成果。消息先持久化到接收方 inbox,再把唤醒事件推迟到发送方当前轮次提交之后;空闲接收方在这个边界之后启动。已在运行的接收方可以在发送者结束前读取消息,因此这不是整个回合的事务保证。

文件成果应写入共享工作区;简短结论可通过摘要和 paths: [] 交付。逻辑任务通过 complete 提交交付,任一提交路径无效都会阻止团队任务完成。Lead 与成员都会获得收件箱正文,下游成员会获得依赖摘要与路径。任务完成事件可以直接把执行权交给下游,Lead 不必在每个中间节点参与转发。最终整合和验收仍由 Lead 完成;成员状态全部结束并不自动等于整体交付成立。

三种通道因此有明确边界:

通道承载内容保留方式
inbox短消息、问题、方向调整持久化并在下一步骤消费
任务交付摘要、结果和修订版本追加记录,关联逻辑任务
共享工作区文件、代码和可检查产物由所有成员直接读写

重新规划保留历史,而不是覆盖旧结果

team_replan 支持取消成员、增加新成员,以及修订已经完成的逻辑任务。修订沿用原成员和任务身份,递增版本并记录新指令;已经依赖旧版本完成的下游会进入 stale,再按依赖顺序重新执行。任务领取时还会记录所依赖的具体版本,使一次交付的依据可追踪。

Replan 顺序执行,不是事务。新增任务可以依赖已交付成员;取消失败分支时保留根任务的失败记录,并清理未完成下游。修订前,下游任务必须已经交付或取消。

取消采用相反方向的保护:系统先把目标及其下游任务写成 cancelled,再中止成员流。这样,流退出后的清理逻辑不会把一次明确取消覆盖成一般失败。成员异常退出或心跳失效时,尚未交付的任务会转为 failed,并唤醒 Lead 决定重新规划;系统不会擅自把失败依赖视为已经满足。

运行所有权约束并发与故障恢复

同一成员流同时受进程内活动表、跨节点唤醒锁和仓储中的 runId 所有权约束。运行期间持续写入心跳,释放时按 runId 条件更新;即使两个节点收到相同事件,也只有取得当前所有权的运行可以继续。

服务端清理器会扫描心跳过期的成员流,通过包含 runId 和过期时间的条件更新回收所有权,再沿正常退出路径标记失败并通知 Lead。服务重启时也会释放旧流并从持久团队状态恢复可继续的成员。事件总线负责传递变化,正确性则由最新快照、条件领取和运行所有权共同保证,不依赖消息只投递一次。

每次成员运行都会记录触发原因、结束方式、步骤数和 token 用量。并行因此是可审计的资源,而不是无法归因的一组后台调用。

系统保证与责任边界

aibuddy 可以保证任务依赖经过校验、协调状态可恢复、消息先于唤醒持久化、同一任务通过条件领取收敛,并保留修订与运行记录。它不能自动判断任务拆分是否合理,也不能阻止两个成员被要求修改同一文件,更不能替 Lead 完成最终验收。

引入多 Agent 前仍需明确三件事:每个分支是否拥有独立信息或动作,交付是否可以单独检查,以及失败或结果冲突时由谁收敛。缺少这些边界时,并行通常只会放大上下文、冲突和成本。

实现锚点

设计职责对应模块
一次性子 Agent 的隔离运行与结果投影task.tool
团队工具协议与角色约束team.tool
持久成员、任务、消息与运行记录TeamRepository
DAG 校验、条件领取与版本化交付TeamCoordinator
基于最新快照的唤醒决策team-graph / team-wake-router
成员运行、心跳与恢复team-execution / team-member-reaper

相关阅读

这页有帮助吗?