02 XML 工具协议与原生工具调用
学习目标
本章要解决什么问题:Cline 如何在 40+ 模型提供商不兼容的工具调用协议下,实现统一的工具系统?XML 和原生 tool calling 如何共存?
前置知识
本章涉及工具调用协议的通用原理,建议先阅读:
下文假设你已理解四层工具系统架构和 OpenAI Function Calling 协议,直接聚焦 Cline 的具体实现。
项目实践
双协议支持架构
Cline 的工具系统同时支持两种协议,通过 useNativeToolCalls 标志在运行时切换:
为什么需要双轨? Anthropic、Ollama、LM Studio 等不支持 OpenAI 格式的原生工具调用。XML 标签是一种通用方案——将工具指令作为提示词的一部分,对模型没有格式要求。但对 OpenAI Responses API 等原生支持的提供商,使用原生协议可以获得结构化输出和 call_id 追踪能力。
ToolExecutorCoordinator 路由
工具执行采用 Coordinator 路由模式:
# 伪代码:路由流程const result = await ToolExecutor.execute({ toolName: "write_to_file", parameters: { path: "...", content: "..." }, approvalState: "approved" // 前置审批检查已通过})路由步骤:
- 从 LLM 响应中提取工具调用(XML 或 JSON)
- 检查自动审批状态(
autoApprove.ts) - Coordinator 按工具名查找 handler
- Handler 在
handlers/目录下独立实现 - 执行结果返回给 LLM 或用户
Plan 模式工具限制
Cline 通过 PLAN_MODE_RESTRICTED_TOOLS 列表限制 Plan 模式下可用工具集,只允许读取和提问类工具,禁止文件写入和命令执行。
并行工具调用
当模型一次返回多个工具调用时,Cline 支持并行执行(通过配置可切换为串行)。并行条件:工具之间无资源依赖和逻辑依赖。
问题与规避
| 陷阱 | 场景 | 对策 |
|---|---|---|
| XML 标签格式错误 | LLM 生成未闭合的标签 | parseAssistantMessageV2 使用健壮解析策略,容忍部分格式错误 |
| 审批前置缺失 | handler 执行了未审批的操作 | 审批检查在 Coordinator 路由之前,未通过审批不调用 handler |
| 工具名称冲突 | 内置工具与 MCP 工具同名 | MCP 工具使用 use_mcp_tool 包装,通过 server_name 区分 |
设计取舍
XML vs 原生协议
| 维度 | XML 标签 | 原生 tool calling |
|---|---|---|
| 兼容性 | 所有模型 | 仅支持 OpenAI Responses API 等 |
| 结构化 | 依赖 LLM 正确生成 XML | JSON Schema 保证结构 |
| 追踪能力 | 无 call_id | 有 call_id,支持并行追踪 |
| 提示词长度 | 较长(标签占用 Token) | 较短(JSON Schema) |
Cline 的策略:能原生就原生,否则用 XML。通过 apiFormat 字段自动选择最优协议。
参考来源
- Cline 源码:
apps/vscode/src/shared/tools.ts - Cline 源码:
apps/vscode/src/core/task/ToolExecutor.ts - Cline 源码:
apps/vscode/src/core/assistant-message/index.ts