07-task-handover.md
6.76 KB
7. Agent 间通讯架构
Agent 子进程之间完全隔离,不直接通讯。所有消息都经主进程路由,所有数据都通过 SQLite 共享。
7.1 核心原则:框架是"神经系统"
每个 Agent 是一个独立的 ACP(Claude Code)子进程。它们之间 不直接通讯。
❌ 不是这样:Agent 之间直连
┌──────┐ ┌──────┐
│Agent A│←──→│Agent B│
└──────┘ └──────┘
✅ 而是这样:所有消息经主进程中转
┌──────┐ ┌────────────┐ ┌──────┐
│Agent A│←──→│ 主进程路由 │←──→│Agent B│
└──────┘ │ (框架层) │ └──────┘
└────────────┘
类比:部门之间不是互相打电话,而是通过公司的 OA 系统发任务、汇报、审批。
7.2 消息类型
| 消息方法 | 方向 | 场景 | 版本 |
|---|---|---|---|
task.assign |
上级 → 下级 | 分派任务 | v1.0 |
task.report |
下级 → 上级 | 汇报结果/进度 | v1.0 |
task.handover |
同级 → 同级 | Pipeline 节点流转 | v1.1 |
task.feedback |
同级 → 同级 | 经验/数据反馈回流 | v1.1 |
cxo.review |
CXO ↔ CXO | 方案审核请求 | v1.2 |
cxo.approve |
CXO → CXO | 审核通过 | v1.2 |
cxo.reject |
CXO → CXO | 审核驳回 | v1.2 |
status.update |
广播 | 状态变更通知 | v1.0 |
status.heartbeat |
下级 → 上级 | 心跳状态上报 | v1.2 |
data.share |
任意 | 共享数据/资源 | v1.2 |
data.request |
任意 | 请求数据/资源 | v1.2 |
7.3 消息流转的完整流程
场景:Master 与用户聊完 → 下达指令给 CEO
Step 1: 用户跟 Master 聊天
用户: "我想做一个 AI 互动短剧平台,主打年轻女性市场"
│
▼ (WebSocket / HTTP)
框架服务器
│
▼ (stdin pipe)
Master ACP 进程
│
│ 根据 agent.md + soul.md 思考:
│ → "用户意图: 做一个面向年轻女性的 AI 短剧平台"
│ → "需要将意图结构化为 Goal,交给 CEO 去战略拆解"
Step 2: Master 调用工具下达指令
Master ACP 输出 (stdout):
{
"jsonrpc": "2.0",
"method": "tool.call",
"params": {
"name": "task.assign",
"args": {
"to": "cxo-ceo-001",
"task": {
"description": "设计 AI 互动短剧平台的完整业务体系",
"goal": {
"target": "Q1 日活 10 万",
"audience": "18-28 岁年轻女性",
"product": "AI 互动短剧,支持用户二改"
},
"priority": "high"
}
}
}
}
Step 3: 框架拦截 → 路由 → 触发 CEO
框架主进程收到 Master 的工具调用:
1. 生成消息 ID,写入 SQLite messages 表
2. 查找 cxo-ceo-001 的 ACP 子进程
├── 如果 CEO 正在运行 → 向 CEO 的 stdin 注入消息
└── 如果 CEO 处于 idle → 启动 CEO 的 ACP 子进程,注入消息
3. 给 Master 返回: "已发送,任务 ID: task-xxx"
Step 4: CEO 收到指令,开始工作
CEO ACP 进程的 stdin 收到:
"[来自 Master 的任务]
设计 AI 互动短剧平台的完整业务体系
目标: Q1 日活 10 万
受众: 18-28 岁年轻女性
产品: AI 互动短剧,支持用户二改"
CEO 根据 agent.md 和 soul.md 推理:
→ "需要 5 个 Role: 编剧、制作、运营、推广、数据"
→ "Pipeline: 选题→剧本→制作→上架→推广→反馈"
CEO 调用工具 (stdout → 框架拦截):
tool_call: role.create({ name: "编剧部", type: "role", ... })
tool_call: role.create({ name: "推广部", type: "role", ... })
tool_call: pipeline.set({ edges: [...] })
框架拦截每个工具调用:
→ AgentScaffold 创建目录
→ AgentRegistry 注册到数据库
→ 启动 ACP 子进程
Step 5: CEO 不等编剧部完成,继续做其他事
CEO 发完 role.create 后继续:
→ 给推广部分派任务
→ 给数据部分派任务
→ 开始自己的 5 分钟心跳循环
编剧部做完后:
→ 编剧部 ACP → (stdout) → 框架 → (stdin) → CEO ACP
→ CEO 收到汇报,评估结果,继续下一步
全程异步。
7.4 三种数据共享方式
| 方式 | 适用场景 | 机制 |
|---|---|---|
| 消息传递 | 任务指令、结果汇报、状态更新 | 主进程路由,payload 携带 JSON |
| SQLite 查询 | 查看全局状态、组织架构、历史任务 | Agent 调用工具(如 org.status),主进程查 SQLite 返回 |
| 文件路径引用 | 剧本、视频、数据报表等大文件 | 消息里传路径,目标 Agent 读取文件 |
消息传递(轻量数据)
{
"method": "task.report",
"params": {
"from": "role-data-001",
"to": "cxo-ceo-001",
"payload": {
"metrics": { "dau": 23000, "retention": 0.42, "conversion": 0.18 },
"insight": "古装题材在 18-25 岁女性中转化率最高 (23%)"
}
}
}
SQLite 查询(全局状态)
CEO 调用: org.status()
↓ 框架主进程查询 SQLite
↓ 返回:
{
"total_agents": 12,
"running": 8,
"pipeline": "选题→剧本→制作→上架→推广→反馈",
"goal_progress": 0.23,
"recent_tasks": [...]
}
文件路径引用(大文件)
编剧部完成剧本 → 流转到制作部:
{
"method": "task.handover",
"params": {
"from": "role-dramatist-001",
"to": "role-producer-001",
"payload": {
"type": "script",
"path": "data/agents/role-dramatist-001/workspace/assets/drama-ep01.md",
"summary": "都市爱情第1集,含3个互动分支"
}
}
}
制作部的 ACP 进程根据 path 读取文件 → 开始制作
(框架授予制作部对该路径的只读权限)
7.5 通讯的设计约束
| 约束 | 原因 |
|---|---|
| 子进程之间不直连 | 隔离性——一个 Agent 崩溃不影响其他 Agent |
| 所有通讯经主进程 | 可审计、可持久化、可限流、可切断 |
| 大数据传路径不传内容 | 保持消息体轻量,避免主进程成为瓶颈 |
| Agent 不感知并发 | 每个 Agent 以为自己是唯一的,框架在背后调度 |
task.assign/role.create这些工具不是 Agent 自己实现的,是框架暴露给 Agent 的。 Agent 在 agent.md 里写了"可用工具: task.assign",框架在启动 ACP 时注册这些工具。 当 Agent 调用时,框架拦截并处理。