本页目录5
这个考点是什么
结构化错误响应,考的是「工具失败之后,失败信息以什么形状交还给模型」这件事的设计质量。Claude 的 Messages API 里,client tool 的失败通过 tool_result 的 is_error: true 字段回传;MCP 工具的失败通过工具结果里的 isError 标记回传。
两条通道的共同前提是:工具永远不该把失败悄悄吞掉、伪装成成功,或者直接抛出未处理异常中断整条 agent 链路——失败也必须变成一条 Claude 能读懂、能据此决策的结构化信号。
「能读懂」不是只看那个布尔位。同一个 is_error: true,消息体写「failed」和写「Rate limit exceeded. Retry after 60 seconds.」对模型后续动作的影响完全不同:前者只告诉模型「没成」,后者还告诉它「为什么没成、要不要等、等多久」。
这个考点因此天然延伸到错误分类(瞬时/校验/权限/业务规则)、可重试标记(isRetryable)、以及并行 tool_use 场景下多个 tool_result 的回传格式规范。
再往外一层,考点还触及「结构化错误 vs 幂等性设计」的分工边界:错误响应解决的是模型能否判断该怎么办,幂等性(如客户端提供 idempotency key)解决的是重试本身会不会造成重复副作用——二者经常配套出现在同一道非幂等写操作题里,但各自解决不同的问题。
为什么考
这个考点是「Tool Design」域里最容易被简化成「记住 is_error 这个字段名」的一条,但命题角度几乎都落在字段之外:题干常给出一个已经在用 is_error/isError 但设计仍然糟糕的例子(千篇一律的「Operation failed」、把访问失败和合法空结果都包装成 success、瞬时超时和业务拒绝共用同一种可重试语义),要求判断"缺的到底是什么"。
另一类高频考法是并行 tool_use 的 tool_result 回传协议——多选题里混入「拆成多条消息发送」「省略失败工具的结果」这类会破坏配对关系的干扰项,以及把「等待模型自行推断」当作合理设计的干扰项。真正的鉴别力在于:考生是否理解结构化错误的目的是让模型据此分支决策,而不是仅仅完成字段格式上的合规。
核心辨析
- 1
is_error: true该在什么时候出现工具执行报错、网络/服务不可用、参数缺失或非法都要设为 true;但绝不能反过来——工具没执行或失败了却省略这个
tool_use对应的tool_result,或者用一条独立文本消息去解释失败。协议要求失败也必须以tool_result形式存在,tool_use_id对应,只是多带一个is_error标记。 - 2
错误消息内容的及格线是「可执行」,不是「诚实」
「failed」「Error 500」这类消息是诚实的但没用,模型拿不到任何下一步依据;「Rate limit exceeded. Retry after 60 seconds.」既说明原因也给出动作,这是官方文档明确用来对比好坏消息的示例,写作时应默认往后者靠。
- 3
MCP 场景里
isError:true(访问/执行失败,如后端不可达、数据库超时)和isError:false附带空结果(查询成功但确实没有匹配)是两种相反的语义,绝不能合并成同一个「no_results」之类的中性状态——前者应该触发重试或升级,后者应该被如实报告为「没找到」,合并会让 agent 自信地得出错误结论而不自知。 - 4
可重试(transient,如超时、限流)和不可重试(permanent,如参数非法、权限/风控拦截)必须能被模型区分,否则默认行为往往是「失败就重试几次」——对瞬时错误是合理的自愈路径,对业务规则拒绝则会造成重复副作用(如反复触发风控告警)。
区分手段可以是显式的
errorCategory/isRetryable字段,也可以是消息措辞本身把两者写得不一样。 - 5
并行
tool_use的回传是格式而非语义层面的易错点多个
tool_result必须整体放进同一条user消息、且都排在任何文本内容之前,每个都要用tool_use_id对应各自的调用;某个工具没跑或跑失败了,也要为它补一个带is_error:true的tool_result而不是跳过——跳过或拆成多条消息发送都会破坏配对协议,还会让模型学会以后少用并行调用。 - 6
结构化错误响应和幂等性设计是两个正交但常配套的问题
前者让模型知道「这次调用失败了、该怎么办」,后者让重试这件事本身不产生副作用重复(例如非幂等写操作配合客户端 idempotency key)。只做好错误分类而不做幂等键,遇到超时后状态不确定的重试仍可能造成重复扣款一类的问题。
反模式对照
所有失败路径都返回同一个通用错误,如 {"status":"error","message":"Operation failed"}
返回带 errorCategory(transient/validation/permission/business)、isRetryable 布尔值、以及针对具体失败原因的说明的结构化对象
通用错误让模型无法区分该重试超时、该改正参数、还是该直接告知用户并终止;四类失败(网络超时、参数非法、风控拦截、订单过期)本该走四条不同的恢复路径,合并成一种会让 agent 只能选择「道歉后结束对话」这一种兜底动作。
工具没执行或执行失败时,省略这个 tool_use 对应的 tool_result,或改用一条独立的纯文本消息说明情况
仍然返回 tool_result,带上匹配的 tool_use_id 和 is_error:true,和其他并行结果一起放在同一条 user 消息最前面
tool_use 与 tool_result 是强制配对的协议,省略会导致 API 报「tool_use ids were found without tool_result blocks」之类的错误;拆成独立消息则会让模型把「以后不要并行调用」当成经验教训,削弱后续的并行工具使用能力。
后端不可达/内部报错时,仍返回和「合法查了个空」一样的成功结构,例如 {"results":[],"status":"success"}
后端故障用 isError:true(或 is_error:true)明确标出访问失败,只有真正执行了查询但没有匹配项时,才返回成功状态配空结果
两者对下一步动作的要求正相反——访问失败该重试或升级给人工,合法空结果该照实汇报「没有找到」并继续推进;合并成一种状态会让下游(甚至下游的另一个 agent)把系统性故障误判成正常的检索结果。
用裸的 HTTP 状态码(如直接返回 429/503)或极简描述代替具体原因和处理建议
给出可执行的说明,比如具体原因 + 建议动作("Rate limit exceeded. Retry after 60 seconds.")
模型看到一个孤立的状态码需要自行猜测语义、等待多久、要不要换参数重试,而很多工具调用本来就不是 HTTP 请求,状态码语义未必能对应上;写清楚原因和建议动作,是官方文档里明确对比过的好坏消息示例所强调的差异。
练这个考点
练习模式支持按考点专练(需 Google 登录,不占用正式考机会)。
专练考点 2.2该考点的公开题(免登录,含完整解析):