03 · Agent 的大脑是怎么工作的
理解 OpenClaw Agent runtime、Agent loop、Tools、Skills、Hooks 与权限边界如何组成一个可执行的大脑。
前两篇已经讲清楚两件事:OpenClaw 不是单纯聊天窗口,一条消息也不是直接丢给模型就结束。本篇继续往里看一层:真正让 Agent 能做事的不是某个模型 API,而是一套运行时循环。
一句话先记住:
OpenClaw 的 Agent 大脑 = Agent runtime + session context + model inference + tool execution + streaming reply + persistence。
模型负责判断下一步,OpenClaw 负责把工作空间、会话、工具、技能、权限、事件流和最终回复串起来。
1. 先把 Agent 看成运行中的工作单元
OpenClaw 官方把 Agent runtime 描述成一个嵌入式运行时:每个 Gateway 里运行一个 Agent 进程,它拥有自己的 workspace、bootstrap files 和 session store。
这和“调用一次大模型接口”不是同一个层级。
flowchart LR
Gateway[Gateway]
Runtime[Embedded Agent Runtime]
Workspace[Workspace]
Session[Session Store]
Tools[Built-in Tools]
Skills[Skills Snapshot]
Gateway --> Runtime
Runtime --> Workspace
Runtime --> Session
Runtime --> Tools
Runtime --> Skills
几个关键点:
- Workspace:
agents.defaults.workspace是工具和上下文的工作目录,可以理解成 Agent 的办公桌。 - Bootstrap files:
AGENTS.md、SOUL.md、TOOLS.md等会被注入上下文,是 Agent 的长期工作说明。 - Session store:会话转录存为 JSONL,是 Agent 的本轮工作记录。
- Built-in tools:
read、exec、edit、write等受 tool policy 控制,是 Agent 的手脚。 - Skills:
SKILL.md文件夹会进入提示词和技能快照,是 Agent 的操作手册。
这里最容易误解的是 TOOLS.md:它不是授权开关。官方说得很明确,核心工具是否存在由 tool policy 决定,TOOLS.md 只是“希望工具怎么用”的指导。
TOOLS.md 是使用说明,不是授权系统。真正的工具可用性由 tool policy 控制。
2. Agent loop 是一次真实运行
官方对 Agent loop 的定义很直接:
intake → context assembly → model inference → tool execution → streaming replies → persistence
翻译成中文,就是:
sequenceDiagram
participant U as User
participant G as Gateway
participant R as Agent runtime
participant M as Model
participant T as Tools
participant S as Session
U->>G: message
G->>R: agent run
R->>S: load session and context
R->>M: model inference
M-->>R: assistant text or tool call
R->>T: execute tool if needed
T-->>R: tool result
R->>M: continue with observation
R-->>G: assistant/tool/lifecycle stream
G-->>U: final or streamed reply
R->>S: persist transcript
这就是 Agent 的大脑循环。
它不是“先规划所有步骤,再线性执行”,而是:
- 先把当前消息、会话、workspace 说明和技能装进上下文。
- 让模型判断下一步是回答、调用工具,还是继续思考。
- 如果调用工具,OpenClaw 执行工具并把结果作为 observation 交回模型。
- 模型基于观察结果继续生成下一步。
- 直到循环结束,再产出可见回复并写入会话。
如果你让 Agent “检查项目测试为什么失败”,一次真实 loop 可能长这样:
flowchart TD
A[用户: 检查测试失败] --> B[组装上下文]
B --> C[模型判断需要读文件]
C --> D[read package config]
D --> E[模型判断需要运行测试]
E --> F[exec test command]
F --> G[读取失败日志]
G --> H[模型定位失败原因]
H --> I[edit or apply_patch]
I --> J[再次运行测试]
J --> K[最终回复]
Agent 看起来像在“自主工作”,本质上是模型决策和 OpenClaw 执行层反复交替。
Agent loop 不是一次 API 调用,而是“模型判断 → 工具执行 → 观察结果 → 再判断”的闭环。
3. OpenClaw 在 loop 里做了哪些系统工作
官方 agent RPC 会先验证参数、解析 session、持久化 session metadata,然后立刻返回 { runId, acceptedAt }。真正的 Agent 工作随后进入 agentCommand 和嵌入式 runtime。
从学习角度,不需要先记函数名,但要理解这几层职责:
| 阶段 | OpenClaw 做什么 | 为什么重要 |
|---|---|---|
| 接收请求 | 解析 sessionKey / sessionId,创建 runId | 后续可以追踪这次运行 |
| 准备运行 | 解析模型、thinking、verbose、trace 默认值 | 同一 Agent 可以有稳定默认行为 |
| 加载技能 | 加载或复用 skills snapshot | 本轮知道可用技能 |
| 启动 runtime | 调用嵌入式 Agent runtime | 进入真正的模型-工具循环 |
| 事件桥接 | 把 runtime 事件转成 OpenClaw stream | UI 和聊天渠道可以看到进度 |
| 完成等待 | agent.wait 等 lifecycle end/error | 调用方能知道运行是否结束 |
OpenClaw 的关键价值在这里:它不是只把消息转发给模型,而是在模型外面维护会话一致性、工具执行、权限控制、流式事件和最终回复。
4. 串行化保证同一个会话不打架
官方文档强调:OpenClaw 的 loop 是 single, serialized run per session。同一个 session key 下的运行会排队,必要时还会经过全局队列。
这解决的是一个现实问题:Agent 会读写 session transcript,也可能调用 exec、write、edit 等工具。如果同一个会话里两个 run 同时改状态,很容易出现:
- 两次回复顺序错乱。
- 工具结果写进错误的轮次。
- session history 被并发覆盖。
- 用户后来发的消息被过早或过晚注入。
所以 OpenClaw 把 Agent loop 当成“一个会话的一次事务性运行”来处理。
flowchart LR
M1[message A] --> L[session lane]
M2[message B] --> L
M3[message C] --> L
L --> R1[run A]
R1 --> R2[run B]
R2 --> R3[run C]
这也是为什么第二篇讲消息队列时会提到 collect、steer、followup:这些模式最终都要喂进 session lane,不能绕过会话一致性。
5. Context 决定大脑看见什么
模型不是凭空推理。它每一步能做什么,取决于本轮 prompt 里有什么。
OpenClaw 在 prompt assembly 阶段会组合:
- OpenClaw base prompt。
- skills prompt。
- bootstrap context。
- per-run overrides。
- session messages。
- 模型限制与 compaction reserve tokens。
这解释了一个常见现象:同样一个模型,在不同 OpenClaw workspace 里表现会完全不同。因为它看到的 AGENTS.md、SOUL.md、TOOLS.md、skills 和历史上下文不同。
可以把大脑分成两层:模型能力负责语言理解、推理、工具调用判断,主要通过换 model 或 provider 改;上下文工程负责角色、规则、工具习惯、项目知识,主要通过 workspace 文件、skills、hooks、memory 改。
下一篇会专门讲记忆系统,这里先记住:OpenClaw Agent 的“聪明”不是只来自模型,也来自上下文装配。
6. Tools 是 Agent 的可执行能力
工具让 Agent 从“会说”变成“会做”。
以 exec 为例,官方定义是:在 workspace 中运行 shell commands,支持前台和后台执行;如果 process 可用,还可以管理后台进程。exec 有几个关键参数:
| 参数 | 作用 |
|---|---|
command | 要运行的 shell 命令 |
workdir | 命令工作目录 |
env | 环境变量覆盖 |
yieldMs / background | 后台执行控制 |
timeout | 单次命令超时 |
pty | 需要 TTY 的命令 |
host | auto、sandbox、gateway、node |
security / ask | host/node 执行的策略和审批 |
elevated | sandbox 中请求跳到宿主执行 |
OpenClaw 还会把工具事件作为 tool stream 发出。也就是说,用户或 UI 不只看到最终答案,还可以看到工具开始、更新、结束。
这对远程 Agent 很重要:如果 Agent 在微信、Discord、Telegram 或 Control UI 里运行,你需要知道它正在查文件、跑命令还是等待审批。
7. Skills 是 Agent 的操作手册
Tools 解决“能不能做”,Skills 解决“应该怎么做”。
OpenClaw 使用 AgentSkills-compatible skill folders。每个 skill 是一个目录,里面至少有 SKILL.md,通过 YAML frontmatter 描述名称和用途,再写具体操作说明。
官方当前的加载优先级是:
| 优先级 | 来源 | 路径 |
|---|---|---|
| 1 | Workspace skills | <workspace>/skills |
| 2 | Project agent skills | <workspace>/.agents/skills |
| 3 | Personal agent skills | ~/.agents/skills |
| 4 | Managed/local skills | ~/.openclaw/skills |
| 5 | Bundled skills | 随安装包提供 |
| 6 | Extra skill folders | skills.load.extraDirs |
同名 skill 冲突时,高优先级覆盖低优先级。这里有两个实践结论:
- 项目专用流程放
<workspace>/skills,不要污染全局。 - 通用个人习惯放
~/.agents/skills或~/.openclaw/skills,但要知道它会影响很多 Agent。
Skill 还有 allowlist。agents.defaults.skills 可以设默认可见技能,agents.list[].skills 可以替换某个 Agent 的技能集合。非空列表是最终集合,不会和 defaults 合并。
8. 权限边界要拆成三层
旧式理解经常把权限说成“允许 Agent 用工具”一句话。OpenClaw 当前文档把它拆得更清楚:
| 控制层 | 决定什么 | 典型配置 |
|---|---|---|
| Sandbox | 工具在哪里运行 | agents.defaults.sandbox.* |
| Tool policy | 哪些工具可用 | tools.*、tools.sandbox.tools.*、agents.list[].tools.* |
| Elevated | sandbox 中的 exec 是否能跳到宿主 | tools.elevated.* |
三个层次不能混为一谈。
flowchart TD
A[Agent wants to run exec] --> B{Tool policy allows exec?}
B -- No --> X[blocked]
B -- Yes --> C{Session sandboxed?}
C -- No --> D[host exec policy applies]
C -- Yes --> E{Elevated requested and allowed?}
E -- No --> F[run inside sandbox]
E -- Yes --> G[run on gateway or node with approvals]
几个硬规则:
deny总是赢。- 如果
allow非空,其他工具默认视为 blocked。 - Tool policy 是硬停止点,
/exec不能覆盖被 deny 的exec。 /exec只改当前 session 的 exec 默认参数,不授予工具访问权。- Elevated 只影响
exec,不授予额外工具,也不覆盖 tool allow/deny。 /elevated full会跳过 exec approvals,但前提仍然是 elevated 可用且 allowlist 通过。
这部分很关键。把权限层次讲清楚,才不会把“工具不可用”“sandbox 里跑不到宿主路径”“审批没过”“skill 没加载”混成同一个问题。
排查工具问题时先分层:tool policy 是否允许、session 是否 sandboxed、elevated 是否可用、审批是否通过。
9. Hooks 不是一个东西
OpenClaw 现在有两套容易混淆的 hook:
- Internal hooks:运行在 Gateway 事件脚本层,适合
/new、/reset、/stop、agent:bootstrap、gateway lifecycle、message events。 - Plugin hooks:运行在插件内进程扩展点,适合改 prompt、拦截 tool call、控制消息发送、观察 session lifecycle。
Internal hooks 的事件包括:
command:newcommand:resetcommand:stopsession:compact:beforesession:compact:afteragent:bootstrapgateway:startupmessage:receivedmessage:preprocessedmessage:sent
Plugin hooks 才包含 before_tool_call、after_tool_call、before_prompt_build、before_agent_reply 等更深的 Agent loop 扩展点。
所以实践上要这样选:
/new时保存一份会话摘要:Internal hook。- Gateway 启动时跑
BOOT.md:Internal hook。 - 在系统 prompt 构建前注入动态上下文:Plugin hook。
- 在工具调用前要求审批或改参数:Plugin hook。
- 出站消息发送前重写或取消:Plugin hook。
不要把 internal hook 当成万能拦截器。它适合事件自动化;真正要进入模型、工具、消息派发链路,应该用 Plugin hooks。
10. Streaming、timeout 和静默回复
Agent loop 运行时会发三类主要事件流:lifecycle 负责 start、end、error;assistant 负责 assistant deltas;tool 负责 tool start/update/end。
这也是为什么 OpenClaw 可以在聊天渠道里边做边回,或者在 Control UI 里展示工具过程。
超时也分层:
agent.wait默认只是等待 30 秒,不代表 Agent 被停止。- Agent runtime 有
agents.defaults.timeoutSeconds,官方默认值是 48 小时。 - Model idle timeout 会在模型长时间没有输出 chunk 时中止请求。
exec自己也有每个命令的 timeout。
最终回复阶段还有一个特殊规则:精确的 NO_REPLY / no_reply 会从出站 payload 里过滤掉。这个能力适合 Agent 已经通过 messaging tool 发送过可见回复、或者某些自动化任务不需要再重复确认。
11. 常见误解
常见误解可以按这组边界校正:
- Agent 不是 ChatGPT 套壳。Agent 是 runtime 驱动的循环,模型只是其中一层。
- Tool 写在
TOOLS.md里不等于能用。工具可用性由 tool policy 决定,TOOLS.md只是指导。 - Skill 不等于工具。Skill 是说明书,工具才是执行能力。
- Hook 不是都能拦截工具调用。
before_tool_call属于 Plugin hooks,不是普通 internal hook。 - Elevated 不等于超级管理员。Elevated 只影响 sandbox 中的
exec,不能覆盖 tool policy。 agent.wait超时不等于 Agent 停了。agent.wait只是等待超时,不等于运行被取消。
这些区别看起来细,但后面排障会频繁用到。
12. 给 Agent 的实践任务
把下面任务交给你的 OpenClaw Agent,观察它的过程:
请解释你处理这条消息时会经历哪些阶段:
1. 哪些 workspace 文件会影响你的回答?
2. 你现在有哪些 tools 和 skills?
3. 如果要运行 shell 命令,sandbox、tool policy、elevated 分别会影响什么?
4. 什么时候应该用 internal hook,什么时候应该用 plugin hook?你要看的不是答案是否漂亮,而是它能不能把 runtime、context、tools、skills、policy、hooks 分层说清楚。
如果它把 TOOLS.md 当成授权配置,或者把 before_tool_call 写成普通 internal hook,就说明这章还没吃透。
13. 本章自检
读完这一篇,你应该能回答:
- 为什么说 Agent loop 不是一次 API 调用?
- OpenClaw 为什么要按 session 串行化 Agent run?
- Workspace、bootstrap files、session store 分别影响什么?
- Tools 和 Skills 的边界是什么?
- Sandbox、tool policy、elevated 三层分别控制什么?
- Internal hooks 和 Plugin hooks 的区别是什么?
NO_REPLY为什么不会作为普通回复发出去?
能回答这些问题,再进入下一篇记忆系统,才不会把“Agent 记住了什么”和“Agent 本轮看见了什么”混在一起。
14. 接下来去哪
04 · 记忆系统
继续拆 session history、memory search、compaction、workspace memory 和长期知识。
02 · 一条消息的旅程
回到消息链路,确认消息如何进入 runtime、session 和 Agent loop。
官方教程:Agents
对照官方 Agents 页继续看 workspace、runtime、tools 和 agent 配置。