"Agent 间通信"
龙虾学堂2026年5月7日
"掌握 OpenClaw 的 Agent 间通信机制,深入理解 sessions_send 工具的使用场景与最佳实践"
Agent 间通信
本文聚焦:Agent 间通信机制 + sessions_send 工具详解
知识点 1:为什么需要 Agent 间通信
从"派工"到"协作"
在 什么是子智能体 中,我们学习了如何用 sessions_spawn 创建子智能体。但仅有"派工"还不够——真正的多智能体系统需要双向通信。
想象一下这个场景:
- 主智能体派生了一个子智能体去分析代码
- 分析进行到一半,子智能体发现了一个关键问题
- 它需要立即通知主智能体,而不是等任务完成才汇报
- 主智能体收到消息后,可能需要调整策略或派生新的子智能体
这就是 Agent 间通信 的价值——让多个智能体能够实时协作、动态调整。
典型应用场景
1. 进度汇报与状态同步
子智能体: "已完成 50% 的文件分析,预计还需 2 分钟"
主智能体: "收到,继续执行"
2. 动态任务调整
子智能体: "发现新问题类型,建议增加检查项"
主智能体: "同意,请同时检查 X 和 Y"
3. 资源协调
子智能体 A: "我需要访问数据库,但连接池已满"
主智能体: "子智能体 B 马上完成,请等待"
4. 结果聚合请求
主智能体: "所有子智能体,请立即汇报当前进度"
子智能体 A/B/C: 各自返回状态
通信 vs 派工的区别
| 特性 | sessions_spawn(派工) | sessions_send(通信) |
|---|---|---|
| 方向 | 主 → 子(单向) | 任意方向(双向) |
| 时机 | 创建时指定任务 | 任意时刻发送消息 |
| 目的 | 委派完整任务 | 传递信息/指令 |
| 结果 | 子智能体完成后汇报 | 接收方处理消息 |
| 使用场景 | 启动后台任务 | 运行中协调沟通 |
知识点 2:sessions_send 详解
工具概述
sessions_send 是 OpenClaw 提供的原生工具,用于向指定会话(包括子智能体、其他 Agent 会话)发送消息。
前置条件:
- OpenClaw 版本 >= 0.15.0
- 当前 Agent 配置中包含
sessions_send工具权限- 目标会话必须存在且活跃
完整参数列表
interface SessionsSendParams {
// 会话标识(三选一)
sessionKey?: string; // 完整会话密钥,如 "agent:main:abc123"
label?: string; // 子智能体标签,如 "code-analyzer"
agentId?: string; // Agent ID,发送给该 Agent 的主会话
// 必需参数
message: string; // 要发送的消息内容
// 可选参数
timeoutSeconds?: number; // 等待响应超时(秒),默认 60
}
参数详解
1. 目标会话标识(sessionKey / label / agentId)
方式一:sessionKey(最精确)
await sessions_send({
sessionKey: "agent:main:a1b2c3d4-e5f6-7890-abcd-ef1234567890",
message: "请暂停当前任务"
});
方式二:label(最便捷)
await sessions_send({
label: "code-analyzer", // 对应 sessions_spawn 时设置的 label
message: "进度如何?"
});
方式三:agentId(跨 Agent 通信)
await sessions_send({
agentId: "github-helper", // 发送给名为 github-helper 的 Agent
message: "有新 Issue 需要处理"
});
2. message(必需)
消息内容支持纯文本或结构化指令。建议:
- 清晰明确:说明意图和期望的响应
- 包含上下文:提供必要的背景信息
- 可解析:如果是机器处理,使用结构化格式(JSON、Markdown 列表等)
示例:
{
"label": "data-processor",
"message": `STATUS_CHECK
当前进度:?
预计剩余时间:?
是否需要协助:是/否`
}
3. timeoutSeconds(可选)
等待目标会话响应的超时时间:
- 默认 60 秒
- 设为 0 表示不等待(即发即走)
- 长时间任务可适当延长
使用示例
示例 1:向子智能体发送进度查询
// 主智能体检查子智能体进度
async function checkProgress(subagentLabel) {
const response = await sessions_send({
label: subagentLabel,
message: "请汇报当前进度:已完成百分比、剩余任务、预计完成时间",
timeoutSeconds: 30
});
console.log("子智能体回复:", response);
// 根据回复决定是否调整策略
}
// 使用
await checkProgress("file-analyzer");
示例 2:动态调整子智能体任务
// 主智能体根据新信息调整子智能体任务
async function adjustTask(subagentLabel, newRequirement) {
await sessions_send({
label: subagentLabel,
message: `任务调整通知:
新增要求:${newRequirement}
请在当前分析中加入此项检查
完成后回复确认`
});
}
// 使用
await adjustTask("code-reviewer", "额外检查 SQL 注入风险");
示例 3:广播消息给多个子智能体
// 同时通知所有子智能体
const subagents = ["analyzer-1", "analyzer-2", "analyzer-3"];
async function broadcast(message) {
const promises = subagents.map(label =>
sessions_send({
label,
message,
timeoutSeconds: 0 // 不等待回复,即发即走
})
);
await Promise.all(promises);
console.log("广播完成");
}
// 使用:通知所有子智能体立即停止
await broadcast("紧急:请立即停止当前任务,等待进一步指示");
示例 4:子智能体向主智能体汇报
// 在子智能体代码中,向主智能体发送中间结果
// 注意:子智能体需要知道主会话的 sessionKey 或 label
// 方式:通过环境变量或任务参数传递主会话标识
const parentSessionKey = process.env.PARENT_SESSION_KEY;
await sessions_send({
sessionKey: parentSessionKey,
message: `中间汇报:
发现 3 个潜在问题:
1. 未处理的 Promise rejection
2. 内存泄漏风险
3. 硬编码的 API 密钥
建议立即处理第 3 项`
});
完整实战:主-子协作模式
// ============ 主智能体代码 ============
async function orchestrateAnalysis(projectPath) {
// 1. 派生子智能体
const subagent = await sessions_spawn({
task: `分析 ${projectPath} 的代码质量,
每发现 5 个问题就向我汇报一次,
等待我的指令后再继续`,
label: "quality-analyzer",
mode: "session" // 持久会话,保持通信能力
});
console.log("子智能体已启动,等待首次汇报...");
// 2. 等待并处理子智能体的汇报
// 实际场景中,子智能体会主动调用 sessions_send 向主智能体汇报
// 主智能体通过消息接收或主动查询获取更新
}
// ============ 子智能体代码(在子会话中执行) ============
async function analyzeWithCheckpoints(projectPath, parentSessionKey) {
const files = await getFiles(projectPath);
const issues = [];
for (let i = 0; i < files.length; i++) {
const fileIssues = await analyzeFile(files[i]);
issues.push(...fileIssues);
// 每发现 5 个问题,向主智能体汇报
if (issues.length >= 5) {
await sessions_send({
sessionKey: parentSessionKey,
message: `进度汇报:
已分析 ${i + 1}/${files.length} 个文件
发现问题:${issues.length} 个
是否继续?回复 CONTINUE 或 STOP`
});
// 等待主智能体回复(实际实现需要消息监听机制)
// 这里简化处理
await waitForContinueSignal();
}
}
return issues;
}
实践建议
-
设计清晰的通信协议 定义消息格式和响应规范,例如:
[ACTION] [PARAMETERS] STATUS_CHECK → 返回进度信息 PAUSE → 暂停当前任务 RESUME → 恢复暂停的任务 ABORT → 终止任务 -
合理设置超时
- 查询类消息:30-60 秒
- 控制类消息(暂停/停止):10-30 秒
- 通知类消息(即发即走):0 秒
-
处理通信失败
try { await sessions_send({ label: "worker", message: "status?" }); } catch (error) { if (error.code === "SESSION_NOT_FOUND") { console.log("子智能体已结束,需要重新派生"); } else if (error.code === "TIMEOUT") { console.log("子智能体响应超时,可能正在忙"); } } -
避免过度通信 频繁的消息往返会增加延迟和复杂度。建议:
- 批量汇报:积累一定信息量后再发送
- 异步设计:子智能体自主决策,减少等待
- 心跳机制:定期检查而非持续轮询
-
使用 label 而非 sessionKey sessionKey 包含 UUID,难以记忆和传递。使用 label 更便于管理:
// 好的做法 sessions_send({ label: "doc-analyzer", message: "..." }) // 避免(除非必要) sessions_send({ sessionKey: "agent:main:abc-123-...", message: "..." }) -
注意权限限制
- 子智能体默认可能没有
sessions_send权限 - 需要在 Agent 配置中显式启用
- 跨 Agent 通信需要双方都有相应权限
- 子智能体默认可能没有
常见陷阱
陷阱 1:向不存在的会话发送消息
// ❌ 错误:子智能体已经结束
await sessions_send({
label: "finished-worker", // 这个子智能体已经完成任务并退出
message: "继续工作"
});
// 结果:SESSION_NOT_FOUND 错误
// ✅ 正确:先检查子智能体状态
const subagents = await subagents_list();
if (subagents.some(s => s.label === "finished-worker")) {
await sessions_send({ label: "finished-worker", message: "..." });
}
陷阱 2:消息格式混乱导致误解
// ❌ 错误:模糊的消息
await sessions_send({
label: "worker",
message: "停一下" // 是暂停?还是完全停止?
});
// ✅ 正确:明确的指令
await sessions_send({
label: "worker",
message: `[ACTION: PAUSE]
原因:需要调整参数
操作:暂停当前任务,保持状态
恢复指令:发送 [ACTION: RESUME]`
});
陷阱 3:忽略超时导致阻塞
// ❌ 错误:没有设置超时,可能永远等待
const response = await sessions_send({
label: "busy-worker",
message: "请回复"
// 默认 60 秒,但如果子智能体陷入死循环...
});
// ✅ 正确:设置合理的超时
const response = await sessions_send({
label: "busy-worker",
message: "请回复",
timeoutSeconds: 10 // 10 秒无响应就放弃
});
陷阱 4:在子智能体中错误地获取主会话标识
// ❌ 错误:子智能体无法自动知道主会话的 sessionKey
// 需要通过任务参数或环境变量传递
// ✅ 正确:派生时传递信息
await sessions_spawn({
task: `分析任务...
主会话标识:${currentSessionKey}
完成后向主会话汇报`,
label: "worker"
});
相关阅读
#["subagent"#"sessions_send"#"通信"#"多智能体"]