目录
在 Claude Code 中长时间作业时,你是否遇到过屏幕上突然涌出一串「从没见过的字符串」:
court
<invoke name="Bash">
<parameter name="command">ssh host 'cp file file.bak ; sed -i ...'</parameter>
<parameter name="description">…命令的说明…</parameter>
</invoke>
Your tool call was malformed and could not be parsed. Please retry.
本应在幕后执行的工具调用(命令),却作为原始文本直接泄露到屏幕上,而且根本没有执行。开头还粘着一个毫无意义的单词 court(或 call)。「我的电脑坏了吗?」「是不是哪里设置错了?」难免让人不安,但先说结论:这既不是你的环境问题,也不是你命令的失误。
它的真相是一个模型侧的缺陷——Claude(尤其是 Opus 4.8/4.7 系列)在生成工具调用「控制标签」的那一刻,偶尔会把标签生成坏掉。这是一个已知现象,Anthropic 官方仓库里也立了大量 Issue(#64108、#64150、#64690、#65705、#66153、#67295、#68354 等)。本文将基于官方文档与实际 Issue,系统梳理机制、原因、常见误解、用户/开发者各自的应对、与相似错误的区别,以及官方处理状况。最重要的应对先说在前面:当 court 出现时,不要在那个会话里硬磨,要尽早撤到新会话(/clear)——理由会在正文中说明。
「court」+invoke 标签泄露的真相
— 控制标签被生成坏掉,没有执行就流到了屏幕上
坏掉的调用无法被解析=不会被执行(fail-closed),因此没有误执行命令的危险。
真正的问题是「一轮空转」,以及放任不管会「连锁」导致卡死。
1. 究竟发生了什么——「court」与 invoke 标签的真相
屏幕上出现的 <invoke name="Bash"> 和 <parameter name="command">,是本来绝不该让你看到的「工具调用标记」。Claude 在执行命令或编辑文件时,会把这种 XML 风格的结构化标签作为 token「生成」出来,再由 Claude Code(即 harness)来解析它、真正运行命令。正常情况下,这些标签会被 harness 吸收、不会出现在屏幕上,你只会看到工具的执行结果。
但这一次,工具调用「表示开始的控制 token」被生成坏掉了,开头混进了 court 或 call 这种毫不相干的单词。由于 harness 只对严格的语法作出反应,于是它判定「这不是工具调用,只是一段文本」,并把它原样流到屏幕上。结果命令没有执行,你会收到「Your tool call was malformed and could not be parsed(工具调用不合法,无法解析)」这条消息。此外,也存在连错误消息都没有、直接默默卡住的情况(在 Issue #65705 中,响应变成了 stop_reason=end_turn,由于没有需要执行的东西,对话就此挂起)。
court 这个词本身没有意义。但它也不是「碰巧蹦出来的、完全随机的一次性词语」——在多份相互独立的报告中,泄露出来的都像盖了戳一样是 court / call。Issue #64690 将其分析为「词表中与正确标签『相邻』的 token 被错误地选中了」。也就是说,court 最好被理解为帮助你识别这个 bug 的「标志(signature)」。
2. 背景:智能体连工具调用也是「生成」出来的
「控制标签」为什么会坏掉?关键在于「对 AI 智能体而言,工具调用归根结底也是文本生成」这一点。
在 Claude API 中使用工具时,开发者看到的格式是 JSON(tool_use 块)。然而在模型内部,它会遵循 Anthropic 自动注入的隐藏系统提示词的指示,把 <function_calls>、<invoke>、<parameter> 这些包裹标签作为 token 序列生成出来。再由 API 层接收并解析它们、转换成整洁的 JSON tool_use 块(详见官方文档中的 tool use 规范)。MCP 和 AI 智能体的「调用工具」动作,全都建立在这套机制之上。
这里关键的一点是 harness 侧的解析器采用「fail-closed(向安全侧倾倒)」设计。只要标签与既定形态差了哪怕一个 token,harness 就不会去猜着执行,而是立即判定为「不合法」并拒绝。这作为一种 harness 设计是正确的——因为把含糊的命令「自作主张地改正后执行」要危险得多。所以这次的现象,本质上是「坏掉了 → 被拒绝 → 没有执行」,是一个向安全侧倾倒的案例。
一句话概括
工具调用=模型生成的「带特殊标签的文本」。当这些标签的开始 token 因生成错误而坏掉时,harness 无法识别,于是泄露到正文里、不会执行。拒绝这一动作本身是正确的安全机制,bug 完全出在模型侧的生成错误。
3. 为什么会发生——两大主因与诱发条件
整合实际 Issue 来看,原因可以归纳为「①生成时的破损」,以及让它变得棘手的「②自我污染导致的连锁」这两层。
从破损发生,到「连锁」的全过程
· 一条消息里有多个工具调用/把工具调用紧接在一段文字之后(#66153)
· 执行
/compact 之后的状态(#67295:compact 之后的首次调用即复发)· 后台 Bash(run_in_background)或连接了 3 个以上的 MCP 服务器(#64690)
· 像段落一样很长的工具参数(#49747:XML 混入 JSON 的另一种变体)
要点:坏掉本身只是罕见的生成抖动。真正棘手的是②的连锁——
所以「在同一会话里硬磨着重试」有可能成为最差的一招。
4. 纠正三个常见误解
这个现象的相关信息很容易混乱。为了能正确应对,先把三个常见误解纠正过来。
| 常见误解 | 实际上 |
|---|---|
| 「工具失控/误动作了」 | 恰恰相反。坏掉的调用没有执行就被拒绝了(fail-closed)。不存在误执行命令的风险,发生的只是「空转一轮+画面露出」而已。是向安全侧倾倒的案例。 |
| 「重试就会好,放着不管会自愈」 | 只对了一半。轻症时一次重试就能恢复,但坏掉的块一旦残留在历史里,模型就会模仿它并连锁。#65705 在 5 小时以上里连续失败 14 次,#66153 在一个会话里失败 30 多次。在同一会话里硬磨反而适得其反。 |
「court 有什么特殊含义/是某个命令」 | 没有任何含义——只是控制 token 变坏后的「残骸」而已。不过 court/call 会反复出现,是个标志,因此可以当作诊断的信号来用。 |
其中第二点最重要。事故报告里常写「重试后已正常恢复,没问题」,但那只适用于连锁开始之前的「轻症」情形。这个 bug 的本质在于一旦进入连锁模式,在那个会话里无论重试多少次都修不好。
5. 立刻修复(面向 Claude Code 用户)
应对方式取决于「还处于轻症,还是已经开始连锁」。按优先级排列如下。
应对的优先级
court 出现时,尽早 /clear 或开启新会话。切断被污染的历史是最可靠的办法。转移之前,用 git commit 或交接备忘保存好状态。/compact 有在其紧随之后复发的报告,并不是可靠的解决办法。
铁律:「失误两次,就放弃这个会话、开新会话」。
在已进入连锁的历史里磨得越久,伤得越深。把 CLI 保持在最新版(但请注意:修复版尚未发布=更新不是灵丹妙药,只是卫生管理)。
补充:只要平时养成把作业状态勤快地保存到 git 或 .md 交接备忘的习惯,无论什么时候转到新会话都不会痛。越是要跑长时间自主作业的人,这个习惯越有用(它也与上下文窗口的管理直接相关)。
6. 面向开发者:通过 API/SDK 预防
如果你在 Claude API / SDK 上自己搭建智能体,可以在 harness 侧加入下面这些防御。Issue #65705 提出的检测逻辑很实用。
// 在执行前检查收到的 assistant 轮次
const text = assistantText(resp);
const looksLeaked =
/<invoke\s+name=/.test(text) ||
/function_calls/.test(text) ||
/\bcourt\s*<invoke/.test(text);
// 1) 上述标记存在,却没有结构化的 tool_use 块 → 坏掉的调用
if (looksLeaked && !hasToolUseBlock(resp)) {
// 2) 不展示给用户,只记录日志。不要把坏掉的块留在历史里(防止自我污染)
// 3) 提示「请用结构化 tool_use 输出,而不是文本」并自动重试
return retryWithNudge(messages);
}
// 拒绝因截断而产生的不完整 tool_use
if (resp.stop_reason === 'max_tokens' && lastBlock(resp)?.type === 'tool_use') {
return retryWith({ max_tokens: higher }); // 不执行
}
四条原则。① 务必检查 stop_reason(明明是 end_turn 却没有工具在运行=检测出默默卡死)。② 执行前先核验「text 里有没有混入 <invoke name= 或 function_calls」,如有则不执行而是重试。③ 不要把坏掉的块留在对话历史里(留着会让下一次生成去模仿它、造成自我污染/#62344)。④ 工具参数要短,长输出要拆分(避开 #49747 的长 payload 变体)。即便使用 Claude Agent SDK 之类的官方 harness,也值得把长时间循环的行为搞清楚。
7. 与相似错误的区分方法
「工具跑不起来」这一类错误有好几种,应对方式各不相同。下面把四种区分开,以免混淆。
| 症状 | 真正是什么 | 主要应对 |
|---|---|---|
| court / call + 原始 invoke 标签被显示出来、没有执行 | 本文主题。控制 token 的生成破损+自我污染导致的连锁 | 优先开新会话(/clear);失误两次就别硬磨 |
| 400「thinking blocks cannot be modified」导致会话卡死 | 扩展思考中的签名不匹配(另一个 bug)。属于 API hard error | 参见专题文章(Esc×2/rewind) |
| 响应中途被截断(没有乱码 XML) | 触及 max_tokens 导致的正常截断。不是错误 | 调高 max_tokens 后重新执行 |
| 在 Bedrock 或 LangChain 等环境下 XML 没有被结构化 | 第三方客户端侧未能解析 Anthropic 的格式(langchain-aws #521)。在官方 API/Claude Code 上不复现 | 检查对接库/托管层 |
区分的判据很简单。看到「court / call 这种乱码 token+原始 XML」,就是本文这个 bug。400 签名错误则是 thinking 块错误。只是干净地截断那就是单纯的输出上限。只在经由 Bedrock 或 LangChain 时才发生那就是对接层的问题——就这样逐一区分。其他 Claude Code 常见错误,汇总在错误集里。
8. 官方处理状况
截至 2026 年 6 月,尚未确认有明确写明「已修复该现象」的官方修复(changelog 条目)。把发布说明一路追到 Claude Code 最新版(2.1.183 系列),也没有针对工具调用序列化破损的记述,相关 Issue 大多仍处于 open,或被归整为「duplicate/stale」。因此本文的所有应对都是「等待官方修复期间的规避方案(workaround)」,无法断言「更新到最新版就能修好」(更新值得推荐,但不是「修好的保证」)。
另一方面,「对坏掉的调用不去猜着执行而是直接拒绝」这套 harness 的 fail-closed 设计本身是正确的。需要修复的是模型侧的生成稳定性,而不是放松解析器去「凑合着改好再执行」——那会招致误执行命令这一重大风险。我们作为用户能做的最好的事,就是以避免连锁的方式运行,以及一旦复现就附上环境与日志向官方 Issue 报告(报告越多,优先级越高、修复越快)。
9. 防复发清单
Claude Code 用户:① 当 court/call 出现,最多重试两次,不行就立即 /clear/开新会话。② 避免超长、跨多日的会话,在各个节点把作业保存到 git/备忘。③ 别在一条消息里塞进过多工具调用。④ 记住 /compact 不是万能(其紧随之后有复发)。⑤ 把 CLI 保持在最新版,并在复现时向官方 Issue 报告。
API/SDK 开发者:① 始终检查 stop_reason。② 执行前检测 <invoke name=/function_calls 是否混入文本,发现就重试。③ 不要把坏掉的调用留在历史里(防止自我污染)。④ 工具参数要短,长输出要拆分。⑤ 因 max_tokens 截断而产生的不完整 tool_use 绝不执行——改为重试。
总结
在 Claude Code 中,「court/call + 原始 <invoke> 标签被显示出来、工具却没有执行」这一现象,是一个模型侧的缺陷——Claude(Opus 4.8/4.7 系列)以坏掉的形态生成了工具调用的控制 token。harness 以 fail-closed 方式拒绝了它,所以不存在误执行命令的危险(是向安全侧倾倒的案例)。真正棘手的是坏掉的块一旦残留在历史里,模型就会模仿它并「连锁」。所以「重试就能修好」只在轻症时成立,铁律变成了「失误两次就撤到新会话」。
原因分为两层:①控制 token 的生成破损 + ②自我污染导致的连锁。诱发条件包括长时间、跨多日的会话,沉重的上下文,/compact 之后的状态,多工具并发,3+ 个 MCP 服务器,以及很长的工具参数等。由于截至 2026 年 6 月官方修复尚未发布,所有应对都是规避方案。用户应「优先开新会话+勤快地保存状态」,开发者应「检查 stop_reason、检测到泄露就重试、不留坏掉的历史、缩短参数」来防守。把thinking 块 400 错误、Claude Code 错误集以及 MCP 一并阅读,会让你在工具调用相关的麻烦面前更有韧性。
FAQ
Q. 屏幕上出现的「court」或 invoke 标签,是我命令或设置的失误造成的吗?
A. 不是,几乎可以肯定不是。这是 Claude 侧以坏掉的形态生成工具调用标签的、模型侧的已知缺陷,Anthropic 官方仓库里也立了多个 Issue(#64108、#65705、#66153 等)。这不是你的环境、命令或设置的失误。请把 court/call 当作这个 bug 的「标志」。
Q. 发生这种情况时,会不会执行了错误的命令、把服务器或文件弄坏?
A. 不会。坏掉的工具调用会被判定为「不合法」,没有执行就被拒绝(fail-closed 设计)。发生的只是「那一轮空转,控制文本显示到了屏幕上」,对你的数据或服务器状态没有影响。这是向安全侧倾倒的设计。
Q. 听说「重试就会自己好」。是真的吗?
A. 只在轻症时才对。首次、单发的情况下,提示一句「继续」往往就能让它重新正确输出。但坏掉的块一旦残留在对话历史里,模型就会拿它当范本、反复以同样的方式坏掉(自我污染)。到了这一步,在同一会话里重试反而适得其反。如果连续失败两次,就别硬磨,转到新会话(/clear)。
Q. /compact 能修好吗?
A. 不可靠。压缩上下文有时会有所改善,但在 Issue #67295 中,/compact 紧随其后的首次工具调用就复发了。最可靠的做法不是 /compact,而是用新会话(/clear)把历史彻底重置。转移之前,先把作业状态保存到 git 或备忘里。
Q. 把 Claude Code 更新到最新版能修好吗?
A. 无法断言「能修好」。截至 2026 年 6 月,尚未确认有明确写明已修复该现象的官方 changelog 条目,相关 Issue 大多仍是 open 或 duplicate。更新作为卫生管理值得推荐,但不是灵丹妙药。目前最好的办法是以避免连锁的方式运行(失误两次就开新会话),以及在复现时向官方 Issue 报告。