K2.2.1 Task 2.2

结构化错误:78-95% 恢复率 vs 通用"Operation Failed"的 15%

isError: true 只是起点。通用的”Operation failed”只有 15% 的 agent 恢复率。加上结构化元数据——错误类别、是否可重试、客户消息、建议动作——能实现不同错误类型 78-95% 的恢复率。

恢复率数据

错误类型提供的元数据恢复率
瞬时性(isRetryable: true)类别 + 可重试性92% 自动恢复
校验性(字段级详情)类别 + 具体错误78% 自动纠正
业务性(isRetryable: false)类别 + 客户消息95% 正确升级
通用(“Operation failed”)15% 恢复

15% 和 78-95% 之间的差距是结构化元数据,不是模型能力。

基本模式

{
  "content": [{"type": "text", "text": "Database query timed out after 30s"}],
  "isError": true
}

Agent 知道工具失败了、看到了原因。但它不知道:该不该重试?这是暂时的吗?该告诉用户什么?

完整结构化模式

{
  "content": [{"type": "text", "text": "Refund of $750 exceeds $500 policy limit"}],
  "isError": true,
  "structuredContent": {
    "errorCategory": "business",
    "isRetryable": false,
    "customerMessage": "Refunds over $500 require manager approval",
    "suggestedAction": "escalate_to_human"
  }
}

现在 agent 知道:这是业务规则(不是瞬时性的)、重试没用、可以告诉客户为什么、应该升级。

四种反模式

静默吞没:数据库不可达时 isError: false 加空内容。Agent 告诉研究者”没找到论文”——但实际上有几千篇。数据库是挂了,不是空的。

成功带错误文本isError: false 加内容”error occurred”。Agent 把这当作返回的数据处理。

未处理的异常:工具错误作为异常传播 → JSON-RPC 协议错误导致连接崩溃。把可恢复的工具错误转成了不可恢复的协议错误。

通用消息:所有错误类型都返回”Operation failed”。Agent 对一切做相同的重试——在不可重试的错误上浪费尝试。

协议错误 vs 工具执行错误

类型示例LLM 可恢复性
协议错误工具名拼写错误(需要代码修复)
工具执行错误API 超时(LLM 可重试/适应)

MCP 规范说工具执行错误应该提供给 LLM 做自我纠正。让异常传播会把可恢复的错误转成不可恢复的。

安全:净化后的错误内容

错误做法:“Connection to db-prod-3.internal:5432 refused。“正确做法:“Database temporarily unavailable。“包含错误类别和可恢复性。完整技术细节记到服务端日志。Agent 得到恢复元数据但不暴露敏感内部信息。


一句话总结: isError: true 加结构化元数据(errorCategory、isRetryable、customerMessage、suggestedAction)实现 78-95% 的 agent 恢复率 vs 通用消息的 15%——所有工具错误捕获为 CallToolResult,绝不让它们变成协议异常,并为安全做净化。