写作现场:2026 年 2 月 4 日。 本文固定在 v2026.2.2,只讨论一条消息如何从 Gateway 进入模型与工具循环。OpenClaw 的关键结构并不是 SOUL.md 或工具数量,而是围绕 Agent loop 建立的控制面:运行标识、会话序列化、全局背压、状态持久化和权限分层。

请求生命周期:标识、排队与持久化

chat.send 要求客户端提交 idempotencyKey,服务端将其作为 runId。会话检查和运行登记完成后,接口先返回:

{ runId, status: "started" }

这里的 started 是接收确认,不是完成确认。runId 能把后续事件、流式输出和最终结果关联到同一次运行,也能识别客户端重发;它不能自动保证工具副作用幂等。邮件已发出但连接中断时,重放整个 run 仍可能再次发送。要获得接近事务的语义,每个外部操作还需要自己的 operation ID、结果收据和重试规则。

执行入口 runEmbeddedPiAgent 经过两级调度:

session:<key> FIFO
        ↓
全局并发闸门
        ↓
模型 / 工具循环

session 队列避免同一段对话的两个 turn 并发修改 transcript 或操作同一浏览器;全局闸门限制整台机器的并发消耗。steerfollowupcollect 又定义了三种插入语义:在工具边界尝试转向、等待当前 run 结束、合并短时间内的消息。它们不是界面选项,而是事件顺序协议。

这一版本用 JSON store 保存 session 元数据,用 JSONL 保存消息轨迹;store 更新依赖文件锁与临时文件原子替换。优点是状态可直接检查,缺点是多进程争用、损坏恢复、schema migration 和跨文件一致性仍由应用层承担。它是一套透明的本地日志机制,不是 durable workflow engine。

权限模型:身份范围与能力分层

session key 同时承担连续性和数据隔离。私聊汇入主 session 可以让同一用户跨入口延续上下文,但多人共享机器人时,channelaccountpeer 必须进入作用域;否则 session 复用会把上下文连续性变成越权读取。

OpenClaw 将权限拆为三层:

  • tool policy 决定模型能否看见某项能力;
  • sandbox 决定代码在宿主机还是隔离环境执行;
  • elevated 为特定命令提供离开 sandbox 的路径。

三者不能互相替代。隐藏一个 write 工具不能让 exec 只读,工作目录也不是安全边界;反过来,进程被放进容器也不代表它有权调用其中的全部凭据。可靠部署至少还需要按用户绑定身份、最小化工具集合、限制网络与文件系统、记录副作用,并区分“模型输出结束”和“外部操作确认完成”。

这套结构解释了 OpenClaw 为何更接近常驻 Agent,而不是套壳聊天界面:Gateway 维持入口,session 保存责任主体,队列确定事件顺序,权限层约束行动范围。它适合需要跨渠道处理重复任务的个人与小团队,但产品竞争最终不会只发生在 Skills 数量上,而会发生在审计、撤销、隔离和恢复语义上。

版本与源码

信息边界:本文只采用 2026-02-04 及此前已公开的事实和 v2026.2.2 源码,不使用后来版本的实现结果。