Clawdbot 后来更名为 OpenClaw,是一个面向自动化任务的开源 AI Agent。它能调用浏览器、Shell、文件系统、记忆检索、接口请求等工具,把一个自然语言任务拆成多个步骤执行。
这种能力的代价也很明显:Token 消耗很容易失控。简单问候可能就要一万多 Token;一旦进入多轮工具调用、错误重试和反思修正,单个任务突破几十万 Token 并不罕见。极端情况下,一周消耗上亿 Token 也不是架构上不可能发生的事。
问题不只是“模型贵”,而是 Agent 的执行方式决定了它会反复携带大量上下文。理解这一点,才能知道钱花在了哪里,也才能知道哪些优化真的有用。
Token 成本为什么会突然变大
Clawdbot/OpenClaw 的成本主要来自四类开销:
flowchart TD
A[一次用户任务] --> B[系统提示词固定开销]
A --> C[ReAct 多轮推理循环]
A --> D[工具执行结果回灌]
A --> E[错误后的反射重试]
B --> B1[身份定义]
B --> B2[工具 JSON Schema]
B --> B3[Skills 和引导文件]
B --> B4[运行时元数据]
C --> C1[每一轮都携带历史上下文]
D --> D1[网页 HTML]
D --> D2[文件内容]
D --> D3[命令输出]
D --> D4[API JSON 响应]
E --> E1[失败分析]
E --> E2[重新规划]
E --> E3[再次调用工具]
这些开销叠加在一起后,会形成一种近似二次方增长的成本曲线。任务轮次越多,每一轮携带的历史越长,下一轮请求就越贵。
一个大致的消耗量级如下:
| 场景 | Token 消耗量级 | 费用量级 | 特点 |
|---|---|---|---|
| 基础对话初始化 | 约 14,500 | 约 0.04 - 0.05 | 主要花在系统提示词和工具定义 |
| 简单查询,无缓存 | 约 15,000 | 约 $0.055 | 用户输入很短,固定开销占主导 |
| 多轮工具调用任务 | 100,000 - 500,000 | 约 0.30 - 1.50 | 每轮都带历史和工具结果 |
| 复杂工作流,含反射循环 | 1,000,000+ | 约 3 - 10 | 错误重试会快速放大上下文 |
| 失控任务 | 10,000,000+ | 数百美元 | 缺少预算上限时容易发生 |
费用会随模型、输入输出比例、缓存命中率而变化,但增长机制是一样的:固定提示词很大,历史上下文不断累积,工具结果又经常很长。
固定系统提示词:一次问候也要背上完整装备
AI Agent 和普通聊天机器人最大的区别,是它通常不只回答问题,还要决定是否调用工具、调用哪个工具、工具参数怎么填、失败后怎么恢复。为了让模型知道这些能力,系统提示词里需要塞入大量说明。
Clawdbot/OpenClaw 的一次请求通常会包含类似结构:
System Prompt
├── 核心身份与行为规范
│ └── 说明 Agent 的角色、能力边界、回复风格
├── 工具定义列表
│ ├── bash
│ ├── browser
│ ├── file_system
│ ├── memory_search
│ └── 其他工具
├── Skills 元数据
│ └── 可用技能、触发条件、描述信息
├── 引导文件
│ ├── AGENTS.md
│ ├── SOUL.md
│ ├── TOOLS.md
│ └── USER.md
├── 运行时元数据
│ ├── 当前时间
│ ├── 时区
│ ├── 主机信息
│ └── 模型配置
└── 回复格式与安全约束
其中最重的一部分通常是工具定义。Clawdbot/OpenClaw 使用 MCP(Model Context Protocol,模型上下文协议)描述工具。每个工具都要告诉模型:工具叫什么、能做什么、参数有哪些、每个参数是什么类型、哪些字段必填。
一个简化后的 bash 工具定义类似这样:
{
"name": "bash",
"description": "Execute shell commands in a controlled environment.",
"input_schema": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "The shell command to execute."
},
"timeout": {
"type": "integer",
"description": "Maximum execution time in seconds."
}
},
"required": ["command"]
}
}
单个工具定义看起来不长,但 20 多个工具一起放进系统提示词后,很容易达到数千 Token。再加上身份说明、技能元数据、引导文件和格式约束,基础系统提示词可能接近 14,000 Token。
这意味着用户只输入“你好”,请求里也可能要带上完整工具手册。用户输入越短,固定开销占比越夸张。
ReAct 循环:每一轮都要重新携带历史
Clawdbot/OpenClaw 这类 Agent 常用 ReAct(Reasoning and Acting,推理与行动)模式。模型不是一次性给答案,而是反复执行:
- 思考当前任务应该怎么做;
- 选择一个工具;
- 调用工具;
- 观察工具结果;
- 基于结果继续推理或结束任务。
调用过程可以表示成这样:
sequenceDiagram
participant U as 用户
participant A as Agent/LLM
participant T as 工具系统
U->>A: 提交任务
A->>A: 读取系统提示词与历史上下文
A->>T: 调用工具 Action
T-->>A: 返回 Observation
A->>A: 基于结果继续推理
A->>T: 再次调用工具
T-->>A: 返回新的 Observation
A-->>U: 输出结果
关键点在于:当前主流 LLM(Large Language Model,大语言模型)API 通常要求每次请求都发送完整上下文。第二轮请求不是只发送“上一轮工具结果”,而是要把系统提示词、用户任务、前面的推理、前面的工具结果一起带上。
假设:
S:系统提示词大小;U:用户任务大小;A:每轮模型输出大小;R:每轮工具返回结果大小;N:任务执行轮数。
第 k 轮输入大约是:
S + U + (k - 1) × (A + R)
整个任务的总消耗大约是:
总输入 ≈ N × (S + U) + (A + R) × N × (N - 1) / 2
总输出 ≈ N × A
总 Token ≈ N × (S + U) + (A + R) × N × (N - 1) / 2 + N × A
这个公式说明了一个重要事实:轮数增加时,成本不是简单线性增长。只要每轮都保留完整历史,累积输入就会出现二次方级别的增长。
举个简化例子:
S = 14,000 # 系统提示词
U = 50 # 用户任务
A = 400 # 每轮模型输出
R = 2,500 # 每轮工具结果
N = 10 # 10 轮推理/工具调用
总输入 ≈ 10 × 14,050 + 2,900 × 45
≈ 140,500 + 130,500
≈ 271,000
总输出 ≈ 4,000
这还只是中等大小的工具结果。如果工具返回网页 HTML、日志文件或大段 JSON,R 会明显变大,成本也会继续放大。
工具结果回灌:真正容易被忽略的 Token 黑洞
很多 Agent 任务贵,不是因为模型“想得太多”,而是因为工具返回得太多。
常见工具输出规模如下:
| 工具类型 | 典型返回内容 | Token 量级 |
|---|---|---|
| 浏览器抓取 | 页面正文、DOM、HTML、链接、脚本片段 | 5,000 - 20,000 |
| 文件读取 | 代码文件、配置文件、日志文件 | 1,000 - 10,000 |
| 数据库查询 | 多行结果集、字段名、嵌套结构 | 2,000 - 15,000 |
| Shell 命令 | stdout、stderr、堆栈信息 | 500 - 5,000 |
| API 调用 | JSON 响应、分页数据、错误详情 | 1,000 - 8,000 |
| 搜索工具 | 多条结果标题、摘要、URL | 2,000 - 10,000 |
浏览器工具尤其容易制造大上下文。用户可能只需要网页中的一句航班价格信息,但工具返回的是整个页面结构。模型下一轮请求又会携带这段页面内容,后续每一轮都继续背着它走。
一个典型任务流程可能是:
flowchart LR
A[用户: 帮我比较航班] --> B[浏览器搜索]
B --> C[返回搜索页 HTML]
C --> D[模型分析]
D --> E[打开航司页面]
E --> F[返回页面 HTML/表单信息]
F --> G[模型继续分析]
G --> H[调用价格比较或代码工具]
H --> I[返回结果]
I --> J[生成答案或继续操作]
如果每一步都把完整结果放进上下文,Token 增长速度会非常快。
更合理的做法是让工具返回“模型真正需要的内容”,而不是原始结果全集。例如:
{
"results": [
{
"airline": "Example Air",
"price": 320,
"departure": "09:30",
"arrival": "12:40",
"url": "https://example.com/flight/123"
}
],
"omitted": {
"raw_html": true,
"reason": "HTML content is too large and not needed for comparison."
}
}
Agent 框架如果默认把原始结果完整回灌,成本会非常难控。工具层做字段筛选、截断、摘要和分页,是控制 Token 的关键手段。
反射循环:错误会把成本继续放大
Agent 执行任务时不可避免会遇到错误,例如网页元素定位失败、命令执行失败、接口返回异常、文件路径不存在。Clawdbot/OpenClaw 这类系统通常会通过反射循环恢复,也就是让模型分析失败原因,然后重新规划下一步。
普通路径是:
Plan → Act → Observe → Done
出错路径会变成:
Plan → Act → Error → Reflect → Retry → Error → Reflect → Retry → ...
反射本身要消耗 Token,因为模型需要读取错误信息、分析原因、提出修复方案。更麻烦的是,每一次错误和反思都会进入历史上下文,导致下一次请求更长。
AgentBench 一类评测中的数据能体现这个趋势:
| 反射轮数 | 平均 Token/任务 | 相对无反射 |
|---|---|---|
| 0 轮 | 约 12,800 | 1x |
| 3 轮 | 约 45,000 | 约 3.5x |
| 5 轮 | 约 136,000 | 约 10.6x |
| 7 轮 | 约 172,000 | 约 13.4x |
反射不是坏机制。没有它,Agent 很多复杂任务根本无法完成。问题在于反射不能无限重试,否则会出现“越失败,上下文越大;上下文越大,模型越难抓住重点;模型越容易继续失败”的循环。
合理的 Agent 应该给反射设置预算,例如:
| 限制项 | 建议 |
|---|---|
| 单个工具最大重试次数 | 2 - 3 次 |
| 单个任务最大反射次数 | 3 - 5 次 |
| 单次工具结果最大 Token | 按工具类型设置上限 |
| 单个任务最大 Token | 达到阈值后暂停并询问用户 |
| 错误摘要策略 | 保留关键错误,丢弃重复堆栈 |
为什么这些成本很难完全避免
Clawdbot/OpenClaw 的高 Token 消耗并不是某一个 bug 造成的,而是 Agentic 系统的常见代价。
API 上下文通常是“全量发送”
很多 LLM API 的请求模型是无状态的。服务端不会默认记住上一轮完整上下文,客户端必须在每次请求里重新提交历史消息。
这带来几个结果:
| 情况 | 成本影响 |
|---|---|
| 只追问一句话 | 仍然要携带前面的对话历史 |
| 只改一个工具参数 | 仍然要携带系统提示词和工具定义 |
| 只需要工具结果的一小段 | 如果没有裁剪,完整结果会进入上下文 |
| 多轮任务持续执行 | 每一轮请求都会越来越大 |
Prompt Caching 可以降低重复前缀的计费,但它不等于“上下文不存在”。缓存内容通常仍然占用上下文窗口,也需要满足缓存命中条件。
Agent 为“能力最大化”设计时,成本会自然升高
很多通用 Agent 默认追求“什么都能做”,于是会启用大量工具、加载完整技能库、保留详细历史、使用能力最强的模型。
这种设计适合探索性任务,但不适合成本敏感场景。
| 设计选择 | 好处 | 成本问题 |
|---|---|---|
| 默认加载 20+ 工具 | 模型随时能调用多种能力 | 工具 Schema 进入系统提示词 |
| 保留完整历史 | 模型不容易丢上下文 | 每轮输入持续变大 |
| 工具返回完整结果 | 信息不丢失 | 大量无关内容进入上下文 |
| 默认强模型 | 复杂推理更稳 | 单价更高 |
| 自动反射重试 | 失败后可恢复 | 错误会不断堆积 |
缺少硬预算时,任务容易跑飞
如果系统没有任务级预算,Agent 可能一直尝试“再试一次”。从用户体验看,它是在努力完成任务;从账单看,它是在持续消耗 Token。
预算控制至少应该覆盖三层:
flowchart TD
A[成本控制] --> B[请求级预算]
A --> C[任务级预算]
A --> D[会话级预算]
B --> B1[单次输入 Token 上限]
B --> B2[单次输出 Token 上限]
C --> C1[最大工具调用次数]
C --> C2[最大反射次数]
C --> C3[最大总 Token]
D --> D1[用户每日额度]
D --> D2[项目级费用上限]
没有这些限制,复杂网页任务、自动化表单任务、长日志分析任务都可能产生远高于预期的账单。
降低 Token 成本的几种有效办法
控制 Clawdbot/OpenClaw 的成本,不应该只靠“少用”。更实际的做法是减少重复上下文、减少无关工具、减少不必要的 ReAct 决策,并给任务设置边界。
启用 Prompt Caching,降低固定提示词成本
Prompt Caching 适合缓存稳定、重复出现的系统提示词和工具定义。对于 Clawdbot/OpenClaw 这种固定提示词很大的 Agent,缓存命中后可以显著降低重复前缀的费用。
示例配置:
agents:
defaults:
model:
params:
cacheControlTtl: "1h"
heartbeat:
every: "55m"
缓存的典型效果:
| 请求类型 | 成本特点 |
|---|---|
| 首次请求 | 需要写入缓存,可能比普通输入略贵 |
| 后续命中 | 缓存前缀按更低价格计费 |
| 长会话 | 固定系统提示词重复出现,节省更明显 |
| 提示词频繁变化 | 容易缓存失效,收益下降 |
使用缓存时要注意几个细节:
- 系统提示词前缀要稳定,工具顺序和内容频繁变化会导致缓存命中率下降;
- 缓存降低费用,不一定减少上下文窗口占用;
- 如果每次都动态注入大量不同文件,缓存收益会被稀释;
- 缓存 TTL 到期后需要重新写入。
用确定性工作流替代部分 ReAct 循环
有些任务不需要模型每一步都重新思考。例如固定的航班查询、价格比较、报表生成、接口同步,本质上是确定流程,只是输入参数不同。
这类任务可以用 Lobster 工作流引擎或类似机制,把多轮 LLM 决策改成预定义工具链:
workflow:
name: flight_booking
steps:
- tool: browser.search
input: "flights NYC to LAX {{date}}"
- tool: code.compare_prices
input: "{{previous_result}}"
- tool: api.book
input: "{{best_option}}"
ReAct 和确定性工作流的差异:
| 方式 | 决策者 | 适合场景 | 成本特点 |
|---|---|---|---|
| ReAct 循环 | LLM 每轮决定下一步 | 开放任务、路径不确定、需要复杂判断 | 成本随轮数快速增长 |
| 确定性工作流 | 配置好的流程决定下一步 | 流程稳定、步骤明确、输入结构化 | 工具链成本更可控 |
| 混合模式 | 关键节点由 LLM 判断 | 部分步骤固定,部分步骤需要推理 | 成本和灵活性折中 |
工作流不是为了替代所有 Agent 能力,而是把“本来就确定”的步骤从 LLM 编排里拿出来。只在真正需要判断的地方调用模型,Token 消耗会明显下降。
做上下文压缩,把历史变成摘要
长会话和多轮任务不能无限保留原始历史。上下文压缩的思路是:把已经完成的中间过程总结成关键状态,只保留后续任务还需要的信息。
示例配置:
agents:
defaults:
memory:
autoCompaction:
enabled: true
tokenThreshold: 50000
interval: 1800
也可以手动触发:
/compact
压缩前的上下文可能是:
用户任务
系统提示词
第 1 轮推理
第 1 次工具返回的完整 HTML
第 2 轮推理
第 2 次工具返回的完整 JSON
第 3 轮错误堆栈
第 4 轮反射分析
...
压缩后应该变成:
任务目标:比较指定日期从 NYC 到 LAX 的航班。
已知条件:
- 用户偏好:价格优先,直飞优先。
- 已排除:ExampleAir 09:30 航班,价格过高。
- 当前候选:DemoAir 12:10,$320;SampleAir 15:00,$350。
- 待完成:确认行李政策和退改签规则。
压缩会丢弃细节,所以不能把所有历史都粗暴摘要掉。适合保留的信息包括:
| 信息类型 | 是否保留 |
|---|---|
| 用户明确约束 | 保留 |
| 当前任务目标 | 保留 |
| 已经做出的关键选择 | 保留 |
| 工具返回的原始大文本 | 通常摘要 |
| 重复错误堆栈 | 只保留关键错误 |
| 临时推理草稿 | 大多可丢弃 |
精简工具集,减少系统提示词体积
如果一次任务只需要文件读取和 Shell,就没有必要把浏览器、数据库、邮件、日历、API 调用等工具全部暴露给模型。
示例配置:
agents:
defaults:
tools:
enabled:
- bash
- file_read
- memory_search
disabled:
- browser
- api_call
工具裁剪的收益很直接:工具越少,系统提示词里的 JSON Schema 越少,模型选择工具时的干扰也越少。
常见工具配置策略:
| 场景 | 推荐工具 |
|---|---|
| 代码仓库分析 | file_read、grep、bash |
| 网页信息检索 | browser.search、browser.extract |
| 数据处理 | file_read、python、bash |
| 知识库问答 | memory_search、file_read |
| 自动化业务流程 | 业务 API 工具、少量浏览器工具 |
更进一步的做法是延迟加载工具:默认只给模型核心工具,等模型判断需要某类能力时,再加载对应工具包。这样可以避免每次请求都带上完整工具宇宙。
对工具返回结果做裁剪
工具返回结果应该服务于下一步决策,而不是把原始数据完整塞给模型。不同工具可以设置不同的返回策略。
| 工具 | 推荐处理 |
|---|---|
| 浏览器 | 提取正文、标题、表格、关键链接,避免返回完整 HTML |
| 文件读取 | 支持按行号读取、按函数读取、按关键词截取 |
| Shell | 限制输出行数,长输出写入文件并返回摘要 |
| 数据库 | 限制行数,返回 schema 和样例,避免一次吐出大结果集 |
| API | 过滤字段,只返回业务相关字段 |
| 搜索 | 控制结果数量,返回标题、摘要、URL 即可 |
例如 Shell 工具可以做输出限制:
tools:
bash:
maxOutputTokens: 2000
truncateStrategy: tail
日志分析时通常更需要尾部错误信息,而不是完整日志。让工具层按场景裁剪,比让模型在几万 Token 的原始输出里自己找重点更省钱,也更稳定。
使用模型路由,不要所有任务都上强模型
不同任务对模型能力要求不同。简单查询、格式转换、工具参数生成,不一定需要最贵模型;复杂规划、长上下文推理、关键决策,才更适合强模型。
示例配置:
agents:
defaults:
model:
routing:
simple_queries: "claude-sonnet-4"
tool_execution: "claude-sonnet-4"
complex_reasoning: "claude-opus-4-5"
模型路由可以按任务类型划分:
| 任务类型 | 推荐模型策略 |
|---|---|
| 简单问答 | 便宜模型 |
| 工具参数生成 | 中等模型 |
| 代码解释 | 中等或强模型,视代码复杂度而定 |
| 长链路规划 | 强模型 |
| 失败反射 | 中等模型起步,多次失败再升级 |
| 最终用户回复润色 | 便宜模型或中等模型 |
如果强模型和中等模型之间有 5 倍价差,正确路由就能明显降低账单。更稳妥的策略是“默认便宜,必要时升级”,而不是所有请求都走最高规格。
一套更稳的成本控制组合
单个优化手段有用,但组合起来效果更明显。一个成本敏感的 Clawdbot/OpenClaw 配置可以遵循这样的思路:
flowchart TD
A[用户任务进入] --> B{任务是否有固定流程}
B -- 是 --> C[走工作流引擎]
B -- 否 --> D[走 ReAct Agent]
C --> E[只在关键节点调用 LLM]
D --> F[加载最小工具集]
F --> G[工具返回结果裁剪]
G --> H{上下文是否超过阈值}
H -- 是 --> I[压缩历史上下文]
H -- 否 --> J[继续执行]
I --> J
J --> K{是否超过任务预算}
K -- 是 --> L[暂停并请求用户确认]
K -- 否 --> M[输出结果]
推荐的组合策略:
| 优化项 | 解决的问题 | 预期收益 |
|---|---|---|
| Prompt Caching | 系统提示词重复计费 | 固定前缀成本大幅下降 |
| 工具裁剪 | 工具 Schema 过大 | 系统提示词变短 |
| 工具结果裁剪 | HTML、日志、JSON 过长 | 历史上下文膨胀变慢 |
| 上下文压缩 | 多轮历史越来越长 | 长任务更可控 |
| 工作流引擎 | 固定流程被 LLM 反复决策 | 避免不必要的 ReAct 循环 |
| 模型路由 | 简单任务使用昂贵模型 | 降低平均单价 |
| 任务预算 | 反射和重试失控 | 防止账单意外扩大 |
使用 Clawdbot/OpenClaw 时的实践检查清单
上线或长时间运行前,至少检查这些配置:
- 系统提示词是否启用了缓存;
- 默认工具数量是否控制在任务真正需要的范围内;
- 浏览器、文件、Shell、API 工具是否有输出上限;
- 是否设置了自动上下文压缩阈值;
- 是否限制了单任务最大工具调用次数;
- 是否限制了反射重试次数;
- 是否按任务复杂度做模型路由;
- 是否给用户、会话、任务设置了 Token 或费用预算;
- 是否在预算耗尽前暂停,而不是继续自动重试。
Clawdbot/OpenClaw 的高 Token 消耗,本质上是通用 Agent 架构的成本体现:它把工具说明、历史上下文、工具结果和错误恢复都交给大模型处理。能力越通用,默认携带的信息越多;执行链路越长,重复发送的上下文越大。
真正的降本方向不是简单限制模型回答长度,而是减少不必要的上下文进入模型:稳定内容走缓存,固定流程走工作流,大工具集按需加载,长工具结果先裁剪,多轮历史及时压缩,错误重试必须有预算。这样才能在保留 Agent 自动化能力的同时,把 Token 消耗控制在可预期范围内。