首页 > AI教程 >多Agent协作与通信:MessageBus最小实现

多Agent协作与通信:MessageBus最小实现

来源:互联网 2026-07-07 06:33:06

如果已经尝试过“单 Agent + 工具循环”编程模式,大概率会遇到一个尴尬场景:模型扫描代码仓库、读了一大段测试用例后,主对话直接被工具输出的信息塞满;想要一边规划,一边派人手查阅文档,却只能串行等待 subagent 完成;后台任务明明完成了,还得手动将结果粘贴回主对话——这种效率明显不够理想。

如果已经尝试过“单 Agent + 工具循环”编程模式,大概率会遇到一个尴尬场景:模型扫描代码仓库、读了一大段测试用例后,主对话直接被工具输出的信息塞满;想要一边规划,一边派人手查阅文档,却只能串行等待 subagent 完成;后台任务明明完成了,还得手动将结果粘贴回主对话——这种效率明显不够理想。

多Agent协作与通信:MessageBus最小实现

长期稳定更新的攒劲资源: >>>点此立即查看<<<

Agent Teams 的设计思路很直接:一个 Lead 负责统筹调度,Teammate 在独立线程里运行自己的循环,彼此通过 MessageBus 互相传话;Lead 通过 inbox 注入,将队友的结果接入自己的主上下文。一句话总结:谁干活,谁负责沟通,各行其道。

先来看一个对比。

一、与同步 Subagent 的区别

很多教学示例中,subagent 都是这样运行的:Lead 调用 task 工具 → 等待 subagent 完成(此处阻塞) → 整段历史作为 tool_result 塞回 Lead。处理简单任务尚可,任务一复杂就会明显感到“等得心焦”——Lead 无法一边思考下一步,一边让队友去查资料。

Agent Teams 换了一种思路:Lead 调用 spawn_teammate 时不会阻塞。后台线程直接启动 teammate_loop(不阻塞),Lead 可以继续对话或做其他事。Teammate 完成后通过 BUS.send 将结果发往 Lead 的 inbox,后台 queue_processor 检测到 inbox 有消息后,自动唤醒 Lead 的 agent_loop。Teammate 不再是工具返回的临时变量,而是真正在后台运行的工作者。

二、三张图看懂架构

1. 三条事件流,共用一个 Lead

① 用户输入 → history → agent_loop
② Cron 触发 → _queue → inject → agent_loop
③ Teammate 回复 → inbox → inject → agent_loop

Cron 和 Teammate 都不会直接调用模型“乱入”,而是被打包成外部事件,由后台 queue_processor 抢锁后统一交给 Lead 的 agent_loop 处理。这种机制是成熟 Agent Runtime 的常见形态,对教学理解很有帮助。

2. Lead / MessageBus / Teammate

Lead agent loop                   MessageBus                    Teammate loop
+----------------+              +-----------+                 +-------------+
| prompt + tools  | --spawn----->| .jsonl   | <---send---- | own history   |
| inject inbox    | <---send------ | 邮箱      | ---inbox---> | own tools     |
+----------------+              +-----------+                 +-------------+

3. 关键设计:共享磁盘,隔离上下文

两个关键点值得留意:

  • 共享工作目录:Lead 和 Teammate 挂载同一个 bash 环境,读写相同文件(教学版未做权限隔离,但思路清晰)。
  • 隔离上下文:Lead 与 Teammate 不共享 messages 列表。队友读取的文件、执行的命令都保留在它自己的上下文里;Lead 最终只看到 inbox 中的结果。

换言之,队友完成工作后只向 Lead 提交一份最终“报告”,不会将中间的大量调试信息一并塞入。

三、MessageBus:用文件充当邮箱(教学版)

生产环境中,MessageBus 通常对应 Redis、Kafka 或数据库消息队列。但教学代码为了清晰展示机制,直接为每个 Agent 使用一个 JSONL 文件模拟邮箱,效果毫不含糊。

目录结构如下:

.mailboxes/
lead.jsonl
reviewer.jsonl

send() 操作是向目标文件追加一行 JSON:

{"from": "reviewer","to": "lead","content": "Parser looks good","type": "result","ts": 1779780000.0}

read_inbox() 则直接读取并删除文件——消费式操作,确保同一行消息不会重复注入。简单直接,但足以说明核心逻辑。

四、Lead 新增三个“团队工具”

工具作用
spawn_teammate按 name / role / prompt 启动后台队友
send_message向指定 agent 发送消息(队友之间也可互通)
check_inbox主动读取 Lead 邮箱(自动注入时可不调用)

spawn_teammate 底层是一个守护线程:

threading.Thread(
    target=teammate_loop,
    args=(client, model_name, name, role, prompt),
    daemon=True,
).start()

Lead 立即获得“已启动”信息,不会被卡在队友的多轮工具循环中。

五、Teammate 的运行规则:刻意限制

Teammate 拥有自己的 system prompt 和 messages,入口任务来自 Lead 的 prompt。教学版工具白名单如下:

  • 可用:bash、read_file、write_file、edit_file、send_message
  • 不可用:spawn_teammate、schedule_cron(避免队友再派生队友,导致复杂度失控)

轮数上限锁定为 10 轮工具循环,防止后台线程无限消耗 token。任务结束(无论成功或失败)都会通过 BUS.send 将结果发回 Lead,然后从 active_teammates 中注销。相当于一个人默默完成工作,提交报告后下线。

六、Inbox Injection:为何伪装成 user 消息?

Lead 每轮调用模型前执行 inject_inbox_messages(messages),即读取 lead.jsonl → 删除文件 → 追加一条 user 消息。注入内容大致如下:

[reviewer:result] queue_processor 会监听外部事件并安全唤醒 Lead……

有人可能会问:为什么一定要使用 role: user?

原因很简单:对于 Agent Loop 而言,inbox、cron 触发、用户输入都是“外部世界发来的新事件”。模型下一轮统一按“用户侧输入”处理,无需为每种事件单独设计 role。Cron 触发同样适用,只是用 包裹。这种做法使系统统一、实现简单,且后续扩展事件类型时无需修改核心 loop。

七、Queue Processor:cron 与 inbox 共享一个唤醒器

上一篇介绍 cron 时,后台线程只监控定时队列。本版扩大了条件:判断 SCHEDULER 是否有待执行任务,或者 BUS 的 lead 邮箱是否有新消息。两者都没有则继续休眠;存在任一条件时,尝试非阻塞获取 agent_lock,获取成功则运行一轮 agent_loop(history)。

agent_lock 解决了一个现实问题:用户正在终端输入时,后台不能同时修改同一份 history。若拿不到锁则 0.2 秒后重试,避免数据冲突。

八、与定时任务如何整合?

这里并未替换掉 cron,而是将两者合并到同一套“外部事件”模型中:

cron 触发 → tick 入队 → inject_cron_jobs → 
队友完成 → send 到 lead → inject_inbox_messages → 
  ↓
queue_processor → agent_loop → 模型 + 工具

持久化方面,cron 的 durable=True 将任务写入 .scheduled_tasks.json,重启后通过 load() 恢复;已到点但未消费的队列仍在内存中,进程终止后丢失——这是教学版本的边界。

九、本地运行:一句命令启动全队

环境变量只需一个 .env 文件:

OPENAI_BASE_URL
OPENAI_API_KEY
MODEL_NAME

在仓库根目录执行:

python3 harness_agent/09_agent_teams.py

推荐直接复制以下指令到终端:

启动一个 teammate,名字叫 reviewer,角色是 code reviewer。让它阅读 harness_agent/09_agent_teams.py,用几句话说明 MessageBus 怎么工作。

预期效果:

  1. Lead 调用 spawn_teammate,终端打印 [teammate] reviewer spawned;
  2. 可继续输入其他指令,或等待;
  3. reviewer 完成后终端显示 [bus] reviewer -> lead,[queue processor] delivering external work;
  4. Lead 被自动唤醒,根据 inbox 内容回复。

全程无需手动拷贝结果,只需编写任务 prompt,系统自动流转。

十、教学版刻意省略的内容(阅读代码时的预期)

简化点真实系统常见补充
文件 JSONL 邮箱MQ / DB / gRPC
单进程锁分布式锁、ack、重试
Teammate 最多 10 轮长期 worker、idle 唤醒
共享工作目录沙箱、per-agent 权限
无取消/超时/成本上限lifecycle、budget、审计

了解这些边界,才能清晰规划下一版本的发展方向。

十一、带走三句话

  1. 多 Agent 不等于多个模型随意调用——必须存在消息边界(MessageBus)和主 loop 串行消费(queue processor + lock)。
  2. 协作依靠异步,隔离依靠独立 messages——Lead 不会被队友的工具轨迹淹没。
  3. Cron、用户输入、队友回复——形态不同,本质都是“外部事件注入主 loop”。

从单人工作到团队分工,是 Coding Agent 走向工程化协作的第一步。后续可以叠加权限管理、结构化 schema、队友生命周期管理——但邮箱 + 注入 + 后台唤醒这条骨架,已足以支撑第一版运行。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备14008430号-1 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。