从零实现自己的agent第六期:Agent Team团队协作

Agent Team:从"派一次差"到"养一支班底"

摘要:Subagent 适合一次性派工:创建独立上下文,完成任务,回传总结,然后销毁。但长期项目常常需要固定角色反复交接,比如 coder 实现、reviewer 审查、再回到 coder 修改。Agent Team 要解决的就是这种持续协作问题:固定队友、文件 inbox、团队状态和总控调度。

标签:Agent Team、多 Agent、协作、消息总线、Python

Subagent 办完即散

前面我们用 subagent 隔离了执行细节。它非常适合一次性任务:读几个文件、抓几个网页、整理一段总结。主 Agent 不需要看所有中间输出,只要最终回禀。

但 subagent 的生命周期很短:

text 复制代码
创建独立上下文 → 执行差事 → 回传总结 → 销毁

这种模式不适合长期交接。比如你希望 alice 负责写代码,bob 负责审查。Alice 写完后,Bob 检查;Bob 提出问题后,Alice 再修改;后面可能还有第二轮、第三轮。这时你需要的不是"一次性工具",而是一支有名字、有角色、有状态的固定班底。

这就是 Agent Team 的出发点。

Agent Team 的最小组成

项目里的团队实现主要在 agent/team.pyagent/tools/team.py

它没有引入数据库,也没有上复杂消息队列,而是用一套最小结构把协作跑起来:

text 复制代码
lead 总控
teammate 固定队友线程
.team/config.json 团队花名册
.team/inbox/*.jsonl 文件收件箱

这四个部分各有职责。

lead 仍然是主 Agent。它理解用户目标,决定召入谁,给谁发消息,什么时候读回禀,最后怎么汇总。

teammate 是固定队友。每个队友在自己的线程里运行,有自己的 system prompt、messages 和工具 registry。办完当前任务后,它不会销毁,而是回到 idle 等下一封消息。

config 是团队花名册,记录成员名字、职司和状态。

inbox 是通信机制。发送消息就是向某个 JSONL 文件追加一行;读取消息就是读完后清空。

MessageBus:文件就是邮箱

MessageBus 是团队通信的底座。

发送消息时,它会校验 sender 和收件人,组装 JSON,再追加到目标 inbox:

python 复制代码
msg = {
    "type": msg_type,
    "from": sender,
    "content": content,
    "timestamp": time.time(),
}

with inbox_path.open("a", encoding="utf-8") as f:
    f.write(json.dumps(msg, ensure_ascii=False) + "\n")

读取消息时,则是 drain 语义:

python 复制代码
lines = inbox_path.read_text(encoding="utf-8").splitlines()
inbox_path.write_text("", encoding="utf-8")

也就是说,读走就清空。

文件 inbox 看起来简单,但非常适合教学。你可以直接打开 .team/inbox/alice.jsonl 看 lead 给 alice 发了什么,也可以看 lead.jsonl 里队友回禀了什么。协作不再藏在模型调用里,而是落到了可观察的文件上。

TeammateManager:身份和状态

固定队友需要被管理。TeammateManager 负责配置、状态、线程启动和队友循环。

团队配置大概长这样:

json 复制代码
{
  "team_name": "default",
  "members": [
    {"name": "alice", "role": "coder", "status": "offline"}
  ]
}

状态分为几类:

text 复制代码
working   当前进程里线程活着,正在工作
idle      当前进程里线程活着,等待消息
offline   config 里有成员,但当前进程没有线程
shutdown  队友已收到退出请求并停止

offline 是一个很真实的状态。Python 线程不会跨进程保存。程序重启后,旧线程已经消失,但 .team/config.json 还在。启动时系统会把遗留的 working/idle 标记为 offline,提醒你需要重新唤回队友。

这比假装队友还在线更可靠。

spawn_teammate:召入或唤回队友

主 Agent 通过 spawn_teammate 召入固定队友。参数包括:

text 复制代码
name   队友名字,例如 alice、reviewer
role   队友职司,例如 coder、reviewer
prompt 第一件差事

如果队友已经在线,新任务会被送入它的 inbox;如果队友离线,则重新启动线程。

队友线程里的 system prompt 会明确告诉它自己的身份:

text 复制代码
你是大内团队中的固定队友,名叫 {name},职司是 {role}。
你不是一次性小太监,而是 agent team 的持久成员。
你可以通过 send_message 给 lead 或其他队友发消息。

这个 prompt 的目的不是营造戏剧效果,而是明确生命周期:teammate 不是一次性函数,办完后要回禀,然后等待下一封 inbox。

队友能用哪些工具

队友拥有基础工具:

python 复制代码
_BASE_TOOL_NAMES = (
    "run_command",
    "web_fetch",
    "load_skill",
    "read_file",
    "write_file",
    "glob",
    "grep",
)

还会加上通信工具:

text 复制代码
send_message
read_inbox

注意,这里没有 dispatch_subagent,也没有 update_todos。固定队友可以做事、可以发消息、可以读自己的 inbox,但它不应该递归调度子代理,也不应该污染主 Agent 的计划状态。

这和 subagent 的白名单设计是一脉相承的:多角色不是放开所有权限,而是更需要清晰边界。

一次完整协作链路

一个最小团队闭环可以这样跑:

text 复制代码
1. 用户交代一个需要实现和审查的任务
2. lead 召入 alice 作为 coder
3. alice 完成实现后 send_message 给 lead
4. lead 读取 inbox,再把结果交给 bob 审查
5. bob 回禀问题或通过意见
6. lead 根据审查结果继续派发或最终总结

这和 subagent 最大的区别在生命周期。Subagent 是一次工具调用;teammate 是固定组织成员。它可以多次收到消息,状态可以从 working 变成 idle,再变回 working。

团队不是多调几次模型

"多 Agent"很容易被讲得很玄,但工程上要警惕一个误区:多个模型调用本身不等于团队。

团队至少要有四件事:

  • 固定身份:谁是 coder,谁是 reviewer;
  • 状态记录:谁在线,谁空闲,谁离线;
  • 通信机制:消息怎么送达,怎么读取;
  • 调度者:谁决定下一步交给谁。

没有这些,模型调用再多,也只是散乱的并发请求。Agent Team 的重点不是模型数量,而是协作协议。

为什么不用共享 history

最直接的多角色方案,是把所有成员消息塞进同一个 history。这样简单,但很快会乱。

Alice 的中间过程、Bob 的审查意见、lead 的调度指令会混在一起。每个成员都看到不该看的细节,上下文也会迅速膨胀。

文件 inbox 的好处是通信显式化。队友不是天然共享一切,而是通过 send_message 把关键结果发出去;接收方通过 read_inbox 获取消息。这个模型更接近真实团队:每个人有自己的工作上下文,通过消息交接必要信息。

底层以后可以换成数据库、消息队列或事件流,但语义不会变:

text 复制代码
消息有发送者
消息有接收者
消息有类型
消息可以被读取
成员状态可以被观察

先用 JSONL 文件把语义写清楚,比一开始接复杂基础设施更适合学习。

什么任务适合 Agent Team

Agent Team 适合天然包含角色交接的任务。

例如:

text 复制代码
让 alice 作为 coder 实现一个最小 demo;
让 bob 作为 reviewer 检查实现;
如果 bob 发现问题,把意见转给 alice 修改;
最后由 lead 汇总结果。

这个任务会同时触发召入队友、发送消息、读取 inbox 和状态变化。你可以用 /team 看谁在 working、idle 或 offline,用 /inbox 查看 lead 收到的回禀。

如果任务只是一次性查资料,subagent 更轻。只有当任务需要固定角色、多轮交接、持续等待消息时,Agent Team 才真正体现价值。

Agent Team 的成本

团队协作带来能力,也带来成本。每个 teammate 都有自己的模型调用、上下文和工具执行。队友越多,调度越复杂,消息也越多。如果只是一个简单问题,开团队反而浪费。

所以使用 Agent Team 前,可以先问三个问题:

text 复制代码
这个任务是否需要固定角色?
这些角色是否需要多轮交接?
中间结果是否需要被保留下来等待后续消息?

如果答案是否定的,普通工具或 subagent 就够了。如果答案是肯定的,Team 才有意义。

这也是多 Agent 系统很容易被误用的地方。不是角色越多越高级,而是角色边界越清楚越可靠。一个清晰的 coder + reviewer,往往比五个职责重叠的"专家"更好用。

inbox 模型的好处

文件 inbox 看起来朴素,但它解决了一个关键问题:消息传递是显式的。

在共享 history 模式下,所有人都读同一本流水账。信息当然完整,但也嘈杂。固定队友可能看到不相关的中间过程,甚至被其他角色的指令干扰。

inbox 模型则更像现实协作。lead 把需要 alice 处理的消息发给 alice,把需要 bob 审查的消息发给 bob。每个队友只处理送到自己 inbox 的内容,办完后再回禀 lead。

这种显式通信还有一个好处:可调试。你可以打开 JSONL 文件,看到消息是谁发的、发给谁、内容是什么、时间是什么。系统出了问题时,不必只靠模型总结来猜。

自己动手验证

一个适合验证团队协作的任务是:

text 复制代码
召入 alice 作为 coder,写一个最小函数;
召入 bob 作为 reviewer,检查这个函数;
如果 bob 发现问题,把意见转给 alice;
最后由 lead 汇总实现和审查结果。

观察几个点:

  • .team/config.json 是否出现 alice 和 bob;
  • /team 是否能看到 working、idle 或 offline;
  • .team/inbox/lead.jsonl 是否收到队友回禀;
  • bob 的审查意见是否能再次转给 alice。

如果这些都成立,说明这个系统已经不是单纯多次调用模型,而是具备了最小组织结构。

和真实团队一样,角色要少而清楚

做 Agent Team 时,最常见的冲动是创建很多角色:架构师、开发、测试、审查、文档、产品、研究员。听起来很完整,但实际运行时很容易变成调度噪声。

角色越多,lead 越需要判断谁该处理什么;消息越多,队友越容易收到和自己无关的信息;上下文越分散,最终结论越需要额外汇总。

更稳的做法是从两个固定角色开始:一个负责执行,一个负责审查。等这个闭环稳定,再考虑加入第三个角色。团队不是角色名称越多越专业,而是每个角色的职责边界越清楚越可靠。

团队状态为什么要落盘

如果 teammate 的状态只存在内存里,进程一停,团队就失忆了。对于一次性任务这没关系,但持续协作需要跨轮次接住上下文。

.team/config.json 和 JSONL inbox 的意义就在这里:它们让团队协作从"当前进程里的几次调用"变成"可以被恢复的工作流"。你能打开文件看到 alice 是否 idle,bob 是否刚收到消息,也能追溯某个结论是从哪封消息传过来的。

这对调试尤其重要。多 Agent 系统最怕"看起来大家都在干活,但不知道信息怎么流动"。落盘后的 inbox 把消息流显式化:谁发给谁、什么时候发、内容是什么,都有记录。

协作闭环比自动化表演更重要

一个团队系统不需要一开始就很热闹。真正值得关注的是闭环是否成立。

lead 能不能把任务拆给合适队友;队友能不能在自己的工具边界内完成工作;完成后能不能把结果发回;另一名队友能不能基于这条消息继续处理;最后 lead 能不能汇总状态并给出可信结论。

只要这个闭环稳定,系统就有扩展空间。否则再多角色、再多并发、再复杂的 prompt,都只是让运行过程更难解释。

inbox 不是聊天室

文件 inbox 的目标不是让所有队友随时闲聊,而是让关键交接被记录。消息应该尽量短、具体、可执行:完成了什么,发现了什么,需要谁继续做什么。

如果 inbox 里塞满寒暄、重复背景和大段无关日志,团队很快会退化成另一个拥挤的 history。好的消息传递应该像工程交接单:接收者打开后,马上知道自己要判断什么、执行什么、回禀什么。

小结

Agent Team 解决的是持续协作问题。

Subagent 适合"派一次差":独立上下文,办完回传,随即销毁。Agent Team 适合"养一支班底":固定身份,记录状态,通过 inbox 交换消息,办完后继续等待下一封任务。

到这里,一个从零实现的 Agent 已经具备了更完整的形态:能调用工具,能保存记忆,能维护计划,能把局部细节交给子代理,也能组织固定队友协作。真正的 Agent 工程,不只是让模型更会说话,而是让模型进入一套可观察、可约束、可持续推进任务的系统。


视频与源码

如果你想看完整演示,可以在主页的《从零手搓 Agent》合集里按顺序观看视频版:

文章里的示例代码和完整项目也放在这里:

我会持续更新 Agent 教学与实战内容。觉得有用的话,欢迎给项目点个 Star ⭐,也谢谢你一路看到这里。

相关推荐
o_insist1 小时前
everything-claude-code 在 Codex 的应用:不要照搬全家桶,而是做一套更聪明的增强层
人工智能·ai编程·vibecoding
_大学牲1 小时前
从零实现自己的agent第一期:什么是agent
github·agent·ai编程
_大学牲1 小时前
从零实现自己的agent第二期: 百行代码从零手搓agent
github·agent·ai编程
正旺单片机1 小时前
claude code 笔记
人工智能·ai编程
码码哈哈0.02 小时前
20260517 最新官网版本Codex 下载
ai编程
程序员柒叔2 小时前
OpenCode 一周动态-2026-W20
人工智能·github·copilot·agent·opencode
Hello_Embed2 小时前
USB 学习指南+软硬件框架
网络·笔记·stm32·嵌入式·ai编程
HIT_Weston2 小时前
85、【Agent】【OpenCode】bash 工具提示词(HEREDOC)
人工智能·agent·opencode