跨 harness 对比:工具体系(定义/调用协议/注册/权限)
工具体系是一个 harness 最见功力的地方:模型能”做什么”由这一层的动作空间决定,“怎么安全地做”由权限层决定,“上下文塞不塞得下”由暴露策略决定。61 个 harness 在这四件事上分化很大。
一、设计谱系
把工具体系拆成四个正交问题,各自有清晰的流派:
1. 工具怎么定义(schema 从哪来)
- 装饰器 + docstring/签名自动生成:最主流的人体工学。函数签名 + docstring → JSON schema。MetaGPT(
@register_tool走 AST/inspect)是较早把 docstring 当契约源的;smolagents(@tool)、LangGraph(langchain@tool)、Semantic Kernel(@kernel_function+Annotated)、Letta(强制 Google 风格 docstring 校验)、Pydantic AI(griffe 解析 docstring)、CAMEL(get_openai_tool_schema,甚至能用 LLM 反生成缺失的 docstring)、Agno(Function.from_callable)、OpenAI Agents SDK(@function_tool)都是这一路。 - 显式 schema 类/接口/trait:把工具做成一等类型,带渲染钩子和谓词。Claude Code 的
Tool<Input,Output,Progress>(含isReadOnly/isDestructive/isConcurrencySafe+ 一大批终端渲染钩子)是最完整的;Zed 的AgentTooltrait(schemars派生 +tools!{}宏编译期查重)、OpenHands 的ToolDefinition[ActionT,ObservationT]、Gemini CLI/Qwen Code 的ToolInvocation、AutoGen 的ToolProtocol 都属此类。 Tool.define(id, init)契约族:opencode 血统的一批 TS harness 高度同构——opencode、MiMo-Code、Kilo Code 三者的Tool.define+ Zod/Effect Schema 校验 + 统一truncate.output+Effect.withSpan("Tool.execute")OTel span 几乎逐行同构,是明显的同源派生。
2. 工具怎么送到模型(调用协议)
- 原生 function-calling:绝大多数走 OpenAI/Anthropic 原生 tool-use schema,占绝对主流。
- 端到端 MCP:goose 是纯 MCP——扩展即 MCP server,工具就是
rmcp::model::Tool;CodeGeeX 更彻底,把自己的文件/终端/代码变换工具拆成内置的 3 个真 MCP server(frontend/backend/terminal),锁mcp>=1.6.0官方 SDK;claude-flow 对外暴露约 314 个 MCP tool,但用手写 JSON-RPC over stdio(非官方 SDK)。 - 文本协议 / 自定义 DSL:不走 function-calling,从模型纯文本里解析动作。Aider 的
<<<<<<< SEARCH/=======/>>>>>>> REPLACE块是最有名的文本编辑协议;Plandex 用### Tasks/### Commandsmarkdown 段;GPT-Pilot 用 pydantic discriminated union 的 step 类型 +<pythagoracode file>标签双协议(因为它假定 Claude 不支持 function calling);MetaGPT 烘焙进 prompt 的{"command_name":"Class.method","args":{}}JSON 数组;SWE-agent 即便配了 function-calling 也只用在 API 边界、随后翻译回字面 shell 命令。 - code-use(代码即动作):把工具作为可调用对象注入沙箱,让模型写代码而非逐动作 tool-call。smolagents 的 CodeAgent 是代表(工具渲染成
def toolname()桩函数,LLM 写 Python 调用);Replit Agent 显式拒绝”每动作一次 tool-call”范式,给 agent 一个注入了 Playwright 辅助函数的 JS 沙箱(vm.createContext),量化收益是”36 次翻页折叠成一个for循环”。 - GUI / computer-use 动作空间:见下节 3.5。
3. 工具怎么注册/发现
- 中央注册表 Map(
name→tool):Trae、Kimi Code、OpenManus、AgentScope、CAMEL、Hermes 等。 - 导入即自注册:Hermes 用 AST 扫描模块体的
registry.register()调用再 importlib 导入;QwenPaw/AgentScope 的@tool_descriptorimport 时自动收集;CrewAI 靠__init_subclass__自注册进全局类型表。 - 约定文件路径、无中央表:Agent Zero 最极端——加工具 = 放一个
<tool_name>.py+ 同名agent.system.tool.*.mdprompt 文件,get_tool()按 agent profile 目录层级查找动态加载,没有注册中心。 - 编译期宏查重:Zed 的
tools!{}宏在编译期强制无重名并生成built_in_tools()。
4. 权限模型(详见各 dossier 的”安全与权限”节,此处只谈工具层入口)
- 逐工具 checkPermissions/ask:Claude Code 的
checkPermissions→allow|ask|deny(可细到 Bash 子命令级)、opencode/Kilo Code 的ctx.ask(...)、Amazon Q 的requires_acceptance()、Factory 的工具实现内checkFileAccess()/checkNetworkAccess()。 - 策略 DSL / 规则引擎:Augment 的
settings.json规则数组(first-match-wins +webhook-policy/script-policy外部裁决 + 租户级覆盖)是文档化最完整的;QwenPaw 的GovernanceRule(match="Bash(git *)", action=ALLOW)glob 匹配 + SQLiteaudit.db审计;Kiro 的capability/match/exclude/effectYAML 统一引擎;v0 直接照搬 Claude Code 的Bash(pattern)allow/ask/deny 三数组。 - hook 拦截:Cursor、Copilot(
onPreToolUse)、Junie(PreToolUseEAP)、Amp(tool.call插件钩子统一拦截点)。 - 无工具级权限门:MetaGPT、OpenManus、Agent Zero、AutoGen、smolagents、UI-TARS、GPT-Researcher 的工具层都没有强制审批门(唯一人在环靠模型自主调
AskHuman/ask类工具)。
二、对比表
| harness | 工具定义 | 调用协议 | 注册/发现 | 工具级权限门 | MCP |
|---|---|---|---|---|---|
| Claude Code | Tool<I,O,P> Zod schema + 渲染钩子 | 原生 tool-use | ~40 内置 + defer_loading 懒加载 | checkPermissions allow/ask/deny,子命令级 | 一等来源(mcpInfo) |
| OpenHands | ToolDefinition + MCP ToolAnnotations | 三线格式互转(mcp/openai/responses) | 全局线程安全 registry + .create() 工厂 | ToolAnnotations 驱动(只读跳过门控) | FastMCP 客户端,复用同派发路径 |
| SWE-agent | Command(Jinja 模板→shell) | 文本→字面 shell(FC 仅 API 边界) | Bundle 目录装进沙箱 | 静态 blocklist(非交互审批) | 无 |
| Aider | SEARCH/REPLACE 文本块 | 文本编辑协议解析 | 无插件注册中心 | shell 命令须 confirm_ask | 无 |
| Cline | createTool() | 流式 tool-call-delta(畸形 JSON 容错) | Map<string,AgentTool> + model-aware 路由 | mode/model 双感知 | InMemoryMcpManager 动态加 |
| Roo Code | BaseTool<name> 类 | 原生 FC(已弃 XML) | 内置 + MCP + .roo/tools/ 自定义 | 审批分散进每工具 callbacks | getMcpServerTools |
| goose | rmcp::model::Tool + ToolAnnotations | 端到端 MCP | ExtensionManager(内置/stdio/inline-py) | ToolAnnotations + OSV 供应链检查 | 全部工具皆 MCP |
| opencode | Tool.define Effect Schema | AI SDK tool-calling | 内置 + tool/*.ts + 插件 | ctx.ask() 逐工具 | 插件桥接 |
| Codex CLI | handler 目录(~30) | ToolRouter 解析 FunctionCall | registry + 逐 turn 可见性 | request_permissions 工具 | McpConnectionManager 聚合 |
| Gemini CLI | ToolInvocation 接口 | 事件驱动 Scheduler 状态机 | registry + 外部命令式发现(stdout JSON) | shouldConfirmExecute + policy | 3 传输 + resources |
| Qwen Code | ToolInvocation(L3 内在权限) | 原生 FC | registry + 惰性 ToolFactory | getDefaultPermission allow/ask/deny | 客户端/连接池/发现 |
| smolagents | Tool 类(inputs 简化 JSON-schema) | code-use + FC 双面 | @tool 装饰 + TOOL_MAPPING | trust_remote_code 门(MCP 加载) | from_mcp(mcpadapt) |
| AutoGPT | @command / Block / BaseTool | 强制原生 FC(并行多调) | Component get_commands() 逐 cycle | requires_auth/is_available | run_mcp_tool 透传 |
| MetaGPT | @register_tool(docstring→schema) | prompt 内 JSON 命令数组 | 全局 TOOL_REGISTRY + 路径动态注册 | 无(仅 terminal 子串黑名单) | 无 |
| LangGraph | langchain @tool/BaseTool | AIMessage.tool_calls 并行 | .bind_tools() | 工具返回 Command 自实现(无声明式清单) | 生态外挂 |
| CrewAI | BaseTool(签名推导 args_schema) | ReAct 文本 + 原生 双套 | __init_subclass__ 自注册 + 层级挂载 | max_usage_count 硬上限 | 3 传输 |
| deepagents | 中间件贡献 BaseTool | langchain tool_calls | 分层:base→追加→profile 排除 | FilesystemPermission(allow/deny/interrupt) 在工具内 | 生态外挂 |
| QwenPaw | AgentScope ToolBase(继承底座) | AgentScope tool_call 块 | @tool_descriptor import 自注册 | PolicyGuardedTool 全局包裹 + GovernanceRule + audit.db | Access Policy(YAML) |
| Hermes | ToolEntry(check_fn+TTL 缓存) | registry 派发 | AST 自发现 ~92 文件 | 审批回调阻塞 + 4 工具 agent 层拦截 | mcp_tool/mcp_oauth |
| MiMo-Code | Tool.define Zod | JSON + shell 风格双风格 | 内置 + 自定义 + 插件 | approvalRule 字符串 | mcp__<server>__<tool> |
| Cursor | 文档级类别 | 原生 + hooks schema | 内置 + MCP | preToolUse/postToolUse hook + 企业白名单 | tools/prompts/resources/apps |
| Anthropic 多 agent | Messages API tool-use | 原生 | — | 内部工具优先于 web | MCP 为扩展层(工具自改进闭环) |
| Comate | 内置 + MCP 两类 | — | — | 按 agent 划分工具权限(Architect 只能调 agent) | MCP Server |
| Trae | Tool 基类(ToolParameter→schema) | 原生(provider 特化 schema 写死基类) | 中央 tools_registry dict | 无逐工具门 | 仅 stdio + allow-list |
| Qoder | 功能分类 | ACP ToolCall(闭源) | 版本化字符串 + allowlist | 可见性 vs 授权双控制面 | 4 传输 + mcp__server__tool |
| Kimi Code | ExecutableTool | 流式局部输出 + 后台分离 | ToolManager 三来源 | approvalRule | 渐进披露 select_tools |
| CodeGeeX | Python 模块=工具 | 真 MCP | 内置 3 个 MCP server + 用户扩展 | 逐次人工审批(UI 强制) | 内置即 MCP |
| AutoClaw | 无 schema 披露 | — | — | 危险脚本智能拦截(原理未披露) | 飞书 API 直连(非 MCP) |
| Amazon Q | Tool 枚举 + requires_acceptance | 原生 | NATIVE_TOOLS + 细粒度 BuiltInTool | 模式风险检测 + READONLY 白名单 | Tool::Custom(rmcp) |
| Devin | Session 原生 + MCP | 原生 | MCP 为主注册机制 | Service Users RBAC + Skill allowed-tools | DeepWiki/Devin MCP + Marketplace |
| Factory | 内置注册表 + GenerateDroid 元工具 | 原生 | 类别→工具 ID 映射 | 工具内 checkFileAccess + 风险分级 autonomy | 40+ registry server |
| Copilot | ToolSet builder | 原生 | builtin:*/mcp:*/custom:* 命名空间 | SDK 默认拒绝一切 + onPreToolUse | local/http + tools allow-list |
| Junie | 内置分类 | 原生 | MCP 为主扩展 | allowlist + Brave mode 分类器 + PreToolUse | .junie/mcp.json + registry |
| Kiro | AST 结构化工具取代文本 | 原生 | 统一 capability 引擎 | capability/match/exclude/effect YAML | stdio/http + Powers 动态工具包 |
| Replit | REPL 注入 JS 函数 | code-use JS 沙箱 | — | Package Firewall 网络层拦截 | 用了 MCP(细节薄) |
| Amp | {Name,Desc,InputSchema,Function} | 原生 tool_use | amp tools list | tool.call 插件钩子统一拦截 | amp mcp add + workspace 审批闸 |
| v0 | Bash/Delete 等 | 原生 | 按消息挂载 mcpServerIds | Claude Code 风格 allow/ask/deny + 硬编码兜底 | 自带 + Marketplace 三模式 |
| Warp | AIAgentActionType 枚举(960 行) | 服务端流式 action | 一文件一工具执行器 | action 类型 + profile 范围 | CallMCPTool 原生 action + 转发第三方 harness |
| Zed | AgentTool trait(tools!{} 宏) | 原生 | 编译期查重 ~23 工具 | 3 道准入闸门(白名单/UI 测试/flag) | mcp:<server>:<tool> |
| AutoGen | Tool Protocol + BaseTool | 原生 FC(strict 模式) | Workbench 有状态容器 | 无内置 allow/deny | McpWorkbench |
| Semantic Kernel | @kernel_function + prompt/OpenAPI/MCP 函数 | 原生 FC | KernelPlugin 字典 | FunctionChoiceBehavior.filters 静态 ACL + 中间件链 | connectors/mcp.py |
| Augment | 规范内建工具名 | 原生 | bundle 双侧执行 | 策略 DSL(webhook/script policy + 租户级) | find-tool/execute-tool 惰性暴露 |
| browser-use | Registry.action 装饰 | 结构化 pydantic Union | 用户可注册任意函数 | domains 按 URL 过滤可见 action | 无(浏览器专精) |
| Open Interpreter | Codex 底座 handler | 随 harness 变(FC 或纯文本 shell) | 每轮合并内置+MCP+plugin+connector | request_permissions | list_all_tools |
| claude-flow | {name,desc,category,inputSchema,handler} | 手写 JSON-RPC ~314 工具 | mcp-client.ts 聚合 45 模块 | 无(依赖 Claude Code 权限) | 自身即 MCP server |
| OpenManus | BaseTool(to_param OpenAI 格式) | 原生 FC | ToolCollection(同名跳过) | 基本无(唯 AskHuman 自主调) | web_search 等内置 |
| Agno | Function.from_callable | 原生 FC | Toolkit(include/exclude) 120+ 工具 | @tool(requires_confirmation) + toolkit 批量标审批 | tools/mcp/ 一等 |
| UI-TARS | Tool(zod/JSON) | 3 种 ToolCallEngine 可切换 | ToolManager + per-execution 覆盖 | 无强制门(hook 链可审批) | 见二代 Tarko |
| Continue | Tool 接口(evaluateToolCallPolicy) | 原生 FC + <tool> 文本兜底 | 运行时动态组装 | 权限串行、已批准工具并行执行 | inputSchema 直映射 |
| GPT-Pilot | pydantic step union | 无 FC,schema 注入 prompt + <pythagoracode> 标签 | 编排器写死分派 | 每 command step 弹确认 | 无 |
| GPT-Researcher | Retriever(管线固定遍历) + MCP | LangChain bind_tools(仅 MCP 走 LLM 决策) | 配置字符串加载类 | 无工具级门 | 两阶段选工具(LLM 选 ≤3) |
| AgentScope | ToolBase(is_read_only 等属性) | ToolCallBlock/ToolResultBlock | Toolkit 中枢 + ToolGroup | check_permissions/match_rule | 一等公民(QwenPaw 底座) |
| OpenAI Agents SDK | @function_tool + 托管工具族 | 原生 + Responses | 挂在 Agent.tools | needs_approval + guardrails | 完整 MCP 客户端 + HostedMCPTool |
| Kilo Code | Tool.define Effect Schema | AI SDK tool-calling | 内置 + 自定义 + 插件三来源 | ctx.ask() 逐工具 | Zod→JSON Schema 桥接 |
| Letta | Python 函数 + docstring 契约 | 原生 tool_call(剥 heartbeat kwargs) | function_sets/ + ToolExecutorFactory 路由 | tool rules + requires_approval + client-side | ExternalMCPToolExecutor |
| Google ADK | BaseTool(FunctionDeclaration) | 并行 asyncio.gather | agent tools=[] + BaseToolset | before/after/on_error 三段 callback + confirmation gate | _remote_mcp_server |
| Pydantic AI | Tool+ToolDefinition(typed) | 原生(kind/tool_kind 判别) | toolsets/ wrapper 组合 | ApprovalRequiredToolset | mcp.py |
| Agent Zero | Tool 子类 + .dox.md 契约 | LLM JSON tool_name/args | 约定文件路径无中央表 | 无 per-tool 门 | 先查 MCP 后查本地 |
| CAMEL | FunctionTool(可 LLM 反生成 schema) | 原生(strict schema) | BaseToolkit.get_tools() ~90 toolkit | mask_tool_output 敏感输出脱敏 | MCPToolkit 生命周期管理 |
| Plandex | markdown 段落 | 无 FC/JSON/MCP 文本解析 | types/reply.go | per-autonomy-level(非 per-tool) | 无 |
| DeerFlow | LangChain BaseTool | 标准 langchain | 四路合并(config/内建/MCP/ACP) | 三道门(tool_groups/skill allowed-tools/guardrail) | + ACP 工具 |
三、分组讨论
3.1 opencode 契约族——一份 Tool.define 的三次复用
opencode 的 Tool.define(id, init)(description + Zod/Effect Schema parameters + execute(args, ctx) + 统一 truncate.output + Effect.withSpan("Tool.execute") OTel span + ctx.ask() 逐工具权限)是一个被反复继承的模板。MiMo-Code(小米)和 Kilo Code 的工具层与它逐行同构:同样的 Tool.define、同样的 truncation 写盘 outputPath、同样的 Effect.withSpan span 名、同样的 apply_patch 只在 GPT 系模型下替换 edit/write 的 model-aware 可见性、同样的 {tool,tools}/*.{js,ts} 自定义工具动态 import。MiMo-Code 在此之上加了原创的 shell 风格调用(工具可接受单行类 shell 字符串经 tokenize 映射为结构化参数)和实验性的 Token Efficient Mode(默认关闭)。这一族是”谁抄谁”最清楚的证据链之一。
3.2 Claude Code 血统——权限规则语法被反复照搬
Claude Code 的 Bash(pattern) 风格权限规则(allow/ask/deny 三数组 + 子命令级审批粒度)成了事实标准。v0 直接照搬——文档明说”规则格式与 Claude Code 的 Bash(pattern) 风格完全一致”,JSON allow/ask/deny 三数组 + User/Team 两级作用域;QwenPaw 的 GovernanceRule(match="Bash(git *)") 也是同一 glob-on-target 语法;claude-flow 干脆不自建权限、直接依赖 Claude Code 的 .claude/settings.json。此外 Claude Code 的 defer_loading + ToolSearch 懒加载、isReadOnly/isDestructive/isConcurrencySafe 谓词、MCP 工具 mcp__server__tool 命名前缀也被广泛复制(Kimi、Qoder、Augment、MiMo 都用 mcp__ 命名空间)。
3.3 端到端 MCP 派——把内部工具也做成 MCP
大多数 harness 把 MCP 当”外部扩展层”,但少数把 MCP 抬成核心协议。goose 最纯粹——扩展即 MCP server,连内置工具都是进程内 MCP,ToolAnnotations(read_only/destructive/idempotent/open_world)被权限系统直接消费,还有 OSV.dev 供应链检查在扩展启动时拦恶意 npm/PyPI 包。CodeGeeX 把自己的文件/终端/代码变换工具拆成内置 3 个真 MCP server(mcp>=1.6.0 官方 SDK,非套壳)。claude-flow 对外是个 ~314 工具的 MCP server,但用手写 JSON-RPC(因为 Codex 在第一行非 JSON stdout 就会关 transport,有精细的 stdout 卫生处理)。OpenHands 走中间路线——内部 ToolDefinition 显式照搬 MCP 的 ToolAnnotations schema,每个工具能 to_mcp_tool()/to_openai_tool()/to_responses_tool() 三线格式互转。
3.4 反 function-calling 派——文本协议与 code-use
一批 harness 刻意不走 function-calling。Aider 的 SEARCH/REPLACE 文本编辑块是最早、最有影响力的文本协议(function-calling 变体在其代码库里已是注释掉的死代码)。Plandex(### Tasks/### Commands markdown)、MetaGPT(prompt 内 JSON 命令数组)、GPT-Pilot(pydantic step union + <pythagoracode> 标签,且直接 raise ValueError("Anthropic Claude doesn't support function calling"))都属此类。SWE-agent 更微妙:即便配了 function-calling 也只用在 API 边界、随后翻译回字面 shell 命令在持久 shell 里跑。
code-use 是这一派里最前瞻的分支:smolagents 的 CodeAgent 把工具渲染成 def toolname() 桩函数让 LLM 写 Python;Replit 显式拒绝”每动作一次 tool-call”(点名 Playwright-MCP/Stagehand/Browser-Use 风格),改给 agent 一个注入 Playwright 辅助函数的 JS 沙箱写循环——量化收益是”36 次翻页折叠成一个 for 循环里的一次模型调用”。这两者共享一个洞见:把动作空间从”固定工具集”扩展成”图灵完备的代码”,能大幅省 token、省往返。CAMEL 的 synthesize_schema/synthesize_output(用 LLM 反生成缺失的 docstring 和模拟工具输出)是另一个 LLM-in-the-loop 的工具定义变体。
3.5 GUI / computer-use 动作空间——一等 vs 单 operator
面向浏览器/桌面操作的 harness 有两种截然不同的动作空间设计。browser-use 把 26 个内置 action(navigate/click/input/extract/scroll/evaluate 任意 JS 等)经 Registry.action 装饰、拼成一个 pydantic Union 塞给 LLM 的 structured output,_normalize_action_function_signature 区分”业务参数”和”特殊注入参数”(browser_session/cdp_client/page_extraction_llm 等),并按当前 URL 用 domains 过滤出 page-specific action——这是细粒度多 action的路线。UI-TARS(二代 Tarko)走相反路线:GUI agent 只注册一个 operator 工具(GUI_ADAPTED_TOOL_NAME,参数为空),模型输出 Action: DSL 由 action-parser 解析成 operator_action、坐标经 normalizeActionCoords 归一化——这是单 operator + DSL的路线,动作空间在 prompt/parser 里而非 tool schema 里。Warp 则把 UseComputer/RequestComputerUse/StartRecording 直接做成 AIAgentActionType 枚举里的一等 action。UI-TARS 还有原创的 3 种可切换 ToolCallEngine(Native / StructuredOutputs / PromptEngineering),最后一种用状态机流式解析 <tool_call>{json}</tool_call> 标签给无原生 FC 的模型——比 Continue/GPT-Pilot 的文本兜底更工程化。
3.6 渐进式披露 / tool search——省 context 的新共识
MCP 工具泛滥导致上下文膨胀(Kiro 文档给的数字:“五个 MCP server 可能在第一条 prompt 前就消耗 5 万+ token,占上下文窗口 40%”),催生了一个跨 harness 迅速趋同的设计:先隐藏工具 schema,模型要用时再放出。Claude Code 的 defer_loading + ToolSearch 工具、Kimi 的 select_tools(MCP 工具不进顶层 tools[],模型必须先调 select_tools 加载 schema,且已加载状态从对话历史派生以对 resume/压缩安全)、Augment 的 find-tool/execute-tool 双元工具(--enable-tool-search)、AgentScope 的 meta tool ResetTools(让 LLM 自己激活/停用 ToolGroup)、Kiro 的 Powers(按对话关键词激活/去激活工具包)、OpenAI Agents SDK 和 Pydantic AI 的 defer_loading/DeferredLoadingToolset、DeerFlow 的 DeferredToolFilterMiddleware + tool_search + MCP auto-promote top-k——都是同一思路的不同实现。这是 2025-2026 期间最集中的一处设计收敛。
3.7 typed 工具与结构化编辑——把类型系统用到极致
Pydantic AI 把”类型化工具”做得最彻底:ToolDefinition 带 kind(function/output/external/unapproved)、tool_kind(跨 provider typed part 判别,如 tool-search)、sequential(并发屏障)、capability_id(工具归属 capability)、unless_native/with_native(本地工具与 provider 原生工具的 fall-up),且 toolsets/ 用 WrapperToolset 组合(FilteredToolset/PrefixedToolset/RenamedToolset/ApprovalRequiredToolset)把过滤/改名/审批做成可组合切面——这套抽象比其他 harness 的”扁平工具列表 + if/else”高一个层级。另一个方向是结构化编辑取代文本匹配:Kiro 用 AST 结构化工具(ClassName.methodName 选择器 + insert_node/replace_node/delete_node/replace_in_node)取代 strReplace 文本匹配,实测 token 减 20-30%、LLM 调用减最多 34%;还把 IDE diagnostics(LSP 类型检查器)做成一等工具(单次 < 35ms,命令执行减 29%),比 shell 出去跑 npm test 高效。Zed 同样有一整组 LSP 驱动工具(go_to_definition/find_references/get_code_actions/rename/diagnostics)。
3.8 底座与继承关系
- AgentScope 是 QwenPaw 的底座:QwenPaw 的
ToolBase、ToolCallBlock/ToolResultBlock契约、Toolkit全继承自 AgentScope;QwenPaw 的原创是在其上把每个工具包进PolicyGuardedTool全局强制门(并显式把 AgentScope 自带权限引擎设为BYPASS,即换掉而非叠加),加上GovernanceRuleglob 规则 +audit.dbSQLite 审计。 - Open Interpreter 以 Codex 为底座,其独特之处是调用协议随目标 harness 变:native/Responses 用 Codex function-tool schema,但把工具映射成目标 CLI 的原生 schema(
kimi_code_tools.json/zcode_tools.json落盘),而 swe-agent/mini-swe-agent/terminus-2 不用 tool schema、从纯文本解析 shell。 - claude-flow(Ruflo)本质是 Claude Code 的 MCP 工具扩展层,不自建权限、复用 Claude Code 的 settings。
- Letta 的独特设计在记忆工具的执行器路由:内置工具函数体多是
raise NotImplementedError,真正执行由ToolExecutorFactory._executor_map按ToolType(LETTA_MEMORY_CORE/LETTA_CORE/EXTERNAL_MCP/…)分发,其中记忆的分层自编辑(core memory 自改写)走专门的LettaCoreToolExecutor,而自定义/用户工具默认走SandboxToolExecutor沙箱——“默认沙箱”是它的安全关键(详见 memory / 安全维度)。
3.9 权限模型的两个极端
- 最工程化:Augment 的策略 DSL 是文档化最完整的——
settings.json规则数组(first-match-wins)、eventType(tool-call 前拦截 / tool-response 后注入)、webhook-policy(POST 到外部 URL 让远端裁决)、script-policy(本地脚本退出码判定)、加上/etc/augment/settings.json不可变的管理员/租户层。QwenPaw 的四态决策(ALLOW/DENY/ASK/SANDBOX_FALLBACK)+ 区分”显式资源工具”(allow=直接执行)与”Bash 类工具”(allow=仍在沙箱执行,因任意 shell 无法预审)也很精巧。Copilot 的 SDK 层”默认拒绝一切”(除非 app 提供onPermissionRequesthandler)是最保守的默认。 - 无门:MetaGPT、OpenManus、Agent Zero、AutoGen、Trae(分发时”就是没有闸门”)、UI-TARS、smolagents、GPT-Researcher 的工具层都没有强制审批门,安全靠沙箱或模型自觉。这类多是研究/框架型 harness,把权限判断留给使用方。
四、最值得借鉴的设计
1. 渐进式披露 / tool search(省 context 的工具暴露)。 这是 2025-2026 最强的一处跨 harness 收敛,且理由是硬约束——MCP 生态一旦接几个 server,工具 schema 就能吃掉 40% 上下文窗口(Kiro 数据)。Kimi 的 select_tools 把”已加载工具状态从对话历史派生”做得最稳(对 resume/undo/压缩天然安全),Augment 的 find-tool/execute-tool 双元工具最简洁,AgentScope 的 ResetTools meta tool 让 LLM 自主管理工具组最灵活。任何要接多 MCP server 的 harness 都应默认上这一层。
2. 结构化 / 类型化取代文本匹配。 Kiro 的 AST 结构化编辑工具(选择器 + 四种类型化节点操作)和 IDE diagnostics 一等工具,用实测数字证明了”让工具返回结构而非全文、让编辑走 AST 而非字符串匹配”能同时省 token(20-30%)、减 LLM 往返(34%)、降错误率——比 Aider SEARCH/REPLACE 那种字面匹配(匹配失败要回退模糊匹配再反射给模型)根本上更可靠。配合 Pydantic AI 的 typed ToolDefinition + WrapperToolset 组合抽象,代表了工具体系”把类型系统和编译器/LSP 基础设施接进来”的正确方向。