从 Code Agent 到 Computer Use,看 Agent 工具接口如何从底层 API 走向语义动作。
导语
Agent 做事的能力,并不只取决于底层模型有多强。模型要进入真实工作流,必须通过工具读文件、改代码、点界面、查数据、调用系统能力。工具接口如果含糊、粗糙、返回值失控,再强的模型也会在错误的观察里绕圈。
过去两年,很多 Agent 系统的瓶颈从"模型会不会调用工具"转向"工具是否适合模型使用"。这不是一个纯粹的 API 设计问题,而是 Agent Runtime 的接口工程:工具的粒度、命名、返回值、错误反馈和安全边界,都会改变模型的决策路径。
这篇文章先讨论两个最有代表性的演进场景:Code Agent 和 Computer Use Agent。前者说明,代码仓库不能只当文本检索库来处理;后者说明,桌面操作也不能只靠截图和坐标点击。两个故事最后指向同一个判断:面向 Agent 的工具接口,需要从"底层能力暴露"升级为"语义动作设计"。
Code Agent:从 RAG 到 ACI 的接口重构
图:Code Agent 的工具接口从文本检索走向交互式语义操作。
Code Agent 是最早暴露工具接口问题的场景之一。代码仓库足够复杂,任务又能用测试验证,所以它天然适合观察"同一个模型,换一种接口,结果会不会变好"。
SWE-agent 的实验把这个问题讲得很清楚。它不是简单地追求更强模型,而是把同一个 GPT-4 放在不同接口下比较。结果说明,工具接口本身就能显著改变修复真实 GitHub issue 的成功率。
RAG 阶段:把仓库当只读文本
早期做法很像问答系统:仓库太大,不能全部塞进上下文,就用 RAG 检索 Top-K 文件,把"看起来相关"的片段拼进 prompt,再让模型生成修改。
这条路的问题很直接:检索是一次性的,模型没有真正进入仓库。它不能主动探索目录,不能跑测试,不能根据报错回头修正。只要第一轮检索漏掉关键文件,后面的生成就建立在错误上下文上。
图:RAG 只能完成一次性检索,缺少交互式补救路径。
RAG 的价值是降低上下文压力,但它把"定位问题"这个动态过程压成了静态检索。对真实代码任务来说,这通常不够。
Shell-only 阶段:让 Agent 自己探索
第二阶段把仓库交给 Agent,让它用 Linux shell 自己查文件、读代码、跑测试。模型可以 ls、cd、grep、cat,也可以在 ReAct 循环里根据新反馈调整方向。
这一步打开了 RAG 的死局。定位不再依赖一次检索,模型可以像开发者一样逐步缩小范围。SWE-bench Lite 上,GPT-4 从 RAG 接口下的 2.67% 成功率,提升到 Shell-only 下的 11.00%。
但裸 shell 的问题也跟着出现。它"什么都能做",并不代表"适合 Agent 做"。
| 任务 | 裸 Shell 常见做法 | 对 Agent 不友好的地方 |
|---|---|---|
| 查文件 | ls |
|
、cd、grep -R、find |
结果容易过长,噪声高;模型还要自己判断哪些路径值得继续看 | |
| 读文件 | cat |
|
| 打印整文件 | 大文件会淹没关键片段;缺少稳定的窗口、分页和行号定位 | |
| 改文件 | 重定向覆盖、sed 替换 |
多行编辑笨重;正则误伤不容易当场发现;修改后反馈不足 |
Shell-only 比 RAG 更灵活,但它把太多底层操作细节丢给模型。模型要一边推理业务问题,一边记住 shell 语法、正则转义、路径状态和输出截断。这些负担会占掉本应用来理解代码的注意力。
ACI 阶段:为 Agent 定制代码操作界面
SWE-agent 的第三阶段是在 shell 上增加定制 ACI,也就是 Agent-Computer Interface。它没有取消 shell,而是把高频、易错、需要结构化反馈的动作重新封装。
| ACI 工具 | 解决的问题 | 关键设计 |
|---|---|---|
find |
||
/search |
文件定位和代码搜索噪声过大 | 区分按文件名查找和按关键词搜索,限制结果数量 |
窗口化 read |
大文件一次性塞满上下文 | 每次只读固定窗口,保留行号和翻页能力 |
单命令 edit |
sed |
|
| 、重定向容易误伤 | 使用精确字符串替换,编辑后立即反馈,非法修改当场拒绝 | |
| shell 兜底 | 专用工具覆盖不了所有情况 | 保留通用执行能力,避免接口不完备 |
这里的关键不是"多做几个命令",而是把 Agent 的常见失败点变成接口约束。工具帮模型省掉机械负担,让它把注意力放回任务本身。
SWE-agent 最后提炼出的 ACI 思路可以概括为四点:动作要简单,返回要紧凑,反馈要足够但不啰嗦,guardrail 要能阻止错误继续传播。SWE-bench Lite 的结果也支持这个方向:RAG 2.67%,Shell-only 11.00%,定制 ACI 18.00%。只换 Func 定义接口,不换模型,差异已经很大。
Computer Use:从坐标点击到语义工具
图:Computer Use Agent 不必把所有任务都翻译成坐标点击。
Computer Use Agent 面对的是另一类环境:桌面、浏览器、办公软件、播放器、文件管理器。最直接的想法是让 Agent 像人一样看屏幕,然后移动鼠标、点击、输入。
这个方向很有吸引力,因为 GUI 是最通用的接口。只要人能操作的软件,Agent 理论上也能操作。但通用性和稳定性经常是反向的。屏幕截图能提供视觉信息,却很少直接告诉模型"当前任务最应该调用哪个业务动作"。
GUI-only 阶段:用截图和坐标模拟人
OSWorld 这类基准把桌面任务交给 Agent:观察是整屏截图,动作是 pyautogui 风格的鼠标和键盘命令。
| GUI 动作 | 含义 |
|---|---|
moveTo(x, y) |
把鼠标移动到指定坐标 |
click(x, y) |
点击屏幕坐标 |
write("text") |
在当前光标处输入文本 |
press("enter") |
按下 Enter |
hotkey("ctrl", "c") |
执行快捷键 |
scroll(200) |
滚动页面 |
dragTo(x, y) |
拖拽到目标坐标 |
这套接口的优点是完备。缺点也很明显:它过于低层。模型要从截图里识别控件位置,推断状态,再把意图翻译成坐标动作。分辨率、窗口位置、弹窗、遮挡、语言环境、焦点状态,都会让同一个任务变得不稳定。
OSWorld 的早期结果很能说明这个难度:369 个真实任务上,人类能做到 72.36%,当时最好的 VLM 只有 12.24%。差距不是单纯因为模型不会思考,而是 GUI-only 接口把太多无关变量压给了模型。
GUI + MCP 阶段:把高频动作升成语义接口
OSWorld-MCP 的方向是给桌面软件叠加语义化工具。Agent 仍然可以看屏幕,但常见操作不再依赖坐标点击,而是通过 MCP 工具直接完成,比如对 VS Code、LibreOffice、Chrome、VLC、Ubuntu 系统能力做结构化封装。
图:GUI 与 MCP 结合后,Agent 可以优先调用语义工具,必要时再回退桌面操作。
这套设计背后有一个朴素原则:能用精确工具时,不要让模型去点屏幕。打开浏览器扩展、读取表格单元格、修改文档结构,这些操作本来就有清晰语义。如果强行用截图和坐标表达,模型要做很多人类都觉得繁琐的低层动作。
OSWorld-MCP 的实验里,GUI + MCP 对不同模型的收益并不相同:
| 模型 | GUI Only | GUI + MCP |
|---|---|---|
| o3 | 12.8% | 25.2% |
| Claude 4 | 40.1% | 43.3% |
这个结果很有意思。对视觉和桌面理解能力较弱的模型,语义工具能显著补齐短板;对已经很擅长看屏幕的模型,正确率提升有限,但执行效率仍然可能更好。因为直接调用工具通常比多轮截图、点击、等待更短。
工业界的 Computer Use 系统也在走类似路线。一个合理的执行顺序不是"永远模拟人",而是"优先使用最精确的工具,必要时再回退 GUI"。比如获取 Slack 消息,连接器比截图点击更快;但遇到没有 API 的遗留软件,GUI 仍然是兜底能力。
语义聚合:工具不是 API 的一比一投影
最常见的误区,是把已有后端 API 一对一变成工具。这样看起来能力很全,实际会带来三个问题:工具数量膨胀,模型选择负担变重;多步链路变长,失败点变多;底层 ID、分页、状态转换等细节占用大量上下文。
更稳的方式是按任务语义聚合。
不友好:
get_pre_sale_knowledge()
get_logistics_knowledge()
get_refund_knowledge()
更适合 Agent:
search_ecommerce_knowledge(
scene="refund",
query="退款多久到账"
)
聚合不是把能力做少,而是把常见任务路径变短。原子工具仍然需要存在,用来保证完备性和兜底;高层工具负责承接高频、稳定、可验证的动作。
图:语义聚合工具缩短高频任务路径,同时保留原子 API 兜底。
这个分层在 Agent 系统里很重要。没有原子层,系统会被高层工具限制住;没有聚合层,模型会在细碎 API 之间反复编排。
Tool Schema:写给模型看的接口说明
工具描述不是普通文档。它会进入模型上下文,直接影响模型是否选择这个工具、如何填写参数、失败后怎么修正。某种意义上,Tool Schema 是工具自带的 prompt。
高质量的 Tool Schema 至少要讲清楚四件事:什么时候用,什么时候不要用,参数怎么填,出错后怎么补救。只写"调用某某 API 获取数据"通常不够,因为模型缺少业务边界和失败处理线索。
| Schema 设计点 | 为什么重要 | 更好的写法 |
|---|---|---|
| 工具名 | 模型先通过名称粗筛工具 | 使用业务动作词,而不是内部系统名 |
| 描述 | 决定模型是否选它 | 说明适用场景和不适用场景 |
| 参数 | 决定调用是否稳定 | 使用语义字段,减少长 ID 和自由文本歧义 |
| 返回值 | 决定下一轮推理质量 | 返回决策必要信息,避免把无关字段全塞回来 |
| 错误 | 决定能否自我修复 | 明确指出错因、错误参数和建议下一步 |
Schema 优化往往是 ROI 很高的工作。原文引用的相关研究里,仅系统性优化工具描述,就能在 StableToolBench、RestBench 等任务上带来 11% 到 16% 的提升。Agent-First Tool APIs 更进一步,把传统 CRUD API 改成面向 Agent 的语义接口,在相同模型和 prompt 下,任务成功率提升 37.5%。
这说明接口说明不是"润色文案"。它会改变模型的行为分布。
返回值控制:少给随机串,多给决策信息
图:返回值应该服务下一步决策,而不是把上下文填满。
Agent 的上下文不是垃圾桶。工具返回越多,不代表模型掌握越多。很多字段对程序有用,对模型却只是噪声。
一个典型例子是长技术 ID。UUID 对数据库很友好,对模型不友好。它没有语义,容易抄错,占 token,还会在多轮调用里和其他 ID 混淆。除非后续动作必须使用,否则返回 name、file_type、title、updated_at 这类语义字段通常更有价值。
{
"uuid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"mime_type": "image/png"
}
可以改成:
{
"name": "product-dashboard-v2.png",
"file_type": "image"
}
如果必须保留 ID,也可以使用短引用、候选编号或"名称 + ID"的组合,让模型在阅读时有语义锚点。
返回值大小也要控制。线性结果适合截断式返回,比如搜索结果、日志、Trace;层级结构适合渐进式返回,比如目录树、知识图谱、复杂项目结构。
| 返回方式 | 适合场景 | 关键点 |
|---|---|---|
| 截断式 | 搜索结果、日志、数据库列表、堆栈信息 | 返回前 N 条,并告诉模型如何继续缩小范围 |
| 渐进式 | 文件树、系统拓扑、知识图谱、复杂配置 | 先给概览,再按节点展开 |
好的返回值应该让模型知道三件事:现在看到了什么,还没看到什么,下一步如何拿到更具体的信息。
Guardrail:把错误挡在工具边界内
Agent 不是不会犯错。工具设计的重点,不是幻想模型永远调对,而是让错误尽早暴露,最好在进入真实环境前就被拦住。
代码编辑工具要能发现匹配失败、重复匹配、语法错误。文件删除工具要能区分普通写操作和高风险操作。外部系统调用要能提供 dry-run 或 preview。错误响应要像给 Agent 的下一步指令,而不是只返回一个错误码。
一个可用的错误响应应该包含:
| 字段 | 作用 |
|---|---|
type |
错误类别,如 validation、authorization、network |
message |
用自然语言说明具体错因 |
bad_param |
回显出错参数,避免模型猜 |
suggestion |
给出可执行的修正方向 |
retryable |
告诉模型是否值得重试 |
这样的错误反馈会把一次失败变成一次有用观察。没有这些信息,模型只能换一种写法碰运气。
Eval Loop:工具要靠轨迹打磨
工具接口很难一次设计正确。因为"好不好用"不是抽象原则能完全推出来的,它要看 Agent 在真实任务里怎么失败。
更可靠的迭代方式,是围绕真实工作流做评测:收集任务成功率、调用次数、token 消耗、错误类型、人工接管点,再回看 Agent 的执行轨迹。模型在哪一步选错工具,在哪个参数上犹豫,哪类返回值让它误判,这些信号比主观讨论有用得多。
图:工具设计需要依赖真实任务轨迹持续评测和修正。
DRAFT 这类工作把这个过程做成了"探索、分析、重写"的闭环。Anthropic 的工具设计经验也强调相同方向:让 Agent 在真实任务中使用工具,分析失败,再修改工具和说明。工具说明不是写完就结束,它应该随着轨迹持续进化。
设计取舍:模型变强后,这些原则还值钱吗
模型会变强,上下文会变长,工具调用能力也会继续提升。但这不意味着工具接口设计会失去价值。
有些收益会变化。比如模型更强后,它确实更能在大量细碎工具中做选择,也更能从长返回值里找信息。聚合工具在"提高正确率"上的边际收益可能下降。
但成本和稳定性不会消失。更少的工具定义、更短的返回值、更清楚的错误反馈,仍然能减少 token、缩短调用链路、降低延迟。尤其是私域系统、企业流程、内部权限和业务术语,永远不会自动存在于基座模型里。这些内容必须通过工具描述、返回值和错误反馈传给模型。
| 设计原则 | 正确性收益 | 成本 / 速度收益 | 判断 |
|---|---|---|---|
| 避免 API 一比一暴露 | 模型越强,收益可能下降 | 工具更少,决策链更短 | 仍然适合高频任务 |
| 减少长技术 ID | 幻觉率下降后收益趋平 | token 更少,复制错误更少 | 长期划算 |
| 控制返回值大小 | 长上下文会削弱一部分收益 | 低延迟、低成本持续存在 | 仍然必要 |
| 打磨 Tool Schema | 私域知识无法靠模型自动补齐 | 一次调对,减少返工 | ROI 很高 |
| 评测驱动迭代 | 持续暴露真实失败 | 能识别低效链路 | 是元方法 |
结语
Agent 工具接口的核心,不是把系统能力尽量多地暴露出去,而是把任务路径设计得足够清楚、足够短、足够可纠错。
Code Agent 的经验说明,RAG 只能解决"给模型看一点代码"的问题,不能替代交互式探索;裸 shell 虽然完备,却把太多底层细节推给模型。Computer Use 的经验说明,GUI 是兜底,不应该成为所有任务的首选接口。只要有更精确的语义工具,就应该让 Agent 先走语义层。
真正 LLM Friendly 的工具,通常同时具备两层能力:底层完备,保证没有路被堵死;上层聚合,让高频任务不必走弯路。再配合清晰 Schema、紧凑返回、可操作错误和评测闭环,工具就不再是模型外面的附属品,而会成为 Agent 能力的一部分。
推荐阅读
Hermes Skill Runtime 架构拆解:三层加载如何压住 Agent 上下文成本
Agent Runtime 架构拆解:Prompt 如何变成可校验的执行链路