前言
很多人在体验 OpenClaw 几天之后,直呼Agent好用,但是token太贵。如果你打开输入命令行开关/usage full,每次输出末尾附带的数万 token 消耗记录,常常会让人倒吸一口冷气。有人说,招呼一句 “Hello” 就消耗了几美元的 token,虽然有些夸张,但也不算完全离谱。

这种花钱如流水的现象,背后有两层原因。第一层原因确实来自 Agent 系统本身。像 OpenClaw 这样的系统,在每一轮对话中都要注入大量上下文,例如用户习惯、系统约束、工具列表等。这是 Agent 与普通聊天模型最大的区别之一。这种上下文注入并不是缺点,而是 Agent 能持续工作的必要条件。第二层原因往往才是真正的 token 消耗大户:**当前主流的 Agent 执行模式——Function Calling。**在这种模式下,Agent 常常在错误中不断尝试调用工具,形成一种类似“鬼打墙”的循环,每一次尝试都在燃烧新的 token。
被困在“盒子”里的 AI Agent
在传统软件工程中,为了可维护和可追溯,系统接口通常必须是强类型、可验证的。无论是 REST API 还是 GraphQL,本质逻辑都很类似:
你必须提供一个精确的结构化输入,否则请求将被拒绝。
这种思维方式已经在软件工程中存在了几十年。2022 年底 ChatGPT 出现之后,早期开发者很快遇到一个问题:LLM 的输出是概率性的文本,而传统程序接口要求严格结构化数据。
于是最早的工程实践通常是这样的:
在 System Prompt 中要求模型:
请务必只输出 JSON,格式如下……
但 LLM 并不总是严格遵守格式,它可能输出:
好的,这是你要的 JSON:
{
...
}
或者把 JSON 包在 Markdown 代码块中。结果是后端解析程序经常崩溃。
为了解决这个问题,OpenAI 在 2023 年推出了 Function Calling。模型在判断需要调用工具时,会输出一个特殊的 tool call token,并生成符合 schema 的 JSON 参数。
例如一个简单的天气查询工具:
{
"name": "get_weather",
"description": "查询特定城市的实时天气",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "城市名,如北京" },
"unit": { "type": "string", "enum": ["celsius", "fahrenheit"] }
},
"required": ["city"]
}
}
当你问:“今天卢森堡冷吗?”模型会输出:
{
"name": "get_weather",
"arguments": "{\"city\": \"Luxembourg\", \"unit\": \"celsius\"}"
}
你的服务器收到这串 JSON,解析出 city=“Luxembourg”,然后调用外部的天气 API,拿到数据后,再把结果发回给 AI,让它用人话翻译给你。
Function Calling 的设计目标其实是解决三个工程问题:
- 结构化调用
- 参数验证
- 工具边界控制
它让 LLM 更容易接入传统软件系统。但在 Agent 场景中,这种方式也带来了新的问题:
静态性:函数 schema 是预定义的。如果 Agent 想临时组合复杂逻辑,就必须新增函数。
上下文成本:为了让模型记住这一堆复杂的 JSON 规则,你必须在每一轮对话中都带上那份冗长的“填表指南”,大量挤占 AI 的上下文窗口。换句话说,这就是在烧你的 Token。
错误反馈有限:如果函数调用失败,模型通常只能看到一个 HTTP 错误,例如:
400 Bad Request模型很难准确理解错误原因,只能尝试猜测新的参数组合。每一轮尝试,都是在燃烧你的钱包。
Function Calling 的设计目标其实是降低 LLM 与传统软件系统之间的集成成本。它让只会写简单后端的开发者,通过填 JSON 就能做出“看起来很聪明”的应用。它实际上是在用“离散的、点状的”传统逻辑,去强行适配“连续的、流式的”神经网络。Agent本来是 Token 流,可以编排无限种可能的组合。但现在它被困在一个盒子里,左右掣肘。Function Calling 不是为了让 AI 变聪明而发明的,它是为了让 “传统的、死板的代码能听懂 AI 的话” 而发明的一个中间层。它的本质是传统程序员对 AI 这种“不确定性能量”的一次集体防御和妥协。
Agent 工具接口的演化
从架构角度看,Agent 的工具接口其实经历了一个演化过程。
最早的模式非常简单:
User
↓
LLM
↓
Answer
后来加入了工具调用:
User
↓
LLM
↓
Tool Call (JSON)
↓
API
↓
LLM
而最近越来越多系统开始探索另一种方式:
User
↓
LLM
↓
Command Text
↓
Execution Environment
也就是让 LLM 直接生成文本命令。这就是 CLI 模式。
50 年前的因与50 年后的果
最近在 Reddit 上有一篇讨论热度极高的帖子:来自一位Manus(已被 Meta 收购)的前后端负责人 MorroHsu,在构建了两年顶尖 Agent 之后,给出的硬核结论——在很多 Agent 场景中,CLI 接口往往比 Function Calling 更自然。。
为什么会这样?因为这里有一个惊人的物理共鸣: Unix 在 50 年前提出了一个极其重要的设计原则:“一切皆文本流”。程序之间通过管道符(|)互相倾听。而 LLM 在 50 年后做出了同样的选择:“一切皆 Token”。
Unix的核心原则是“一切皆文本流 (Everything is a text stream)”。Unix命令之间不交换复杂的二进制结构,而是通过文本管道 (|) 互相倾听。前一个命令的输出可以作为下一个命令的输入,将命令群优雅地串连起来得到精确结果。而 LLM 在 50 年后做出了同样的物理选择:“一切皆 Token”。AI 的思考是文本,行动是文本,接收的反馈也必须是文本。
当前Transformer架构的LLM本质上最擅长的是预测下一个token,而不是填写一张复杂的JSON表格结构。各种超参数,比如温度,会影响它的稳定输出。而JSON的宽容度又很差,结尾没有带"}",或者当中缺了一个",",都会被判失效,返回没有任何指导意义的错误结果。Agent只能凭着感觉一试再试,你的Token自然就如流水一般被消耗了。当 LLM 需要生成复杂 JSON schema 时,实际上就是在做一件并不擅长的事情:维护严格结构层级。
CLI则完全不一样。它是由意义明确的精简单词构成,天然顺应当前大语言模型的“预测下一个Token"特性。它遇到不明确的调用不会报错,而是列出所有可用的命令参数,对AI也是点菜一般丝滑。最后,即使调用有问题,它的错误输出也会指出下一步修正的目标,AI不会象无头苍蝇一样乱试。这种调用方式构成连续的“语义力场”,每一步都是都是 “语义反馈网络”。AI Agent不再是被困在盒子里,而是徜徉在一个 “语义空间”。每一个命令名、每一个错误提示、每一个输出页脚,都是这个空间里的一个坐标点。每个结果都是一个 “路标”,展示下一步的 语义方向。AI 顺着这个路标,就能瞬间从“探索态”进入“执行态”。因此,当它生成一条命令时:
ls -la | grep id_ed25519
它只用选择合适的词汇组合。这恰好是 LLM 最擅长的任务。
命令语义网络探索:让 AI 自己找路
很多现代用户已经习惯了图形界面,很少接触命令行。但对于 AI 来说,CLI 反而是一种非常自然的交互方式。在 Linux 或 macOS 终端中,如果你输入:
grep --help
系统会输出完整参数说明。如果输入错误参数:
grep --abc
系统通常会返回提示信息,例如:
invalid option -- 'abc'
Try 'grep --help'
这种错误信息往往包含修正提示。AI不需要自己去猜,自然就知道下一步要怎么修正调整。对 AI 来说,这意味着一种非常重要的能力:启发式导航。AI 不需要提前加载所有文档,它可以:
- 尝试命令
- 阅读帮助信息
- 修正参数
- 再次执行
每一步输出都会成为下一步的语义提示。这种“按需披露”保护了上下文窗口。
另外,每个命令执行完后,会带上 类似[exit:0 | 12ms]这样的返回结果。这让 AI 对任务的 “物理成本” 和 “结果状态” 有了实时的反馈,它会学着变得更聪明(更省时间或者Token)。
读、洗、算、存:一行指令的暴力美学
更深一步来说,CLI 赋予了 AI 编排“物理流水线”的权力。举个例子:你的指令是:“分析今天日志里报错最多的 3 个 IP 地址,并存入报告。” 在传统模式下,AI 没有“管道”这个概念,它必须碎步前行:
read_file
→ LLM 分析
→ filter
→ LLM 再处理
→ write_file
Function Calling 模式中,AI 扮演了 “搬运工”。它必须把沉重的数据搬来搬去,既慢又容易出错。
在CLI模式下,AI 通过一行命令就能完成这套动作:
cat access.log | grep "ERROR" | awk '{print $1}' | sort | uniq -c | sort -nr | head -n 3 > report.txt
这条命令实际上完成了四个动作:
- 读 (Read):cat access.log(从磁盘读取原始数据流)。
- 洗 (Clean/Filter):grep “ERROR”(物理剔除无关信息)。
- 算 (Compute):awk/sort/uniq(执行频率统计和排序逻辑)。
- 存 (Store):> report.txt(将物理结果落盘)。
CLI 模式下,AI 只提供了 “逻辑配方”。数据的读写和计算,物理上都发生在 Linux 内核和内存管道中。数据流从未离开过执行环境,只有最终的“3 个 IP 地址”这个极简结果被传回给 AI。AI 不再只是一个“点一下动一下”的木偶,它变成了一个 “车间主任”。它只需要构思出那一串管道符连接的指令,就能在物理世界中一次性引发一连串的连锁反应。而这种编排下一个指令,和预测下一个Token没有任何区别,正是大模型天然熟悉的。更何况,AI 只提供了“逻辑配方”,不需要搬运数据。 指令越长,AI 在物理世界中引发的改变就越深,而它消耗的认知能量(Token)反而越少。这就是对 Token 焦虑的物理降维打击。
尾声:权力的物理移交
为什么说CLI才是AI Agent的母语?因为它把 “动作的选择” 降级为了 “词汇的选择”。AI 对单词的掌握是天生完美的。让它在 100 个复杂的 JSON 结构里选一个(容易错),和让它在写一段话时选一个合适的动词(它最擅长),两者的认知损耗完全不在一个量级。
选择CLI,是把“接口定义权”从人类程序员物理性地移交给 AI。我们不给它设限,我们只给它一把名为 CLI 的利刃。这是一种 “开放式创作”。AI 的面前只有一张白纸(一个单一的输入框)。AI 想要读文件,就写 cat;想要搜索,就写 grep。这里的 run 不是一个工具,它是一个 “物理通道 (Pipe)”。这就是为什么 Manus 的后端负责人敢说“放弃 Function Call”。因为他发现,与其费劲心思教 AI 怎么当个循规蹈矩的填表员,不如给它一把名为 CLI 的手术刀,让它去解剖整个系统。
智力不是大模型的属性,而是物理环境赋予它的敏捷性。当你不再把 AI 关在 JSON 的格子里,而是让它在流动的文本流里进行“主动狩猎”时,你会发现,它不仅变聪明了,还帮你省下了大把的真金白银。如果你也深受 Token 消耗之苦,是时候拆掉那些“死板的盒子”,给你的 AI 一条通往 Linux 的管道了。