OpenClaw 多 Agent 通信机制解析:sessions_spawn 与 sessions_send

引言:Agent 之间如何"对话"?

想象你是一个项目经理(主 Agent),需要完成一个复杂项目。你有两种协调方式:

  1. 雇佣新员工完成任务(sessions_spawn):招募专家,分配任务,完成后自动提交报告
  2. 与现有同事实时沟通(sessions_send):向在职同事发消息,进行多轮讨论

OpenClaw 的多 Agent 系统就是基于这两个核心工具设计的。本文将解析它们的工作机制 和设计哲学。


一、核心概念:两种通信模式

1.1 sessions_spawn:创建新的 Agent 实例

typescript 复制代码
sessions_spawn({
  agent: "code-reviewer",      // 要启动的 Agent
  task: "审查 PR #123",        // 任务描述
  mode: "run",                 // run=一次性, session=持久化
  thread: false                // 是否绑定到消息线程
})

本质:Fork 一个新进程

  • 创建独立的会话和执行环境
  • 完成后自动推送结果给父 Agent
  • 用户默认看不到子 Agent 的执行过程

1.2 sessions_send:向现有会话发送消息

typescript 复制代码
sessions_send({
  sessionKey: "agent:code-reviewer:subagent-abc",
  message: "能再检查一下安全性吗?",
  timeoutSeconds: 30           // 等待回复时间
})

本质:进程间通信(IPC)

  • 向已存在的会话发送消息
  • 可同步等待回复
  • 支持多轮协商(最多 5 轮 ping-pong)

二、sessions_spawn 深度解析

2.1 完整执行流程:10 个阶段

css 复制代码
用户请求 → Main Agent → 调用 sessions_spawn
  ↓
[1. 权限验证] → 检查深度、并发数、白名单
  ↓
[2. 会话创建] → 生成唯一 session key
  ↓
[3. 线程绑定] → (可选) 绑定到 Discord/Slack 线程
  ↓
[4. 附件处理] → 快照传递附件内容
  ↓
[5. 系统提示] → 注入任务上下文和能力说明
  ↓
[6. 工作目录] → 继承或使用目标 Agent 配置
  ↓
[7. Agent 启动] → 通过 Gateway RPC 启动
  ↓
[8. 运行注册] → 记录到 SubagentRegistry
  ↓
[9. 钩子触发] → 通知插件(如 Discord)
  ↓
[10. 结果返回] → 返回 childSessionKey 给父 Agent

2.2 关键设计:三层安全防护

约束类型 默认值 作用
最大递归深度 1 层 防止无限递归
最大子进程数 5 个/会话 防止资源耗尽
白名单机制 需配置 跨 Agent 权限控制

配置示例:

json5 复制代码
{
  agents: {
    list: [
      {
        id: "main",
        subagents: {
          allowAgents: ["code-reviewer", "doc-writer"]  // 白名单
        }
      }
    ]
  }
}

2.3 会话键(Session Key)的设计

ruby 复制代码
主 Agent:   agent:main:main
子 Agent:   agent:main:subagent:<uuid>
孙 Agent:   agent:main:subagent:<uuid>:subagent:<uuid>

为什么用 UUID?

  • 全局唯一(跨机器、跨时间)
  • 包含 Agent ID,便于路由
  • 层次化结构,可追溯父子关系

2.4 mode: "run" vs "session"

特性 mode="run" mode="session"
生命周期 一次性,完成即删除 持久化,等待后续消息
线程绑定 不支持 必需(thread=true)
用户可见性 ❌ 完全不可见 ✅ 在线程中可见
适用场景 后台数据处理 多轮对话、代码审查

实际对比:

mode="run" 的场景(用户看不到)

css 复制代码
用户: "分析这个日志"
Main Agent: "正在分析..."
  → sessions_spawn({ agent: "analyzer", mode: "run" })
  → [analyzer 后台执行,用户看不到]
  → 完成后推送结果给 Main Agent
Main Agent: "分析完成,发现 3 个错误..."

mode="session" 的场景(用户可见)

php 复制代码
用户: "审查这段代码"
Main Agent: "已启动审查"
  → sessions_spawn({
       agent: "reviewer",
       mode: "session",
       thread: true
     })
  → Discord 创建线程 "Code Review"

用户(在线程中): "第 42 行有问题吗?"
Reviewer Agent: "是的,这里有空指针风险..."

用户: "如何修复?"
Reviewer Agent: "可以使用 Optional..."

2.5 推送式结果通知:为什么不用轮询?

轮询方案的成本:

ini 复制代码
假设子任务运行 30 秒,每秒轮询 1 次
→ 30 次查询 × 500 tokens = 15,000 tokens 浪费!

OpenClaw 的推送方案:

ini 复制代码
子 Agent 完成 → 结果冻结到 SubagentRegistry
  ↓
后台 Sweeper(1-8 秒检查一次)
  ↓
自动推送到父 Agent 会话(deliver=false)
  ↓
父 Agent 接收内部消息:
  [Subagent Completion]
  Status: ok
  Result: <<<分析完成,发现 3 个错误...>>>

重试机制:

  • 首次失败:5 秒后重试
  • 二次失败:10 秒后重试
  • 三次失败:20 秒后重试
  • 超过 3 次:标记失败

三、sessions_send 深度解析

3.1 完整执行流程

css 复制代码
Agent A 调用 sessions_send
  ↓
[1. 目标解析] → 通过 sessionKey 或 label 查找
  ↓
[2. 权限检查] → A2A 策略 + 沙箱限制
  ↓
[3. 消息投递] → 启动目标 Agent
  ↓
[4. 等待回复] → (可选) 同步等待
  ↓
[5. A2A 协商] → 多轮 ping-pong(最多 5 轮)
  ↓
[6. 最终通知] → 投递到原始频道

3.2 A2A 多轮协商流程

java 复制代码
Agent A (requester)          Agent B (target)
    │
    ├─ "请格式化代码" ──────→   │
    │                          ├─ "需要哪种风格?"
    │  ← ───────────────────   │
    │
    ├─ "使用 Prettier" ─────→   │
    │                          ├─ "完成了"
    │  ← ───────────────────   │
    │
    ├─ REPLY_SKIP ─────────→   │ (结束协商)
    │
    │                          ├─ 最终通知
    │  ← ───────────────────   │
    │
    └─ 投递到用户频道 ────────→  User
       "✅ 代码已格式化"

协商控制:

  • 最多 5 轮(可配置)
  • 任一方回复 REPLY_SKIP_TOKEN 结束
  • 最终可回复 ANNOUNCE_SKIP_TOKEN 保持沉默

3.3 两种使用模式

模式 1:同步等待回复(timeoutSeconds > 0)

typescript 复制代码
const result = await sessions_send({
  sessionKey: "agent:formatter:session-123",
  message: "格式化这段代码",
  timeoutSeconds: 30  // 等待 30 秒
});

console.log(result.reply);  // 同步获得回复
// 后台继续进行 A2A 协商流程

模式 2:异步投递(timeoutSeconds = 0)

typescript 复制代码
sessions_send({
  sessionKey: "agent:formatter:session-123",
  message: "格式化代码",
  timeoutSeconds: 0  // 立即返回
});
// 后台进行 A2A 协商,最终结果投递到频道

四、两者的协作:设计模式

4.1 Fork-Join(并行处理)

scss 复制代码
Main Agent
  ├─ spawn analyzer-1 (处理分片 A)
  ├─ spawn analyzer-2 (处理分片 B)
  └─ spawn analyzer-3 (处理分片 C)
       ↓ ↓ ↓ (并行执行)
  ← announcement 1
  ← announcement 2
  ← announcement 3
  综合结果 → 回复用户

4.2 Master-Worker(主从协作)

typescript 复制代码
// 创建专家 Agent(持久化)
sessions_spawn({
  agent: "security-expert",
  label: "security",
  mode: "session"
});

sessions_spawn({
  agent: "performance-expert",
  label: "performance",
  mode: "session"
});

// 主 Agent 向专家提问
const security = await sessions_send({
  label: "security",
  message: "这段代码有安全风险吗?"
});

const performance = await sessions_send({
  label: "performance",
  message: "性能瓶颈在哪?"
});

// 综合专家意见
return synthesize(security, performance);

4.3 Pipeline(流水线)

scss 复制代码
PDF → Extractor → 原始文本 → Cleaner → 清洁文本 → Summarizer → 摘要
      (spawn)    (announce) (spawn)   (announce)  (spawn)      (announce)

五、关键设计决策

5.1 为什么 mode="session" 需要 thread=true?

问题场景:

arduino 复制代码
mode="session" + thread=false
→ 子 Agent 会话保持打开
→ 用户发送后续消息 "继续"
→ 消息去哪里?❌ 无法路由

解决方案:强制 thread=true

ini 复制代码
mode="session" + thread=true
→ Discord 创建线程,绑定到子 Agent
→ 用户在线程中的消息自动路由 ✓

5.2 为什么附件是快照传递?

方式 优点 缺点 采用
引用传递 节省存储 父删除,子引用失效 ❌
快照传递 独立生命周期 占用更多存储 ✅

快照传递的优势:

css 复制代码
Main Agent 传递附件 → 子 Agent 获得完整副本
→ Main Agent 清理 → 子 Agent 仍可访问 ✓

5.3 为什么跨 Agent 使用目标工作目录?

markdown 复制代码
Main Agent (workspace: /project/main)
  ├─ 同类型子 Agent → 继承 /project/main ✓
  └─ 跨 Agent 子 Agent (code-reviewer)
     → 使用 /project/reviews ✓

原因:
1. 每个 Agent 有自己的工作约定
2. 防止权限越界
3. 安全隔离

5.4 用户可见性矩阵

场景 Mode Thread 用户可见性 原因
后台任务 run false ❌ 不可见 deliver=false
持久会话 session true ✅ 在线程中可见 线程绑定
嵌套子 Agent run false ❌ 不可见 父是子 Agent

六、最佳实践

6.1 何时使用 sessions_spawn?

✅ 适合:

  • 后台数据处理(mode="run")
  • 并行任务分解(多个 spawn)
  • 多轮交互(mode="session", thread=true)

❌ 不适合:

  • 简单查询(直接在主 Agent 处理)
  • 需要立即同步回复(用 sessions_send)

6.2 何时使用 sessions_send?

✅ 适合:

  • Agent 间协作
  • 实时反馈循环
  • 多轮协商

❌ 不适合:

  • 创建新任务(用 sessions_spawn)
  • 长时间任务(会超时)

6.3 配置建议

基础配置:

json5 复制代码
{
  agents: {
    defaults: {
      subagents: {
        maxSpawnDepth: 1,          // 一层子 Agent
        maxChildrenPerAgent: 5,    // 最多 5 个并行
        runTimeoutSeconds: 300     // 5 分钟超时
      }
    }
  },
  session: {
    agentToAgent: {
      enabled: true,
      allow: ["*"],                // 允许所有跨 Agent 通信
      maxPingPongTurns: 5
    }
  }
}

高级配置(复杂任务):

json5 复制代码
{
  agents: {
    defaults: {
      subagents: {
        maxSpawnDepth: 2,          // 两层嵌套
        maxChildrenPerAgent: 10,   // 更多并行
        runTimeoutSeconds: 600     // 更长超时
      }
    }
  }
}

七、总结

核心设计原则

原则 实现 收益
推送优于轮询 自动 announcement 零轮询成本
隔离优于共享 独立会话、工作目录 避免冲突
声明优于命令 工具调用 LLM 友好
异步优于同步 后台执行 高并发
快照优于引用 附件复制 独立生命周期

适用场景

场景 工具 模式
后台任务处理 sessions_spawn mode: "run"
并行数据分析 sessions_spawn mode: "run"
多轮代码审查 sessions_spawn mode: "session", thread: true
Agent 间协作 sessions_send timeoutSeconds: 30
实时问答 sessions_send timeoutSeconds: 15

技术创新

  1. 推送式通知:零轮询成本,实时响应
  2. 多轮 A2A 协商:Agent 间智能对话
  3. 层次化权限:深度限制、白名单、沙箱
  4. 线程绑定:持久化会话自动路由
  5. 结果冻结:网络故障重试不丢失

OpenClaw 的多 Agent 通信机制不仅适用于代码助手,更是构建自主 AI 系统的基础设施。

相关推荐
wangruofeng6 小时前
AI Models 模型目录,跨平台比较大模型 API 价格与上下文
github·aigc·ai编程
程序员海军8 小时前
用了两年多 GPT,我最近开始换模型了,还折腾了个求职避坑 Agent
前端·人工智能·后端
码士集团小青8 小时前
SpringBoot 集成缓存性能之王 Caffeine
spring boot·后端·缓存
孟健9 小时前
一个人做 26 个平台的内容分发:字流 3.0 从选题到复盘的完整链路
aigc·ai编程
excel10 小时前
IndexNow:让搜索引擎更快发现网站更新的主动通知协议
前端·后端·架构
Json____10 小时前
用 FastAPI + Vue3 打造一套完整的在线考试系统:从组卷到阅卷的业务闭环实践
后端·node.js·fastapi·it学习·wwwoop.com
小灰灰搞电子11 小时前
Rust+Slint 实现FTP客户端调试助手源码分享
开发语言·后端·rust
专业程序开发源12 小时前
springboot欧缇蔓月子中心管理系统82697-计算机课程设计、毕业设计
java·spring boot·后端·python·spring·django·课程设计
卷无止境12 小时前
面向arm64桌面客户端开发全景:语言、框架与生态
后端·python
小四的小六12 小时前
一次出站重试风暴的沙箱复盘:重试没退避,Agent 十几分钟烧穿整月额度
aigc·openai·ai编程