Skip to content
Calvin's Blog

比 Function Calling 更重要的,是给 Agent 一条能自我修正的命令行

Mar 13, 2026 — AI, Agents, Tool

这条帖子标题很猛,最容易被转成一句口号:别给 Agent 一堆 function calling 了,直接上 run(command="...")

但把原帖和评论区都看完,我反而觉得重点不在“CLI 必胜”,而在另一层:对 Agent 来说,接口是否统一、操作能不能组合、失败后能不能顺着提示自己修正,很多时候比接口是不是严格类型化更重要。

评论区真正掰扯的,其实也就是三件事:工具要不要继续加、错误恢复到底重不重要、以及 shell 这条路的安全边界放在哪里。

原帖到底在讲什么

原帖的论证可以压成三层。

第一,Unix 的接口模型天然适合 LLM。Unix 世界里,一切围绕文本流、管道、退出码和 stderr 展开;LLM 世界里,输入输出本来也是 token 和文本。作者想说的不是 CLI 对模型“友好”,而是这套交互方式本来就和模型的工作介质一致。

第二,相比给模型一个很长的工具列表,给它一个统一的 run(command="...") 更容易稳定。因为模型不用先在 search_webread_filewrite_filerun_code 这些 API 之间切换心智,只要在一个命令空间里继续拼接字符串。catgrephead&&||| 这些模式,本来就是训练语料里密度很高的东西。

第三,真正让这个方案能跑起来的,不只是“把 shell 暴露出去”,而是围绕命令行补一层面向 Agent 的启发式设计。原帖里给了三类做法:

  1. 用渐进式 --help 让 Agent 自己发现命令和参数,而不是把整本说明书塞进 prompt。
  2. 让错误信息带方向感,不只是报错,还要告诉 Agent 下一步该怎么改。
  3. 统一输出格式,把 exit code、耗时和 stderr 稳定地暴露出来,让模型逐步学会什么是成功、什么值得重试、什么成本太高。

后面那部分“两层架构”也值得记下来。作者把“Unix 执行语义”和“给 LLM 看的输出层”拆开,避免在管道执行过程中提前截断、附加元数据,或者把二进制垃圾直接喂给模型。这已经不是观点了,更像踩坑后的经验总结。

更少的工具,通常是真的更好

有条评论提到,他们去年做过类似实验,最开始有 40 多个 typed function call,后来逐步收敛到 8 个左右。评论者并不完全认同“只保留一个 shell command”这个极端结论,但认同一个方向:工具越多,模型越容易在“该选哪个”上浪费推理预算。

这比原帖那种“只保留一个入口”的说法更容易落地。大多数团队未必需要真的退化成单一 run,但很可能都该问一句:我现在这套工具,到底有多少是能力边界需要,多少只是接口换了个名字?如果多个工具本质上只是同一类资源访问、过滤、组合和执行能力的不同包装,那继续加数量,通常不如先收一收。

大家认同的核心价值,其实是“可组合 + 可恢复”

评论区里还有个很实在的补充:typed function call 出错时,模型经常要先重新判断“我应该换哪个工具”;shell 风格接口出错时,模型往往只需要在同一个心智模型里调整命令、参数或者管道结构。

这点很关键。真正降低失败率的,不是命令行这三个字,而是统一语义下的连续修正能力。一次失败之后,模型最好不用退回“重新选工具”这一步,而是直接做局部修正。有人说,把大工具集压缩后,多步任务的失败率明显下降。我觉得这不一定是模型突然更聪明了,更像是接口让它少绕了几圈。

安全不是附属问题,而是这个方案的硬边界

评论区里最有价值的反对意见也很直接。有人提到他们在 staging 里试过“让 Agent 直接拿 shell 权限”,结果很快出过问题,连 rm -rf 这种清理动作都可能因为路径判断错误而越界。评论者最后的折中方案是:对外保留少量 typed tools,但工具内部仍然可以调度 shell 命令,把组合性留在系统内部,而不是完全暴露给模型。

这也说明,CLI 方案真正成立的前提不是“模型会自觉”,而是“你已经把 blast radius 压到可接受范围内”。如果没有隔离、配额、权限裁剪和可中断执行,CLI 的表达力会直接变成系统风险。这个问题不是靠 prompt 多写几条 NEVER 能解决的。

CLI 的优点,也可以被 MCP 和 typed tool 吸收

还有一类评论并不反对原帖的结论,但提醒了一点:原帖夸的很多优点,其实不一定非要靠 shell 才能获得。错误信息里带“Did you mean …”式的导航、渐进式暴露子工具、面对长输出时给后续分页入口,这些能力完全可以做进 MCP server 或者 typed tool 的返回协议里。

换句话说,原帖真正证明的,也许不是“Function Calling 不行”,而是很多现有 function calling 设计得太像给后端程序调用的 API,而不是给 Agent 用的接口。它们有 schema,却没有引导;有参数校验,却没有恢复路径;有类型,却没有组合感。

这也是我最认同评论区的一点:真正该淘汰的,未必是 typed tool,而是那种只对机器严谨、对 Agent 却不友好的工具设计。

一个还没解决的问题:模型真的会在乎耗时吗

还有条评论提了一个很具体的问题:即使把耗时信息打印出来,模型也不一定会因此学会并发规划或减少等待。评论者说,他在自己的 agent terminal 里也加了 duration 和相关指令,但在 Claude Opus 4.6 和 GPT-5.4 上,真正能稳定利用这些信息的比例仍然不高。

这个观察给原帖里“统一输出格式能让 Agent 越用越聪明”补了一个保留条件。输出一致当然有帮助,但帮助的上限可能取决于模型训练目标里有没有真正优化 wall time、并发收益和项目推进效率。如果底层奖励函数不关心这些事,单靠在输出末尾补一行 [exit:0 | 3.2s],效果未必像我们想得那么大。更准确地说,这类设计是在给模型机会利用信号,而不是只要信号放在那里,模型就会自动变好。

如果让我给 Agent 设计工具接口,我会怎么选

读完这串讨论,我自己的取舍也很明确:优先追求“少而统一”的工具系统,但别把“只有一个 shell 入口”当成教条。更实际的做法通常是四条:

  1. 先压缩工具数量,把语义重复的工具并起来,减少模型做工具选择题的次数。
  2. 尽量让工具具备组合感,不管是 shell pipe、分页 continuation,还是更细的子命令体系,本质上都在降低多步任务的拆解成本。
  3. 把错误恢复当成一等公民,help、stderr、替代路径、边界提示都要能直接指导下一步,而不是只报错。
  4. 默认按高风险系统来设计隔离层。命令执行越通用,外部安全约束就得越强。

如果这四条做到了,外层到底更像 CLI,还是更像带状态和 breadcrumb 的 typed tool,反而没那么重要。

结语

这篇帖子会火,不只是因为标题够猛,而是因为它戳中了很多 Agent 系统都在碰的真问题:工具不是越多越强,接口也不是越类型化越好。

对 Agent 来说,最好用的接口通常有三个特征:统一、可组合、能自我修正。CLI 只是目前最接近这三个特征的一种成熟范式,所以看起来特别顺手。

但如果把这件事理解成“以后不要 Function Calling,只要 shell”,判断就太粗了。更准确的说法应该是:

我们需要的不是某一种神圣工具形态,而是一套真正按 Agent 工作方式设计出来的接口。