上一篇留下的问题
上一篇讲了 AgentTeams 的设计动机:多个 agent 并行协作,协调者负责分发任务和收集结果。
但有一个细节没有展开:协调者怎么知道某个成员 agent 已经收到并处理了它发出的任务消息?
这个问题在单 agent 里根本不存在。主 agent 调用一个工具,工具执行完就返回结果,一来一去,没有"消息在路上"的状态。
但在多 agent 系统里,情况完全不同。消息发出去之后,可能发生很多事:
- 成员 agent 还没启动,消息堆在队列里
- 成员 agent 收到了,但还在处理
- 成员 agent 处理完了,但结果还没被协调者读取
- 成员 agent 崩了,消息永远不会被处理
如果不对这些状态进行追踪,协调者就不知道该等还是该重发,整个协作就乱了。
这就是 消息 ACK(Acknowledgement,确认应答)机制存在的原因。
结论先说
AgentTeams 的消息协议围绕三个核心概念设计:
| 概念 | 作用 |
|---|---|
| SendMessage 工具 | agent 之间发送消息的唯一入口 |
| ACK 三态 | 追踪每条消息的生命周期:pending → delivered → processed |
| TeamStatus 工具 | 查询团队和消息的当前状态 |
三态状态机保证了协调者随时能知道"我发出的消息,现在到哪一步了"。
一、为什么需要 ACK?
先用一个生活类比解释 ACK 是什么。
想象你是一个项目经理,你给三个程序员分配了任务,用微信发了消息。你怎么知道任务被接受并开始执行了?
- 如果对方只是看到了你的消息,那叫"已读"
- 如果对方回复确认了,那叫"已确认接收"(delivered)
- 如果对方完成了任务并汇报,那才叫"已处理完毕"(processed)
如果对方既没有已读也没有回复,你需要判断:是没看到?是看到了没回复?还是手机没电关机了?
ACK 机制就是把这些模糊的中间状态变成确定的、可查询的状态。
在 AgentTeams 里,每条消息都有这三个状态:
scss
pending
│ (消息已发出,等待成员 agent 接收)
▼
delivered
│ (成员 agent 已接收,正在处理)
▼
processed
(成员 agent 已处理完毕,结果可供读取)
二、SendMessage:发消息的唯一入口
在 AgentTeams 里,agent 之间发消息只能通过 SendMessage 工具。
bash
协调者 agent 调用 SendMessage:
- to: "member_agent_2" # 收件人
- content: "请重构 utils.py" # 消息内容
- message_type: "task" # 消息类型
SendMessage 不是简单地把字符串传过去。它做了几件事:
1. 把消息写入持久化存储
消息不是直接发送到对方 agent 的内存里,而是先写到一个持久化的"消息队列"中。这样即使成员 agent 还没启动,消息也不会丢失。
2. 给消息分配一个唯一 ID 并设置初始状态
每条消息创建时,状态是 pending,并有一个时间戳记录"何时发出"。
3. 返回消息 ID 给协调者
协调者拿到消息 ID 之后,可以用 TeamStatus 来查询这条消息后续的状态变化。
这个设计的好处是:发消息和处理消息是解耦的。协调者发完消息就可以去做别的事,不需要一直等着。
三、ACK 三态的状态转移逻辑
接下来看每个状态是怎么被触发的。
pending → delivered
当成员 agent 的"收件箱"被检查、消息被取出时,状态变为 delivered。
markdown
成员 agent 启动后:
1. 检查自己的"收件箱"(从消息队列取未处理消息)
2. 取到消息,立刻把状态从 pending 改为 delivered
3. 开始处理消息内容
这个设计的关键点:状态变更发生在"开始处理"之前,而不是"处理完成之后"。
为什么?因为如果等处理完再改状态,协调者无法区分"成员还没收到"和"成员收到了但还在处理"这两种情况------它们对协调者来说都表现为"消息还是 pending"。
把状态变更提前到"取到消息"的那一刻,协调者就能知道:pending = 消息还没被取到;delivered = 已经在处理了。
delivered → processed
当成员 agent 处理完消息、把结果写入输出区时,状态变为 processed。
markdown
成员 agent 处理完成后:
1. 把处理结果写到指定位置(协调者可以读取的地方)
2. 把消息状态从 delivered 改为 processed
3. 通知协调者(或等协调者主动来查)
processed 状态意味着:结果已经准备好,协调者可以来取了。
四、协调者怎么知道消息处理完了
协调者有两种方式知道消息被处理完了:
方式 1:主动轮询(polling)
协调者定期调用 TeamStatus,查询所有消息的当前状态:
ini
协调者:
while True:
status = TeamStatus(team_id)
if all(msg.status == "processed" for msg in status.messages):
break # 所有消息都处理完了,可以 Collect 了
wait(一段时间)
继续做其他事...
这是最简单的方式,但有轮询延迟------从最后一条消息变成 processed,到协调者发现这个变化,中间有等待时间。
方式 2:TeamCollect 阻塞等待
TeamCollect 工具可以配置等待策略,在所有消息变为 processed 之前保持等待,然后一次性返回所有结果。
ini
协调者:
TeamFanout(tasks=[任务1, 任务2, 任务3]) # 分发任务
results = TeamCollect(timeout=300) # 等待所有结果,最多等5分钟
这是更推荐的方式,协调者不需要自己写轮询循环。
五、消息状态的完整生命周期
把上面的内容串起来,一条消息从发出到被消费的完整过程是这样的:
csharp
协调者发出消息
│
▼
[pending]
消息写入持久化存储
协调者继续做其他事...
│
▼
成员 agent 启动/激活,取到消息
[delivered]
成员 agent 开始执行任务
│
▼
成员 agent 完成任务,写入结果
[processed]
结果等待协调者读取
│
▼
协调者调用 TeamCollect,读取结果
消息生命周期结束
每个状态转移都有明确的触发条件和时间戳记录,所以出了问题,协调者可以通过 TeamStatus 精确定位"卡在哪里了"。
六、边界情况:消息丢失和成员崩溃
到目前为止,我们描述的是"一切顺利"的情况。实际系统里有各种边界情况,AGentTeams 是怎么处理的?
情况 1:成员 agent 取到消息后崩溃
消息状态停留在 delivered,但成员已经挂了。协调者会看到消息一直处于 delivered 状态,超过超时时间之后,可以选择将它重新变为 pending,等待重试。
情况 2:消息发出后成员 agent 一直没启动
消息状态停留在 pending。如果超过了超时时间,协调者可以判定这个成员"不可达",选择换一个成员来处理,或者直接返回部分结果。
情况 3:协调者自己崩溃了
因为消息状态写在持久化存储里,协调者重启后可以重新读取所有消息的状态,继续从上次断掉的地方继续。这是持久化设计的核心价值。
设计亮点
1. 消息持久化,不依赖内存
消息不是靠 Python 对象传递,而是写到持久化存储里。这样任意一方崩溃重启,消息不会丢失。
2. 三态而不是二态
很多简单的消息系统只有"已发送/已完成"两个状态。AgentTeams 多出了 delivered 这个中间状态,让协调者能区分"消息还没被看到"和"消息在处理中",极大地减少了协调者的盲猜。
3. 状态机而非信号
不用"事件通知"(如回调、信号),而是用"可查询的状态"。协调者随时可以主动查状态,不依赖"对方会主动通知我"这个假设。在分布式系统里,主动拉取(pull)比被动通知(push)更可靠。
小结
| 设计选择 | 方案 | 工程价值 |
|---|---|---|
| 消息传递 | SendMessage 工具,消息持久化 | 发消息和处理消息解耦,支持崩溃恢复 |
| 状态追踪 | ACK 三态(pending/delivered/processed) | 协调者随时知道消息到了哪一步 |
| 结果收集 | TeamCollect 阻塞等待 | 协调者不需要自己写轮询循环 |
| 故障处理 | 超时 + 状态回退 | 成员崩溃后可以重新分配任务 |
下一篇讲 TeamFanout 和 TeamCollect------任务是怎么被高效分发出去、结果又是怎么被汇总回来的。
关于本系列的源码
本系列所有分析均基于开源项目 MyCodeAgent。
AgentTeams 的实现已从稳定版本移除,但设计原理在 docs/research-archive.md 和移除计划文档 docs/plans/2026-07-12-lean-runtime/tasks/M2-03-remove-agent-teams.md 中有完整记录。
bash
git clone https://github.com/chendongqi/MyCodeAgent
cd MyCodeAgent
cp .env.example .env
uv sync
uv run python main.py
欢迎访问 PrimeSkills ------ 一个精心策划的 AI Agent 与技能市场,所有内容均经过真实企业级工作流验证。没有噱头,只有真正有效的东西。
更多实用知识和有趣产品,欢迎访问我的个人主页