OpenClaw 多 Agent 架构深度调研
基于 OpenClaw 源码的逐文件深度阅读,系统梳理其多 Agent 设计。
一句话总结
OpenClaw 的多 Agent 系统 = 基于嵌套深度(depth)自动分配角色 + 车道制并发控制 + Push-based 自动汇报。不需要你选模式,系统根据"你在第几层"自动决定你的身份和权限。
一、整体架构
1.1 核心理念
用一句大白话概括:不需要你选角色。谁生了你,你在第几层,系统自动决定你的身份和权限。 没有环境变量开关,没有模式切换。OpenClaw 基于嵌套深度(depth)自动分配角色和工具权限,越往下权限越少,但每一层都能干活。
1.2 架构全景图
┌─────────────────────────────────────────────┐│ Gateway 进程 ││ ┌─────────┐ ┌─────────┐ ┌─────────┐ ││ │ Agent A │ │ Agent B │ │ Agent C │ │ ← 多人格共存│ │ coding │ │ family │ │ default │ ││ └────┬────┘ └────┬────┘ └────┬────┘ ││ │ │ │ ││ ┌────▼────────────────────────────────┐ ││ │ Lane-Based Queue │ ││ │ Main 车道: ████░░ (4/4 满) │ ││ │ Subagent 车道: ██████░░ (6/8) │ ││ │ Cron 车道: █░░░ (1/1) │ ││ └─────────────────────────────────────┘ ││ │ ││ ┌────▼────────────────────────────────┐ ││ │ Depth-Based Role Engine │ ││ │ depth 0 → main(CEO) │ ││ │ depth 1 → orchestrator / leaf │ ││ │ depth N → leaf(最底层) │ ││ └─────────────────────────────────────┘ │└─────────────────────────────────────────────┘二、角色体系:自动分配
2.1 三种角色
OpenClaw 根据"你是被谁生出来的,你在第几层"自动决定角色。用公司组织架构来理解:
// src/agents/subagent-capabilities.tsif (depth <= 0) return "main"; // 顶层 = CEOif (depth < maxSpawnDepth) return "orchestrator"; // 中间层 = VPreturn "leaf"; // 到底了 = 工程师CEO(主 Agent,depth 0)├── VP 产品(orchestrator,depth 1)── 能管人,也能自己干活│ ├── 工程师 A(leaf,depth 2)── 只能干活,不能招人│ └── 工程师 B(leaf,depth 2)├── VP 工程(orchestrator,depth 1)│ └── 工程师 C(leaf,depth 2)└── 实习生 D(leaf,depth 1)── 如果 maxSpawnDepth=1,depth 1 就已经是 leaf2.2 层级配置
maxSpawnDepth 决定公司允许几层管理层级:

最大支持 5 层嵌套。
2.3 角色核心特征

关键点:orchestrator 既能管人也能干活。这意味着一个 Agent 可以先自己尝试,发现复杂了再派子 Agent,不需要提前决定自己是"管理者"还是"执行者"。
三、工具权限:9 步过滤管道
3.1 管道架构
OpenClaw 的工具权限不是硬编码白名单,而是一条 9 步过滤管道,每一步都可能砍掉或加回工具:
原始 30+ 工具 ├── Step 1: 全局 profile 过滤(coding/messaging/minimal/full) ├── Step 2: 按 AI 提供商过滤 ├── Step 3: 全局 allow/deny 列表 ├── Step 4: 按提供商的 allow/deny ├── Step 5: 当前 Agent 的 allow/deny(per-agent policy) ├── Step 6: 当前 Agent 按提供商的 allow/deny ├── Step 7: 群聊/频道级别的 allow/deny ├── Step 8: 沙箱级别的 allow/deny └── Step 9: Subagent 深度级别的 deny ← 角色裁剪发生在这里3.2 深度裁剪逻辑
源码位置:src/agents/pi-tools.policy.ts所有 subagent 永远被禁的 6 个工具(系统管理类): - gateway — 系统管理 - agents_list — 系统管理 - whatsapp_login — 交互式登录 - session_status — 调度 - cron — 定时任务 - sessions_send — 直接跨 session 消息leaf 额外被禁的 4 个工具(管人类): - subagents — 管理子 agent - sessions_list — 查看 session 列表 - sessions_history — 查看 session 历史 - sessions_spawn — 派活
3.3 各角色工具能力

3.4 alsoAllow 机制
OpenClaw 支持通过配置把默认被禁的工具加回来:
{ "tools": { "subagents": { "tools": { "alsoAllow": ["sessions_send"] } } }}这比硬编码白名单灵活得多——可以针对特定 Agent 或特定场景定制工具集。
四、系统提示:渐进裁剪
4.1 PromptMode
// src/agents/system-prompt.tstype PromptMode = "full" | "minimal" | "none";不同于整体替换系统提示,OpenClaw 是按章节裁剪——subagent 保留干活必需的部分,去掉不需要的:

4.2 角色注入
subagent 额外收到一段角色上下文(src/agents/subagent-announce.ts),核心内容: - "你是一个由 [父 Agent] 派出来的 subagent" - "完成这个任务。这是你存在的全部意义" - "你不是 [父 Agent]。别试图扮演它" - orchestrator 被告知"你可以用 sessions_spawn 派出子 agent" - leaf 被告知"你是叶子节点,不能再派出子 agent"
五、Subagent 完整生命周期
源码位置:src/agents/subagent-spawn.tsspawnSubagentDirect()
5.1 Spawn(创建)
LLM 调用 sessions_spawn 工具 ├── 验证 agentId 格式 ├── 检查深度限制:callerDepth >= maxSpawnDepth → 禁止 ├── 检查子任务数:activeChildren >= maxChildrenPerAgent → 禁止 ├── 生成 session key:agent:<agentId>:subagent:<uuid> ├── 分配角色:resolveSubagentCapabilities({ depth, maxSpawnDepth }) ├── 解析模型和 thinking 级别 ├── 构建 subagent 系统提示 └── 通过 Gateway 发起 agent 调用,进入 Subagent 车道5.2 Execute(执行)
CommandLane.Subagent 车道5.3 Announce(自动汇报)—— Push-Based
这是 OpenClaw 最有特色的设计——完全异步的 push-based announce chain:
Leaf 完成任务 ├── 自动捕获最后一条 assistant 回复(最大 100KB) ├── 检查是否还有子 agent 在跑(有则等它们先完成) ├── 打包成 announce 消息 └── 推送给父 Agent ├── 父是 orchestrator → 内部投递,orchestrator 继续处理 │ └── orchestrator 综合所有子结果后,再向上 announce └── 父是 main → 外部投递,带频道/线程路由投递失败时支持指数退避重试(5s → 10s → 20s),最多 3 次,5 分钟过期。
5.4 Cleanup(清理)
cleanup: "delete" — announce 后立即删除 sessioncleanup: "keep" — 保留 session,等待 archive sweeper六、并发控制:车道制(Lane-Based Queue)
6.1 架构
OpenClaw 用车道制管理并发——不同类型的任务走不同车道,每个车道有独立的容量上限:
┌─────────────────────────────────────────┐│ Gateway 进程 ││ ││ Main 车道 ████░░░░ (4/4 满) ││ Subagent 车道 ██████░░ (6/8) ││ Cron 车道 █░░░░░░░ (1/1) ││ ││ 等候区:[任务5] [任务6] [任务7] ... │└─────────────────────────────────────────┘6.2 配置参数

6.3 车道特点
七、派活决策
7.1 谁决定"要不要派活"—— LLM 决定
sessions_spawn 是一个普通工具,和 read、exec 地位完全一样。LLM 在对话过程中自己判断是否调用。 系统提示里只给了一句模糊引导:
"If a task is more complex or takes longer, spawn a sub-agent. Completion is push-based: it will auto-announce when done." 没有复杂度评分、没有自动分析、没有决策树。整个代码库中没有任何
auto-spawn、should-spawn逻辑。
7.2 谁决定"能不能派活"—— 配置决定
虽然"要不要派"是 LLM 动态决定的,但"能不能派"是配置预先确定的:
LLM 想派活 → 调用 sessions_spawn ├── 我有这个工具吗? → leaf 没有(工具被裁掉了) ├── 深度允许吗? → callerDepth >= maxSpawnDepth → 禁止 ├── 子任务到上限了吗? → activeChildren >= maxChildrenPerAgent → 禁止 └── 全部通过 → 执行 spawn八、多 Agent Gateway
这是 OpenClaw 独有的概念——一个 Gateway 进程中可以同时托管多个独立"人格",每个有自己的身份、工作目录、记忆和权限:
{ "agents": { "list": [ { "id": "coding", "workspace": "/projects/main-app", "model": "anthropic/claude-opus-4-6", "sandbox": { "mode": "off" } }, { "id": "family", "workspace": "/home/shared", "model": "anthropic/claude-sonnet-4-6", "tools": { "deny": ["exec", "write"] } } ] }}外部消息通过Binding 路由决定发给哪个 Agent(src/routing/resolve-route.ts): - WhatsApp 家庭群 → family Agent - Discord 开发频道 → coding Agent - 默认 → 第一个 default: true 的 Agent 每个 Agent 的 subagent 完全隔离,不会互相访问对方的工作目录。
九、关键设计决策

夜雨聆风