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 调用时,框架拦截并处理。