乐于分享
好东西不私藏

OpenClaw 多 Agent 架构深度调研

OpenClaw 多 Agent 架构深度调研

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 就已经是 leaf

2.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(执行)

子 Agent 在独立 session 中运行,使用独立的 AbortController
运行在专用的 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 后立即删除 session
cleanup: "keep" — 保留 session,等待 archive sweeper
Archive sweeper 每 60 秒扫描一次,默认 60 分钟后自动归档

六、并发控制:车道制(Lane-Based Queue)

6.1 架构

OpenClaw 用车道制管理并发——不同类型的任务走不同车道,每个车道有独立的容量上限:

┌─────────────────────────────────────────┐│              Gateway 进程                 ││                                           ││  Main 车道    ████░░░░  (4/4 满)          ││  Subagent 车道 ██████░░  (6/8)            ││  Cron 车道    █░░░░░░░  (1/1)             ││                                           ││  等候区:[任务5] [任务6] [任务7] ...       │└─────────────────────────────────────────┘

6.2 配置参数

6.3 车道特点

车道满时新任务进入等候区排队
不同车道互不影响——Subagent 车道满了不影响 Main 车道
每父限制(maxChildrenPerAgent)防止单个 Agent 独占资源

七、派活决策

7.1 谁决定"要不要派活"—— LLM 决定

sessions_spawn 是一个普通工具,和 readexec 地位完全一样。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-spawnshould-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 完全隔离,不会互相访问对方的工作目录。

九、关键设计决策