OpenClaw 技术架构深度解析

本文的架构脉络参考了 hesamation 的英文 thread,以及 Cell细胞的中文译文。但本文不是译文,也不是源码审计:我按 2026 年 7 月的公开文档重新核对了运行时、记忆和 exec 的行为,并补上了初学者读原文时最容易缺失的因果链。

OpenClaw 迭代很快。端口、目录、默认策略、是否启用 sandbox,都会随版本和配置而变。本文解释的是架构和判断方法;部署时请再查看当前的官方文档与 release notes。特别是安全相关结论,不能把“功能支持”读成“你的实例已安全配置”。

先给结论:它到底是什么

OpenClaw 不是一个“会聊天的模型”。它是一个把聊天渠道、模型 API、文件与浏览器工具、会话记录放进同一套运行时的个人 Agent 系统。模型只负责根据眼前的上下文决定下一步;OpenClaw 负责把消息送到模型、把模型要求的动作执行掉,并把结果再交还给模型。

这一区分很重要。一个普通聊天窗口大致是“输入文本,得到文本”。OpenClaw 多了一条循环:

1
用户提出任务 → 模型决定要不要调用工具 → 系统执行工具 → 结果回到模型 → 模型继续判断

比如你在 Telegram 里说:“读一下下载目录,把昨天的发票列出来。”模型本身没有你的文件。它会先请求一个读目录的工具,拿到文件名后再筛选日期、读取候选文件,最后把结论发回 Telegram。能做事的不是模型的“记忆力”,而是这套循环和它被允许使用的工具。

读完本文,如果你能回答下面四个问题,就算真正掌握了主干:

  1. 一条 Telegram 消息为什么会进入某个特定会话,而不是直接交给模型?
  2. 模型为什么能“看见”文件和网页,又为什么有时会遗忘先前的约定?
  3. 同一条 shell 命令为什么可能在容器、Gateway 主机或另一台已配对的机器上运行?
  4. 为什么允许模型调用工具,并不等于应该让它拥有无限权限?

阅读前先补齐五个概念

后文有不少英文名词。它们不是五个神秘组件,先用一句话记住即可。

术语 初学者可以怎样理解 它不是什么
LLM 根据已有文字预测下一段文字的模型 不会直接读本机文件,也没有永久记忆
Agent 让 LLM 在“思考、调用工具、读取结果”之间循环的程序 不是另一种模型
工具(tool) 受参数约束的能力接口,例如读文件、搜索、执行命令 不是自然语言提示词
上下文(context) 当前一次模型调用真正收到的材料 不是完整历史的同义词
会话(session) 一段对话及其运行状态、记录和默认设置 不等于一个用户或一个聊天软件

“上下文”和“记忆”最容易混。上下文像你摊在桌上的资料,模型只能看到桌上的这些。记忆是被写进磁盘的笔记,需要时再挑片段放上桌。聊天记录则更像录音:它可以留存,但不代表每次都会原样塞进模型的上下文窗口。

一条消息走完全程

假设你在 Slack 对 OpenClaw 说:“把仓库里今天改动的 Markdown 文件列出来,并告诉我哪篇还没有参考资料。”这条消息会经历下面的链路。

这张图里最需要把握的是职责边界:渠道适配器只负责“听懂某个平台的消息格式”;Gateway 管理系统里的连接、会话与调度;Agent Runner 管模型调用和工具循环;真正会触及文件、命令或浏览器的,是工具执行面。不要把这些全称作“AI”。

第一步:渠道适配器把不同聊天软件翻成同一种消息

Telegram、Slack、WhatsApp 的消息格式和鉴权方式并不一样。渠道适配器要做四类工作:验证 bot token 或登录状态,解析文字和附件,检查发送者或群聊规则,把最终回复转换成该平台能显示的格式。

因此,消息刚进系统时,最重要的信息不只是“用户说了什么”,还包括“它来自哪个渠道、哪个聊天、哪个已认证的发送者、是否带有附件”。这些元数据决定后续是否允许执行命令、该归入哪段对话,以及回复要发回哪里。

第二步:Gateway 决定这是谁的任务

Gateway 可以把它理解成常驻的调度服务。它维护渠道连接,识别这条消息要送给哪个 agent 和 session,也保存一部分会话与运行状态。默认监听地址常见为 127.0.0.1:18789,但端口和监听地址应以自己的配置为准。

“路由到会话”听起来抽象,实际很朴素。假设你同时在私聊和项目群里使用同一个 agent:私聊里讨论的是个人待办,项目群讨论的是发布计划。两处对话不应混成一锅。Gateway 用渠道、聊天标识和配置规则找到对应 session,Agent Runner 才能读到正确的历史与工作区指令。

Gateway 也是信任边界的一部分。它一头接外部渠道和 WebSocket 客户端,另一头能调度带工具权限的 agent。把它直接放到公网,等于把一个可能触及本机资源的控制入口暴露给陌生网络。是否“有 token”并不能替代网络隔离、访问控制和更新。

第三步:Agent Runner 把“该给模型看什么”组装出来

Agent Runner 不是模型本身。它为每次模型调用准备材料,选定提供方和模型,处理流式响应、失败重试或回退,并把工具定义交给模型。官方运行时把这部分放在内嵌 runner、session 管理和 provider transport 等模块中;插件只能通过公开 SDK 接口接入,而不应依赖内部目录结构。

一次调用的上下文通常由下表几类内容组成。实际顺序、预算和覆盖规则会随版本和 agent 配置变化,所以把它当作心智模型,而不是不可变的加载清单。

上下文材料 它回答的问题 常见载体
系统规则 “我是谁,哪些事不能做?” 内置系统提示词、策略配置
工作区说明 “这个 agent 的工作方式和人格是什么?” AGENTS.mdSOUL.mdTOOLS.md
相关记忆 “以前已经确认过什么?” MEMORY.md、每日笔记、检索片段
当前会话 “刚刚聊到哪里?” session 转录和摘要
工具定义 “我能调用什么,参数怎么填?” 内置或插件提供的 schema

这里有两个常见误解。第一,SOUL.md 不是安全控制器,它只是模型会读到的一段指令文本。第二,工具说明进入上下文,不代表模型绕过工具策略就能执行。模型只能提出结构化请求,程序仍应在工具层检查这个请求。

第四步:模型在工具循环里工作

模型每次返回的东西通常有两种:最终文本,或工具调用。前者可以直接发回渠道;后者需要 Agent Runner 执行工具,把结果作为新消息追加到上下文,然后再问一次模型。

用上面的“检查 Markdown 参考资料”任务举例,内部过程可能接近这样:

1
2
3
4
5
6
用户:检查今天改动的 Markdown 文件和参考资料
模型:调用 exec,列出 Git 今天改动的 .md 文件
工具:返回文件路径列表
模型:调用 read,读取每篇文章的“参考资料”部分
工具:返回相关片段
模型:整理结论,生成一段 Slack 回复

模型不会像人一样在后台持续思考。每一轮都得重新把足够的上下文和上轮工具结果给它。为防止死循环或成本失控,运行时会设置工具轮数、超时、上下文预算等限制。出现“它一直在重复搜索”时,先别急着怪模型笨:工具结果可能不完整、任务描述不够可验证、或循环上限和错误处理不合适。

第五步:工具结果和最终答复回到原渠道

工具输出不会直接等于用户可见的答案。它先回到模型,模型可能据此继续行动,也可能写出解释。最终文本再经 Gateway 和渠道适配器返回原聊天软件;长回复还可能被分片,Markdown 会按平台规则转换。

同时,系统会保存会话转录。它常采用追加式记录,便于追踪用户消息、工具请求、工具结果和模型回复。不要执着于某个固定目录名:当前版本的会话与 agent 状态会按 agent 的状态目录组织,路径是可配置的。排查问题时应使用状态命令或配置,而不是照抄旧文章里的 ~/.openclaw/sessions/

lane 队列:先保证同一会话不会互相踩脚

假设用户先发“把 README 标题改成 v2”,紧接着又发“把刚才改动撤销”。如果两条消息完全并行,后发任务可能先读取旧文件、先执行撤销,结果就会和用户看到的对话顺序相反。更糟的是,两个工具调用会同时写同一个文件。

OpenClaw 使用 lane 来表达这种调度关系。可以把 lane 想成单车道:进入同一条 lane 的工作按顺序走,后一个任务等前一个任务完成或让出位置。需要独立处理的定时任务或专门任务可以放到另一条 lane。它并不神奇地消灭所有并发问题,但把“默认串行”放在了靠近调度的位置。

这比到处给业务代码补锁更适合对话式任务。因为对用户而言,“我刚说完 A,又说 B”天然带有顺序含义。只有当任务确实独立,例如一个 cron 汇总和一段私聊,才值得显式并发。

不过不要把 lane 理解成事务。两个 lane 仍可能碰同一份外部资源,例如同一个 Git 工作树或同一张在线表格。开发者仍要选好隔离范围、幂等操作和冲突处理。lane 解决的是常见的会话内顺序问题,不是数据库级一致性保证。

记忆:磁盘笔记、检索和上下文压缩是三件事

“它记得我喜欢 TypeScript”背后,至少有三层机制,混在一起就容易把问题看错。

  1. 会话转录保存发生过什么。
  2. Markdown 记忆文件保存以后仍值得使用的事实、偏好和决定。
  3. 检索与上下文管理决定这次模型调用实际看到哪一部分。

当前官方文档把默认记忆工作区写为 ~/.openclaw/workspace,但多 agent 或自定义部署会有不同的 agent workspace。最常见的文件是:

文件 适合保存什么 是否会自动出现在新会话上下文
MEMORY.md 稳定偏好、长期决定、短摘要 会,但有引导文件预算
memory/YYYY-MM-DD.md 当天观察、过程记录、临时线索 不会整份注入,会供检索使用
DREAMS.md 可选 Dreaming 机制的整理记录,供人审阅 不是常规长期记忆入口

这套设计的优点是可读、可编辑、可备份。你可以直接修改 Markdown,而不用猜一个黑箱数据库保存了什么。代价也很明确:如果把十万字日记塞进 MEMORY.md,它会挤占每一次模型调用的上下文;文件虽然仍在磁盘上,进入模型的副本可能被截断。

检索不是“把所有记忆都喂给模型”

当 embedding 提供方配置好后,memory_search 会将向量相似度和关键词匹配结合起来。向量检索适合找“语义相近”的内容,关键词对 API 名、订单号、代码符号更可靠。它们命中的片段再进入上下文,而不是整座记忆库被一次性搬进提示词。

这也解释了一个现象:模型可能“记得”你偏好 TypeScript,却忘了某个昨天提过的文件名。前者被提炼进长期记忆,后者也许只在每日笔记里,而且这次查询没有成功召回。需要精确找回的标识符,应保留清晰关键词和结构化上下文,而不是只写一句模糊感想。

压缩、修剪和记忆整理各自解决什么

长对话会塞满上下文窗口。OpenClaw 的三种机制不要混为一谈:

机制 处理对象 对磁盘记录的影响 目的
Context pruning 较旧、过大的工具结果 仅本次调用的内存视图,不改原始转录 减少无用工具输出占 token
Compaction 较长的对话历史 用摘要替代部分历史的会话视图 让对话继续进行
Memory flush 压缩前的重要上下文 尝试写入记忆文件 降低摘要丢失关键事实的概率

官方文档还提供了可选的 Dreaming:它会按计划把短期记忆候选做筛选、整理和提升,并把过程写入 DREAMS.md 供人检查。它默认关闭,不能据此假定每个实例都会自动“遗忘旧记忆”。即便开启,记忆也只是给模型的提示材料,不能替代审批、sandbox 或其他硬性策略。

Pre-compaction memory flush 默认开启,作用是在会话被总结前给 agent 一个静默回合,把值得保留的内容写到文件。它有用,但不是保险箱。模型可能判断错重点、写入失败,或把没有授权边界的旧约定理解错。因此,“删除邮件前必须确认”这类约束应该同时进入权限策略,不能只依赖一段记忆或聊天历史。

这一节只搭建架构地图。记忆文件的分工、混合检索与压缩细节,可以接着读《OpenClaw 记忆系统深度解析》

Computer Use:模型没有手,工具才是它的手

“Computer Use”常被理解为模型看截图、点鼠标。实际范围更广:文件读写、shell 命令、浏览器控制、后台进程都可能属于 agent 的行动能力。每种工具的风险不同,也不应共用一套粗糙权限。

能力 典型任务 主要风险 更合适的默认态度
read / write / edit 阅读和修改工作区文件 覆盖重要内容、读取敏感文件 限定工作区和可写范围
exec 调用 Git、构建、脚本 任意命令和凭据泄露 sandbox 或审批优先
browser 查询、表单、网页操作 提示注入、误提交、登录态泄露 使用独立浏览器 profile
process 长时间构建或服务 遗留进程、资源消耗 限制时长并追踪状态

浏览器尤其值得单独说。OpenClaw 管理的浏览器可以使用一个专供 agent 的 Chrome、Brave、Edge 或 Chromium profile,和个人浏览器资料隔离。它能用文本化的可访问性树来表示页面,例如按钮、输入框、标题和它们的引用编号。对多数填表、搜索、点链接任务,语义快照比反复截图更轻,也更容易让模型定位控件。

1
2
3
- textbox "搜索关键词" [ref=2]
- button "搜索" [ref=3]
- heading "检索结果"

但“看得懂网页结构”不等于“懂得网页内容是否可信”。网页里可以有诱导 agent 忽略规则的文字,也可能把删除、支付、授权伪装成普通按钮。涉及资金、发布、账户授权和删除数据的动作,仍应要求人工确认。

执行面与 sandbox:同一个 exec,可能落到三处

这部分是初学者最容易产生危险误解的地方。exec 是一个会修改环境的 shell 能力。禁用 writeedit 等文件工具,并不会让 exec 自动只读,因为 shell 自己就可以写文件或发网络请求。

当前 exechost 可以是 autosandboxgatewaynode

执行位置 它是什么 适合什么场景
sandbox 隔离运行时中的命令 默认处理不完全可信的任务
Gateway 运行 OpenClaw 服务的那台主机 必须访问该主机资源的受控维护任务
Node 已配对的伴侣设备或 Node Host 明确需要操作另一台指定设备时
auto 有 sandbox 时选 sandbox,否则选 Gateway 方便,但必须先确认实际解析结果

官方文档明确写着:sandbox 默认关闭;它关闭时,host=auto 会解析到 Gateway。更容易被忽略的是,未显式收紧时,Gateway 和 Node 的 host 策略默认是 security=fullask=off。这不代表所有部署都会这样运行,但足以说明不要把“我没配置任何东西”误当成“它会弹窗问我”。

如果你刚开始使用,先做两件事:启用 sandbox,并把 host 执行设为需要审批或 allowlist。下面的配置只展示思路,字段和可用模式仍应与当前版本文档核对:

1
2
3
4
5
6
7
8
{
tools: {
exec: {
host: "auto",
mode: "ask"
}
}
}

mode: "ask" 的意思通常是 allowlist 命中的命令直接通过,其余命令请求人工批准;deny 则完全禁用执行。不要为了“少弹几个框”把一长串复杂 shell 放进永久 allowlist。安全策略要识别的是可执行程序、参数和执行位置,而不是只看一段看起来无害的自然语言。

为什么 exec 的安全问题很难靠黑名单补完

早期安全设计常把“允许什么命令”写成命令名或路径的模式匹配,再配合人工批准。它对简单命令有用,但 shell 会解释重定向、变量、转义、子命令和解释器参数。策略层看到的文本,未必等于 shell 最终执行的语义。

例如,批准“某个程序”不一定等于批准它调用的子解释器;拒绝一个完整选项名,也不等于覆盖同一行为的所有写法。更近的 OpenClaw 文档已经为 allowlist 模式增加了多段命令、重定向、内联解释器等限制和审批回退,但这类边界仍需要持续审计,不能把 allowlist 当作沙箱的替代品。

一篇 arXiv 预印本收集并分类了 OpenClaw 相关 advisory。其中的价值不在于某个数字能代表今天的漏洞总数,而在于它把风险按接口拆开:Gateway WebSocket、渠道输入、工具分发、exec 策略、容器边界和技能分发会相互叠加。单点看似中等的问题,串起来可能变成越权或远程命令执行。

这张图不是某个漏洞的复现步骤,而是威胁建模方法:每次新增渠道、插件、浏览器登录态或配对 Node,都问一遍“谁能提供输入”“输入会进入哪里”“它能影响什么权限”“这个权限能否再跳到别处”。

Skills 也应放进这个模型里。SKILL.md 往往会进入 agent 的上下文,因而它既可以教会 agent 一个可靠流程,也可能夹带恶意指令,诱导模型下载、执行或泄露内容。安装社区 skill 前先读文件、确认来源和依赖;对不可信网页、邮件和附件,把它们当作数据,不要让它们改写系统规则。

给初学者的部署核对表

理解架构的目的,是能做判断,而不是背组件名。如果你已经运行了 OpenClaw,下面的检查比继续调 prompt 更优先:

  1. Gateway 是否只监听本机或受控内网?若必须远程访问,是否经过认证和安全网络入口?
  2. sandbox 是否真的已启用?当前会话的 /exec 状态里,host=auto 最终会落在哪里?
  3. Gateway 与 Node 的 tools.exec 是否显式设为 askallowlistdeny,而不是依赖默认值?
  4. 渠道 allowlist 是否使用平台稳定的用户或聊天 ID,而不是可修改的显示名和用户名?
  5. 浏览器是否使用独立 profile?是否避免把主力邮箱、密码管理器和金融账户直接暴露给 agent?
  6. 记忆中是否把“需要确认后才能执行”的约束写清触发条件、失效条件和负责人?更重要的是,是否有权限策略来强制它?
  7. 安装的 plugin 与 skill 是否来自可追溯来源,并且更新后重新检查过权限?

可以把这张表当作一次小练习。你不必先理解 TypeScript 或 WebSocket,先能在自己的实例里查到“这条命令将在哪执行、谁可以触发它、需要谁批准”,就已经掌握了 OpenClaw 架构最实用的部分。

小结

OpenClaw 把 LLM 放进一个会话驱动的运行时:渠道适配器接消息,Gateway 找到正确的会话并安排任务,Agent Runner 把上下文和工具定义交给模型,模型通过工具循环完成任务,执行面在策略约束下触及真实环境。

这套架构有几个很朴素的取舍。lane 把同一会话的顺序放在默认路径上;语义快照尽量先提供结构化网页信息,再考虑昂贵的视觉输入;Markdown 记忆让人能查看和修改 agent 保存的事实。另一方面,记忆检索会漏召回,压缩会损失细节,shell 的语义也比字符串规则复杂得多。把安全交给提示词、记忆或一次“允许”都不够。

所以,OpenClaw 最适合被看作一套“把模型接到现实世界”的运行时,而不是一个无所不能的聊天机器人。模型负责提出下一步,系统设计负责决定它看得到什么、做得了什么,以及做错时损失有多大。


参考资料