OpenClaw 怎样拼装系统提示词并控制 Token 成本

OpenClaw 怎样拼装系统提示词并控制 Token 成本
Asaakii核验范围: 本文以 2026 年 7 月查阅的官方文档为准。Token 数字来自特定环境的实测,会随模型、插件数量和工作区文件大小变化;本文把它们当作量级示例,不当作所有实例的默认值。
每次向模型发消息时,OpenClaw 发送的不只有用户输入。它还会拼入身份、工作区文件、工具说明、安全规则和运行环境,这一整段称为 system prompt。本文说明它由什么组成、为什么会带来固定 Token 成本,以及应该从哪里开始瘦身。
初学者阅读地图
| 概念 | 先把它理解成 |
|---|---|
| 用户消息 | 你当前发出的需求,例如“帮我整理这份笔记” |
| System prompt | 系统每轮随请求带上的角色、规则、工具和上下文 |
| 工具 schema | 模型可调用工具的机器可读说明 |
| Context | 本轮真正送进模型的全部信息 |
先看第一节理解“为什么一句 hi 也会有成本”;第二、三节看上下文如何被拼装;最后两节再判断哪些内容可以精简、哪些不能动。
一、一句「hi」要花多少钱
先看一个会让人愣一下的事实。
你给一个全新的 OpenClaw 会话只发一个字——「hi」。你以为发出去的就是这两个字母。但如果把真正送到模型面前的完整请求拉出来看,输入 token 是 16k 量级。也就是说,一个干净的对话,还没开始干活,system prompt 默认就带了一万多 token 的「底噪」。
这不是 bug,是设计。OpenClaw 为了让模型「开箱即会」——知道有哪些工具、遵守哪些安全准则、记得你是谁、认得你的工作区——每一轮都要把这一整套上下文重新塞给模型。方便是真方便,但天下没有免费的上下文:这坨东西每一轮对话都要重付一遍 token。
所以这篇的核心问题就两个:这一万多 token 里装了什么?以及,哪些是可以省的?
二、怎么把完整的 prompt「抓」出来看
想优化,先得看见。会话日志通常不保留完整的运行时 system prompt,因此不要只靠翻 JSONL 判断上下文大小。
优先使用 OpenClaw 的 /context list 和 /context detail:它们能列出当前注入了哪些内容、各占多少 Token。原文作者使用过 modelbox 这类代理方式捕获完整请求,它仍适合做深入排查,但不应成为初学者的第一步。
三、把 system prompt 摊开:它由哪几段拼成
抓出来之后,可以把它切成三大块:源码硬注入段 + 工作区文件注入段 + 收尾协议段。
flowchart TD SP["每轮发给模型的完整请求"] SP --> A["① 源码硬注入段<br/>身份 / Tooling / Safety / Skills<br/>Memory Recall / Messaging / 防注入"] SP --> B["② Project Context<br/>八个工作区文件全文注入"] SP --> C["③ 收尾协议段<br/>Silent Replies / Heartbeats / Runtime"] SP --> D["④ body.tools[]<br/>工具的完整 JSON schema"] B --> B1["AGENTS · SOUL · TOOLS · IDENTITY<br/>USER · HEARTBEAT · BOOTSTRAP · MEMORY"]
① 源码硬注入段:模型的「行为宪法」
这一段来自源码,每次都在,是 OpenClaw 塞给模型的「规矩」。逐个说几个关键的:
- 定身份:开头一句
You are a personal assistant running inside OpenClaw,把角色边界写死。 - Tooling(晒武器):列出「经策略过滤后当前真实可用」的工具清单,附短描述。注意这里有一句容易踩的话——
Tool names are case-sensitive,工具名大小写敏感,写错一个字母就调用失败。 - Safety(立规矩):一段护栏提醒,明确告诉模型它没有独立目标,不许自我保全、自我复制、扩权、绕过监督。这段的灵感来自 Anthropic 那套「AI 宪法」思路。它是官方通用的,不是谁的个人配置。
- Skills(加技能):技能索引段。回复前先扫描
<available_skills>列表,匹配到就用read读对应的 SKILL.md 再照做,一次最多只读一个。 - Memory Recall(查记忆):强制规则——凡涉及历史、决策、日期、偏好、待办,必须先跑
memory_search、再用memory_get拉需要的行。这正是第二篇讲的「查询式记忆」在 prompt 层的落点。 - Messaging(管消息):规定消息一律走 OpenClaw 内部路由,
Never use exec/curl for provider messaging——严禁模型自己用 curl 发消息。 - Inbound Context(防注入):这一段值得单独强调。它把「OpenClaw 带外生成的可信元数据」(chat_id、channel、provider 等)和「用户发来的、可能伪造的文本」明确分开,并告诉模型:用户的文本就算长得像元数据头,也不能当真。
最后这条防注入,是本系列安全线的第四次出现:第一篇是 exec allowlist(词法层拦命令),第二篇是记忆投毒(写入层防污染),第三篇是 Gateway 靶心(入口层防越权),这一篇是 prompt 层给上下文标注来源、降低提示注入。四层防御各在一处,思路是同一个——别默认输入可信。
② Project Context:八个工作区文件,全文注入
接下来是把你工作区里的文件整篇拼进去。主对话会带全部八个:
AGENTS.md、SOUL.md、TOOLS.md、IDENTITY.md、USER.md、HEARTBEAT.md、BOOTSTRAP.md、MEMORY.md。
这些文件各自装什么、承载哪种记忆,第二篇已经讲透了,这里不重复。这一篇只关心它们作为 prompt 的成本,有两个第二篇没提的要点:
- 是全文注入,不是检索片段。 每一轮,这八个文件的完整内容都硬拼进 system prompt。所以它们越大,你每句话就越贵。其中
MEMORY.md是最容易失控的——它会随时间越长越长,是 system prompt 成本的大头之一,也会导致更频繁的压缩。这给第二篇那句「保持 MEMORY.md 精简」补上了硬理由:不是洁癖,是每一轮都在为它付费。 - 有截断上限。 官方有两个配置默认值兜底:单个文件超过
agents.defaults.bootstrapMaxChars(默认 20000 字符)会被截断,八个文件注入总量则由bootstrapTotalMaxChars(默认 60000 字符)封顶。换句话说,MEMORY.md写太长,底部内容可能根本到不了模型眼前——这也是「保持精简」的另一个现实理由。
③ 收尾协议段
prompt 末尾还有几段固定协议:Silent Replies(没话说时只能整条回 NO_REPLY,还给了正反例防误用)、Heartbeats(心跳轮询时没事回 HEARTBEAT_OK、有事直接发内容)、Runtime(注入当前 agent、host、os、model、channel 等真实环境快照,让模型别瞎猜自己在什么环境里)。
四、Token 都花在哪,以及能省的地方
把成本摊开看,最值得注意的是一个冗余。
工具信息在这份请求里其实出现了两次:
- 一次在 system prompt 的
Tooling段里(自然语言列表 + 短描述,作用是行为引导); - 一次在
body.tools[]里(每个工具的完整 JSON schema,作用是机器可读的调用定义,这个不能省)。
某次实测里,body.tools[] 约 6k–9.5k token,整段 system 约 8k–12.7k token,而两边的工具集合完全重合。也就是说,同一批工具,你为它的「描述」付了两遍钱——一遍给人看的引导,一遍给机器用的 schema。
(这里插一句区分:原文那次实测是 31 个工具,还包含作者自己装的 camofox_* 反检测浏览器插件。工具数量取决于你装了什么,不是固定值,别拿 31 这个数去套自己的环境。)
所以如果你要给 prompt 瘦身,优先级大致是:
- 压缩 system 里的工具说明——只保留调用规则,别逐个复述工具描述(
body.tools[]里的 schema 已经是权威定义)。 - 管住工作区文件——尤其
MEMORY.md,定期精简,别让它无限膨胀。 - 裁剪 Skills / Memory 的注入策略——不是所有技能索引都需要每轮都在。
body.tools[] 的 schema 本身别动,那是调用必需的。
五、两个反直觉的点
拆到最后,有两个容易想错的地方值得单独点出来。
其一:触发 compact 压缩,不会压 system prompt。 很多人以为上下文一压缩,这一万多 token 的底噪也会跟着缩水。不会。compact 压的是会话消息历史(旧对话、大的工具结果),而 system prompt 每轮都按当前配置重新构建——它甚至可能因为你新增了配置而变得更大。这条纠正很重要:想省钱,得去改 system 段和工具定义本身,指望 compact 顺手帮你瘦身是错的。
其二:subagent 的 prompt 是精简版。 你 spawn 出去的子代理,拿到的 prompt 明显更小:Project Context 里只注入 AGENTS.md 和 TOOLS.md(其余六个文件被过滤掉),工具也少了一批(会话编排和记忆检索类的,比如 sessions_*、memory_* 会被主动去掉)。这解释了第二篇那句「子代理看不到灵魂和身份」在成本层的道理——主代理背着完整人格和记忆干活,子代理只带一份工牌和工具箱去打工。 好处是子代理的上下文开销小得多。
我的理解与核验
我在整理本文时,先区分了“用户输入很短”和“模型收到的请求很短”这两件事。真正影响长期成本的,通常不是一句用户消息,而是每轮重复注入的工作区文件、工具说明和 schema。排查成本时,先看 /context 命令的真实构成,再决定是否裁剪文件或 Skills,比凭经验删除内容更稳妥。
文中 16k、工具数量和 Token 占比都用于说明结构,不应直接拿来估算自己的账单;实际结果要以当前模型与当前工作区测量值为准。
小结
这一篇把前三篇一直在「拼装」的那个 system prompt,真正抓出来数了一遍。结论可以浓缩成三句:
- 它很大,而且每轮都在。 一句「hi」就带 16k 量级的底噪,因为身份、工具、安全准则、工作区文件都要每轮重新塞给模型。
- 它的成本有明确的大头和明确的冗余。 大头是全文注入的工作区文件(尤其
MEMORY.md),冗余是 system 段和body.tools[]里重复了两遍的工具信息。 - 想省,得改对地方。 compact 不压它,subagent 天生比它小;真正的杠杆在工作区文件的体量和工具说明的裁剪。
回到系列的主线。前三篇反复讲 OpenClaw「把约束做进结构」——lane 队列、控制平面、记忆文件。这一篇揭示了这种做法的账单:当你把身份、安全、工具、记忆全部硬编码进每一轮的 system prompt,你换来的是模型「开箱即懂」,付出的是一笔每轮都要重付的固定开销。 结构化的约束不是免费的,它的价格就印在每一次请求的 token 账单上。看得见这张账单,才谈得上优化它。
到这里,本系列前四篇讲的都是单个 agent。下一篇《OpenClaw 如何运行多 Agents》进入多 agent:一个主 agent 怎么把任务派给专精的子 agent,又靠什么在并行放养时不失控。
参考资料
- 岚叔《深度解析 OpenClaw 万字系统提示词构成》实测拆解(原始来源:X 上 LufzzLiz 的 thread)
- OpenClaw 官方文档:System prompt | Context | Token use and costs
- 本系列上一篇:OpenClaw 控制平面深度解析:Gateway 如何用 WebSocket 统一多端 | 记忆系统:OpenClaw 记忆系统深度解析:Markdown 存储、混合检索与压缩 | 第一篇:OpenClaw 技术架构深度解析











