👥 从零打造 AI Agent:多 Agent 平台篇(S15-S19)

从一个 Agent 到多个 Agent,从临时工到正式团队,从被动协作到主动工作。


🎬 开场:为什么需要一个 Agent 团队?

现在你的 Agent 已经:

  • ✅ 有了核心循环,会把结果喂回模型
  • ✅ 会用工具,能读写文件、执行命令
  • ✅ 有了安全防护,不会乱删东西
  • ✅ 有了记忆,跨会话也能记住一些事
  • ✅ 能管理任务,能异步执行,能定时触发

但它还是… 一个人在干活。

想象你要盖一栋大楼:

  • 只雇一个工人 → 他要搬砖,要砌墙,要刷漆,要装水管…
  • 项目大了,根本忙不过来
  • 而且他不知道"谁在等谁",经常返工

你的 Agent 也面临同样的问题。


📚 上集回顾:任务运行时

上篇文章我们讲了任务管理能力:

章节 核心问题 解决方案
S12 任务系统 管理复杂项目的依赖关系 任务图 + 自动解锁
S13 后台任务 让慢命令异步执行 后台执行 + 通知队列
S14 定时调度 让时间触发工作 调度器 + 触发器

今天,我们给它加上团队协作的能力,从"一个人干活"变成"多个 Agent 协作"。


👥 S15:Agent 团队 - 长驻的专职队友

🎬 精彩开场:球队的故事

没有团队(只有临时工):

  • 临时找几个人
  • 干完今天的活
  • 明天重新找
  • 每个人都不知道昨天发生了什么

有团队(长期队友):

  • 有固定成员:张三,李四、王五
  • 每个成员都了解团队文化
  • 可以持续积累经验
  • 可以互相配合

Agent 团队就是这样:从"临时工"变成"正式员工",从"一次性委派"变成"长期协作"。

核心问题

之前的 subagent 是一次性的:

  • 创建 → 执行 → 返回摘要 → 消失
  • 适合小任务,不适合长期协作

解决方案

建立长期存在的队友,有名字、有角色、有邮箱、有独立循环。

工作流程

lead(主 Agent)
    |
    +-- spawn alice (coder)  # 派生子队友
    +-- spawn bob (tester)
    |
    +-- send message --> alice inbox
    +-- send message --> bob inbox

alice(子队友)
    |
    +-- 自己的 messages
    +-- 自己的 inbox
    +-- 自己的 agent loop

bob(子队友)
    |
    +-- 自己的 messages
    +-- 自己的 inbox
    +-- 自己的 agent loop

关键数据结构

# 团队成员
TeamMember = {
    "name": "alice",
    "role": "coder",
    "status": "working",
}

# 邮箱消息
Message = {
    "type": "message",
    "from": "lead",
    "content": "请 review 这段代码",
    "timestamp": 1710000000.0,
}

新手最容易踩的4个坑

  1. 把队友当成"名字不同的 subagent" → 如果生命周期还是"执行完就销毁",那不是 teammate
  2. 队友之间共用同一份 messages → 上下文会互相污染
  3. 没有持久名册 → 系统重启后不知道"团队里有谁"
  4. 没有邮箱,靠共享变量直接喊话 → 教学上建议用邮箱,让"队友通信"和"进程内部细节"分开

📜 S16:团队协议 - 共享请求-响应规则

🎬 精彩开场:快递的故事

**没有协议(只有邮箱):

  • A 发送消息:“我寄了一个快递给你”
  • B 收到消息,不知道快递在哪
  • A 也不知道 B 收到没有
  • 双方靠"信任"维持协作

**有协议(结构化消息):

  • A 发送消息:{"type": "寄件请求", "快递单号": "12345", "状态": "pending"}
  • B 回复:{"type": "寄件响应", "快递单号": "12345", "状态": "approved"}
  • 双方都有记录,都知道"这件事现在走到哪一步了"

团队协议就是这样:把协作从"自由聊天"变成"结构化流程",每件事都有编号、状态、可追踪。

核心问题

团队成员之间只能自由聊天:

  • A 说"我完成任务了" → B 不确定这是不是正式通知
  • C 说"好的" → 是同意了还是只是礼貌回复?

协作没有规矩,容易混乱。

解决方案

制定"协议"——结构化的请求-响应模式。

两种协议消息

协议消息
{
    "type": "shutdown_request",
    "from": "lead",
    "to": "alice",
    "request_id": "req_001",  # 关键:请求编号
    "payload": {},
}

请求追踪表
requests = {
    "req_001": {
        "kind": "shutdown",
        "status": "pending",  # pending / approved / rejected
    }
}

两种协议

1. 关机协议

# 发请求
request_shutdown("alice")
    ↓
请求追踪表: {"req_001": {"status": "pending"}}
    ↓
alice 收到请求,可以 approve 或 reject

# 收响应
handle_shutdown_response("req_001", approve=True)
    ↓
请求追踪表: {"req_001": {"status": "approved"}}

2. 计划审批协议

# 发请求
submit_plan("alice", "修改认证模块")
    ↓
lead 可以审批:approve 或 reject

新手最容易踩的4个坑

  1. 没有 request_id → 多个请求同时存在,很快就乱
  2. 收到请求只回自然语言 → 系统需要结构化回复
  3. 没有请求状态表 → 如果不记录 pending/approved/rejected,协议没有真正落地
  4. 把协议消息和普通消息混成一种结构 → 普通消息解决"说了什么",协议消息解决"这件事走到哪一步了"

🤖 S17:自主代理 - 自主认领,自主续跑

🎬 精彩开场:老板与员工的故事

没有自治(纯人工分配):

  • lead 分配任务 → alice 做
  • lead 分配任务 → bob 做
  • lead 很忙,成了瓶颈
  • 5 个队友都在等

有自治(自动认领):

  • 任务板上有一堆任务
  • 队友空闲时自动扫描
  • “任务 4 没人在做,我来做”
  • 不需要 lead 一个个分配

自主代理就是这样:从"被动等待分配"变成"主动去找事做"。

核心问题

团队成员还是被动等待分配:

  • lead 分配任务 → alice 做
  • lead 分配任务 → bob 做
  • lead 很忙,成了瓶颈
  • 5 个队友都在等

解决方案

让空闲的队友自己去找任务。

WORK/IDLE 两个阶段

WORK
    ↓
当前轮工作做完,或者主动进入 idle
    ↓
IDLE(空闲)
    |
    +-- 看邮箱,有新消息 → 回到 WORK
    |
    +-- 看任务板,有 ready task → 认领 → 回到 WORK
    |
    +-- 长时间什么都没有 → shutdown

核心流程

def idle_phase(name: str) -> bool:
    # 1. 先看邮箱
    inbox = bus.read_inbox(name)
    if inbox:
        return True  # 有消息,继续工作
    
    # 2. 扫描任务板
    unclaimed = scan_unclaimed_tasks(role)
    if unclaimed:
        task = unclaimed[0]
        claim_task(task["id"], name, source="auto")  # 自动认领
        return True
    
    # 3. 都没找到,退出
    return False

新手最容易踩的7个坑

  1. 只看 pending,不看 blockedBy → 前置任务没完成,不能认领
  2. 只看状态,不看 claim_role/required_role → 错误的队友可能接走错误的任务
  3. 没有认领锁 → 两个队友可能同时认领同一个任务
  4. 空闲阶段只轮询任务板,不看邮箱 → 队友会错过别人明确发给它的消息
  5. 认领了任务,但没有写 claim event → 你只能看到"任务现在被谁做",却不知道什么时候被拿走的
  6. 队友永远不退出 → 教学版里,长时间无事可做时退出是合理的
  7. 上下文压缩后不重注入身份 → 队友可能"忘记自己是谁"

📁 S18:Worktree 隔离 - 独立目录,独立车道

🎬 精彩开场:装修的故事

没有 Worktree(所有人在同一个房间装修):

  • 木工在锯木头
  • 电工在拉电线
  • 油漆工在刷墙
  • 所有人都挤在一个空间里
  • 木头屑飞到电线里
  • 乱成一团

有 Worktree(每个人在独立房间装修):

  • 木工在 A 房间
  • 电工在 B 房间
  • 油漆工在 C 房间
  • 各自独立工作,互不干扰
  • 完成后汇合验收

Worktree 隔离就是这样:每个任务在独立目录执行,互不干扰。

核心问题

多个任务同时在同一个目录操作:

  • 任务 A 在改 auth.py
  • 任务 B 也在改 auth.py
  • 两个人改的东西打架了
  • 不知道哪个是谁的

解决方案

每个任务在独立目录执行,互不干扰。

通过 task_id 关联

.tasks/task_12.json
{
    "id": 12,
    "subject": "重构认证模块",
    "status": "in_progress",
    "worktree": "auth-refactor"  ← 关联!

.worktrees/index.json
{
    "worktrees": [{
        "name": "auth-refactor",
        "path": ".worktrees/auth-refactor",
        "task_id": 12,  ← 关联!
        "status": "active"
    }]
}

收尾操作

worktree_closeout(
    name="auth-refactor",
    action="keep",  # 或 "remove"
    reason="需要 review",
    complete_task=True
)

新手最容易踩的7个坑

  1. 有 worktree 但命令还在主目录执行 → cwd 没切过去,worktree 形同虚设
  2. 删除 worktree 前不看未提交改动 → 可能丢失工作
  3. 没有显式收尾状态 → 系统不知道"这条车道最后怎么了"
  4. 把 worktree 当成长期垃圾堆 → 如果从不清理,目录会越来越多
  5. 没有事件日志 → 创建失败、删除失败时很难排查
  6. 把 worktree 当成"只是一个 git 小技巧" → 关键的是"把任务和执行目录做显式绑定"
  7. 没有 worktree_state/closeout 显式收尾状态 → 系统只剩下"现在目录还在不在"

🔌 S19:MCP 与插件 - 外部能力总线

🎬 精彩开场:手机与 App Store

没有 MCP(工具都在手机里):

  • 手机自带:电话、短信、相机
  • 想用其他功能?没有!
  • 需要什么?买新手机!

有 App Store(外部能力接入):

  • 手机自带基础功能
  • 想用外卖?去 App Store 下载
  • 想用地图?去 App Store 下载
  • 想用外卖 + 地图 + 支付?去 App Store 下载更多

MCP 就是 AI 世界的"App Store":让外部工具可以像 App 一样接入系统,而不是把所有功能都写死在代码里。

核心问题

工具都写死在主程序里:

  • 想加一个新工具 → 要改主程序
  • 想用外部服务 → 要写一堆集成代码

扩展困难,不够灵活。

解决方案

让外部工具可以像 App 一样"插进来"。

三层架构

LLM
    ↓
asks to call a tool
    ↓
Agent tool router
    |
    +-- native tool → 本地 Python handler
    |
    +-- MCP tool → 外部 MCP server
    ↓
return result

Plugin 配置

{
    "name": "my-db-tools",
    "version": "1.0.0",
    "mcpServers": {
        "postgres": {
            "command": "npx",
            "args": ["-y", "@modelcontextprotocol/server-postgres"]
        }
    }
}

工具前缀规则

mcp__postgres__query      ← postgres server 的 query 工具
mcp__browser__open_tab    ← browser server 的 open_tab 工具

新手最容易踩的3个坑

  1. 把 MCP 当成完全不同的工具系统 → 最终还是要回到同一条控制面
  2. 忽略命名与路由 → 没有统一前缀,系统会乱
  3. 一上来讲太多协议细节 → 主线是"外部工具怎么接进来"

🎯 核心公式总结

多 Agent 平台 = Agent 团队 + 团队协议 + 自主代理 + Worktree 隔离 + MCP/插件
Agent 团队 = 名册 + 邮箱 + 独立循环 + 持久队友
团队协议 = request_id + 请求状态表 + 结构化消息
自主代理 = WORK/IDLE 循环 + 邮箱检查 + 任务扫描 + 安全认领
Worktree 隔离 = 任务与目录绑定 + 进入车道执行 + 收尾状态
MCP = MCPClient + 工具标准化 + 前缀路由 + 统一权限

🔗 从"单打独斗"到"团队协作"

一个人干活(S01-S14)
    ↓
变成团队(S15)
    ↓
制定规矩(S16)
    ↓
让成员主动工作(S17)
    ↓
隔离执行空间(S18)
    ↓
扩展外部能力(S19)
    ↓
= 完整的多 Agent 系统

🎯 一句话带走

记住这句话就够了:多 Agent 平台的核心是"协作与扩展"。从临时 subagent 变成长期 teammate,从自由聊天变成结构化协议,从被动等待变成主动认领,从共享目录变成隔离 worktree,从硬编码工具变成可插拔 MCP。


🎉 总结:完整的 Agent 系统

核心闭环(S01-S06)
    ↓
系统加固(S07-S11)
    ↓
任务运行时(S12-S14)
    ↓
多 Agent 平台(S15-S19)
    ↓
= 完整的 Agent 系统

恭喜你!学完了 Learn Claude Code 的全部内容!

你已经掌握了构建完整 Agent 系统所需的核心能力:

  • ✅ Agent Loop 基础
  • ✅ 工具系统
  • ✅ 规划与记忆
  • ✅ 安全与稳定
  • ✅ 任务管理
  • ✅ 多 Agent 协作

下一步建议:

  1. 阅读源码:https://github.com/anthropics/anthropic-cookbook
  2. 实践项目:尝试构建自己的 Agent 系统
  3. 深入研究:选择感兴趣的章节深入学习

▶️ 相关文章

完整的系列文章:


关注我,一起探索 AI Agent 的世界!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐