7大开源Agent源码对比解读——工具调用
7大开源Agent源码对比解读——工具调用
本文是「7大开源Agent源码对比解读」系列第 4 篇。评估对象:codex、gemini-cli、qwen-code、opencode、kimi-code、deepseek-harness(下称 dsh)、oh-my-pi(下称 omp)。所有机制描述附源码引证。
| 篇 | 文章 | 内容速览 |
|---|---|---|
| 总述 | 拆了七大开源 Agent 的源码,最高分竟然不是 Codex | 总体结论、评估方法与评分卡 |
| 01 | 架构对比 | 四种流派与分化根源、主循环与事件机制、插件化与耦合风险 |
| 02 | 上下文管理 | 压缩触发阈值、摘要方式、token 计数口径、跨会话记忆 |
| 03 | 会话管理 | 持久化模型三层次、并发控制、崩溃恢复与 resume / fork |
| 04 | 工具调用 | 注册与可见性、并行调度四种语义、审批门控、错误处理 |
| 05 | 重连与容错 | 重试预算、流中断处理、降级链、副作用安全 |
| 06 | 系统提示词与指令遵循 | 四种组装范式、动态注入、注入防御三层与共同敞口 |
| 07 | 思维链与工作流编排 | 思维链接入、plan 模式语义、子代理治理、工作流引擎 |
| 08 | 性能设计 | 前缀缓存三档分化、启动优化、成本核算 |
| 09 | 可扩展性 | MCP 接入、自定义工具、多 provider、SDK 与 API |
| 10 | 安全与权限控制 | 沙箱两种语义、审批默认姿态、企业管控、敏感数据保护 |
七家在工具调用上的分化集中在三条轴线:注册与可见性(模型一次能看见多少工具)、并行调度(怎么排一批工具调用)、审批门控(缺省放行还是缺省拒绝)。
注册与校验
| 项目 | 注册机制 | Schema 校验 |
|---|---|---|
| codex | ToolExecutor trait + 六种暴露态 | JSON Schema + strict;apply_patch 用 lark 文法 |
| gemini-cli | 两阶段:先校验参数再构造调用对象 | JSON Schema + Ajv(双版本共存) |
| qwen-code | tool-registry + 懒注册 | JSON Schema |
| opencode | Tool.define + 项目级本地工具目录 | Effect Schema,校验错误自动生成改写指引 |
| kimi-code | builtin 工厂 + zod | zod 双向(模型侧与运行时同源) |
| dsh | defineTool:schema DSL + render 投影 | 白名单只给模型 name、description、parameters |
| omp | BUILTIN_TOOLS 工厂 + omptype | 自研 omptype(ArkType 兼容的字符串 DSL) |
「模型一次能看见多少工具」被各家当成核心治理问题。把全部工具一次性塞给模型会污染 prompt、降低调用准确率,于是各家演化出不同机制:
- codex 的
ToolExposure有六种暴露态(tools/src/tool_executor.rs:51):Direct 进初始列表、Deferred 注册但须通过tool_search发现、Hidden 可派发但对模型不可见,另有三个 code-mode 相关变体。同一工具可以在多个 surface 上差异化暴露。 - dsh 用白名单投影:工具定义里有很多运行时元数据(超时、并发分类、finalizer),给模型的永远只有 name、description、parameters 三件套(tools/src/index.ts:251 注释「NEVER sent to the model」)。
- qwen 把大工具集做成懒注册:computer-use 的 35 个工具需要时才 reveal 进模型可见列表,工具名表由脚本从 cua-driver 的真实
tools/list输出生成,避免手工维护漂移。
一个反直觉的特例是 codex 的 apply_patch:它声明成 freeform 工具,用一份内联的 Lark 文法定义 *** Begin Patch 包裹的类 diff 语法,完全绕开 JSON Schema(apply_patch_spec.rs:9-22)。patch 本质是行级文本块,JSON 转义会放大 token 且模型容易出错,让模型直接写 diff 文本、由解析器在 API 侧校验,是七者中唯一的非 JSON Schema 工具。
并行调度的四种语义
这是分歧最大的一条轴,有四种范式。
范式一:模型显式控制。 gemini-cli 给每个工具自动注入 wait_for_previous 参数,模型需要等前一个工具完成时就显式设 true(tools.ts:538,系统提示里专门教了这个约定)。灵活,但依赖模型自觉;编辑类工具被硬编码永远串行。
范式二:静态属性分区。 qwen 的 partitionToolCalls 按工具安全属性分区:连续的安全工具合成一个并行批,每个非安全工具自成串行批,顺序保留([Read, Read, Edit, Read] → [[Read,Read], Edit, Read],coreToolScheduler.ts:1297-1306 的注释原例)。kimi 的 ToolAccesses 更精细,区分文件读/写/递归路径,只有写操作或路径重叠才判冲突。omp 的工具声明 concurrency: shared/exclusive,exclusive 形成屏障。可预测、可证明无冲突。
范式三:流式边到边执行。 codex 的 parallel_tool_calls 恒开,工具调用一从模型流里析出就 tokio::spawn 入队,流还在产出时工具已经开始跑,结束后按入队序收尾(turn.rs:2224-2392)。非并行工具通过读写锁形成独占屏障:声明 supports_parallel=false 的工具拿写锁,阻塞所有其他工具(tools/parallel.rs:92-113)。
范式四:有界滚动池 + 启动前重分类。 dsh 的并行度有界(默认 10),每个调用启动前重新读一次执行模式,若被重分类为独占则中断填充、等当前池排空(tool-calls.ts:200-204)。取消时为未启动的调用补合成错误结果,保证回放仍然有效。这是四者中工程化程度最高的。
gemini-cli 的批处理用 Promise.all 不限并发,模型一次发起大量 shell 调用时可能耗尽 fd 和 CPU。调度器不做资源治理,责任就推给了沙箱。
审批门控:缺省放行还是缺省拒绝
| 项目 | 默认姿态 | 特色机制 |
|---|---|---|
| dsh | ask,fail-closed | ask 缺审批支持即转 deny |
| codex | OnRequest | guardian 独立 LLM 评审器 + 审批缓存 |
| opencode | ask | 三层通配规则,拒绝可带反馈回传模型 |
| gemini-cli | default | 五级 TOML 策略引擎 + Always-Allow 收窄 |
| qwen-code | AUTO | 正则硬阻断 + 两阶段 LLM 分类器 |
| kimi-code | manual | 21 条策略链,首个非空结果胜出 |
| omp | yolo | 三层 tier,出厂全自动批准 |
几个值得展开的设计:
codex 的 guardian。 OnRequest 模式下模型请求审批时,先由一个独立 LLM 评审会话评估是否可自动放行,避免打扰用户(core/src/guardian/)。评审把转录摘要、工具参数、工具结果一律当作「不可信证据而非指令」,超时、执行失败、畸形输出一律不放行(90 秒超时、连续拒绝上限 3 次)。审批结果按缓存键复用,同一会话不重复弹窗。
qwen 的 AUTO 四道门槛。 并非单纯交给分类器:工作区内编辑走 fast-path 直放;只读工具白名单直放;破坏性命令正则硬阻断(在分类器之前执行,分类器误判也放不过去);最后才是两阶段 LLM 分类器(permissions/autoMode.ts:685-744)。每次工具调用都可能产生额外 LLM 查询,成本和延迟是代价。
kimi 的有序策略链。 21 条策略按固定顺序执行,从 hook 拦截、模式裁决、用户规则到敏感文件、最终回退,第一个给出非空结果的策略胜出(permission/policies/index.ts:28-71)。用户一次「本会话内批准」会成为会话级记忆,后续同工具调用自动放行。
opencode 的 reject 带反馈。 用户拒绝一个工具调用时可以附上理由,理由作为错误回传给模型(permission/index.ts:121-125)。拒绝也是对话的一部分,模型能据此调整,避免盲目重试。
omp 的默认姿态。 出厂默认 yolo,全自动批准,用户须显式切到 always-ask 或 write 才进入审批态。适合开发者自用,不适合托管服务。
错误处理与循环防护
错误分类最干净的是 codex:RespondToModel 可恢复,错误文本回传模型继续;Fatal 不可恢复,终止整个 turn(function_call_error.rs:5)。
其余几家的特色机制:
- opencode 的 doom_loop 检测:最近 3 个 part 是同名工具且输入完全相同,就把「死循环」当作一种 permission 请求弹给用户裁决,用户可以一键放行该工具(processor.ts:356-379)。
- qwen 的 XML 方言回退:某些模型不输出标准 function call,把工具调用写在文本里用 XML 表达,qwen 用正则解析
<invoke>块,解码实体、保留缩进、标量字符串不强转(xml-tool-call-fallback.ts)。这是兼容小模型的实用设计。 - omp 的合成结果保配对:被中断或跳过的工具调用补一个合成结果,文本明确告诉模型「别把跳过当完成,需要的话下一步重试」。深层原因是 provider 协议要求每个 tool_use 块都有配对的 tool_result,否则重放时整段交互被剥离(agent.ts:1330 注释)。
- kimi 的结果信任边界:工具返回 undefined、原始类型或缺字段的对象,一律强制规整成带
isError的标准形状,保证循环永远能发出配对结果(tool-call.ts:679-698)。
内置工具面:只列特色
九个大类(文件/搜索、shell、代码智能、计划、子代理、定时、网络、多模态、记忆)各家都有基础款,差异在特色深化:
- 代码智能:omp 的 LSP 14 个操作(含跨文件重命名、code actions)加 DAP 28 个操作,是七者中唯一能交互式调试的(下断点、单步、查栈帧和内存);qwen 的 LSP 12 个操作、7270 行实现次之;codex 有
tool_search配合 deferred 工具发现。 - shell:omp 内嵌 brush(Rust 写的 bash 替代),不 spawn 外部 shell,每次调用复用同一会话的 cwd 和环境;gemini-cli 和 kimi 的 shell 超时后转后台进程,配 list/read 工具读输出。
- 定时与自治:kimi 的 cron 带确定性抖动,防止所有用户都写
0 9 * * *导致上游在整点遭遇齐射(jitter.ts:4-10);dsh 的 schedule 直接是会话事件类型,不需要单独的调度持久化。 - 多模态:qwen 的 CUA 35 工具覆盖桌面自动化;omp 覆盖 browser、computer、TTS、WebRTC 实时语音,面最广。
- 记忆工具:omp 的 retain/recall/reflect/learn 四件套最结构化;dsh 提供 5 个 session 工具。
给 Agent 开发者的借鉴清单
- 工具可见性要治理。 工具超过二三十个就该上 deferred 注册 + 工具搜索(codex)或白名单投影(dsh),别让模型背全量清单。
- 并行语义四选一,推荐有界。 静态属性分区可预测,有界滚动池最完整。无上限的
Promise.all是资源隐患。 - 独占工具要有屏障语义。 读写锁(codex)或 exclusive 排队(omp、dsh)都能实现,关键是「独占等所有前序完成」的语义要显式。
- 托管服务学 dsh 的 fail-closed。 审批支持缺席时,ask 必须转成 deny,默认放行只适合开发者自用场景。
- 拒绝要能带理由回传模型。 否则模型只能盲目换姿势重试(opencode)。
- 合成结果保配对是硬要求。 任何中断、跳过、取消路径都要补配对的 tool_result,不然历史不可重放。
- 循环检测前置比事后便宜。 doom_loop 三连检测、dsh 的重复工具提醒,都比 gemini-cli 用 LLM 裁判循环便宜几个数量级。
- 破坏性命令用正则硬阻断。 放在分类器之前,不依赖模型判断(qwen 的 L5.2.5)。
文档地图
| 篇 | 文章 | 内容速览 |
|---|---|---|
| 总述 | 拆了七大开源 Agent 的源码,最高分竟然不是 Codex | 总体结论、评估方法与评分卡 |
| 01 | 架构对比 | 四种流派与分化根源、主循环与事件机制、插件化与耦合风险 |
| 02 | 上下文管理 | 压缩触发阈值、摘要方式、token 计数口径、跨会话记忆 |
| 03 | 会话管理 | 持久化模型三层次、并发控制、崩溃恢复与 resume / fork |
| 04 | 工具调用 | 注册与可见性、并行调度四种语义、审批门控、错误处理 |
| 05 | 重连与容错 | 重试预算、流中断处理、降级链、副作用安全 |
| 06 | 系统提示词与指令遵循 | 四种组装范式、动态注入、注入防御三层与共同敞口 |
| 07 | 思维链与工作流编排 | 思维链接入、plan 模式语义、子代理治理、工作流引擎 |
| 08 | 性能设计 | 前缀缓存三档分化、启动优化、成本核算 |
| 09 | 可扩展性 | MCP 接入、自定义工具、多 provider、SDK 与 API |
| 10 | 安全与权限控制 | 沙箱两种语义、审批默认姿态、企业管控、敏感数据保护 |
葡萄城是专业的软件开发技术和低代码平台提供商,聚焦软件开发技术,以“赋能开发者”为使命,致力于通过表格控件、低代码和BI等各类软件开发工具和服务,一站式满足开发者需求,帮助企业提升开发效率并创新开发模式。
更多推荐



所有评论(0)