Skip to content

fix: fall back to compact tool preamble before rejecting oversized tool payloads#74

Closed
baily-zhang wants to merge 1 commit into
dwgx:masterfrom
baily-zhang:fix/tool-preamble-fallback
Closed

fix: fall back to compact tool preamble before rejecting oversized tool payloads#74
baily-zhang wants to merge 1 commit into
dwgx:masterfrom
baily-zhang:fix/tool-preamble-fallback

Conversation

@baily-zhang
Copy link
Copy Markdown
Contributor

问题

最近引入的 tool preamble 预算逻辑会在 完整 tool 定义 超过 hard cap 时直接返回:

{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "Tool definitions are too large (74KB > 47KB). Reduce the number of tools or shorten parameter schemas."
  }
}

在 Claude Code / opencode / Cline 这类客户端里,首轮请求通常会附带 20+ 个工具和较大的参数 schema。这样会导致:

  • 首次 prompt 直接 400,还没进入正常对话就失败
  • 用户看到的是 Claude Code 前端报错,以为服务不可用
  • 代理虽然已经有 buildCompactToolPreambleForProto(),但这条 fallback 根本没有被用到

影响

这不是偶发上游错误,而是本地预算逻辑的回归:

  • 只要完整 preamble 超过 hard cap,就会在入口被拒绝
  • 即使 compact preamble 只有 1~2KB、完全可以继续请求,也不会尝试 fallback
  • 对 Claude Code 影响尤其明显,因为它默认会携带完整工具定义,用户在升级到最新版本后会在第一条消息就遇到 400

根因

当前逻辑顺序是:

  1. 先计算 full preamble 大小
  2. full > hard cap 时直接 tool_preamble_too_large
  3. 只有 full > soft cap && full <= hard cap 时才会走 compact fallback

也就是说,最需要 compact fallback 的场景反而被提前 reject 了

修复

这次改动把预算决策抽成独立 helper,并改成下面的顺序:

  1. full <= soft:继续使用完整 preamble
  2. full > soft:先尝试 compact fallback
  3. compact <= hard:使用 compact preamble 继续请求
  4. 只有 fullcompact 都超过 hard cap 时,才返回 400

这样可以保证:

  • 大工具集请求优先降级到 names-only compact preamble
  • 只有真正塞不下时才拒绝
  • Claude Code 首次 prompt 不会再因为 74KB > 47KB 在入口直接报错

验证

新增回归测试覆盖两种情况:

  1. full > hardcompact <= hard:必须 fallback 到 compact
  2. full > hardcompact > hard:才允许 reject

本地聚焦测试:

node --test test/chat-tool-preamble-budget.test.js test/tool-emulation.test.js

另外用一份 30 个工具的大请求实测,本地日志现在会出现:

toolPreamble 118KB exceeds soft/hard budget; falling back to names-only preamble (1KB, 30 tools)

请求可以继续返回 200,而不是直接 400。

@dwgx
Copy link
Copy Markdown
Owner

dwgx commented Apr 26, 2026

image xie'xie'l谢谢你了 bailyzhang我今天有codex跑了一大堆 过两天我不写了 你来 谢谢你!!

@dwgx
Copy link
Copy Markdown
Owner

dwgx commented Apr 26, 2026

谢了 baily,思路对得不能再对。这条线一周已经走过两轮:

  • 818b4d2 给 Bash/Read/Write 一类高保真工具加 compact fallback hints
  • 8f50c6b 修了 Bash 命令前缀截断的回退场景
  • 现有 applyToolPreambleBudget + test/tool-preamble-budget.test.js 已经把 compact 优先于硬拒的行为锁死

你这版的 root cause 诊断跟现有实现重合,差别基本上只是命名和分支风格。为了不让 history 里同一条改动两个人重写,先按现有 commit 关掉这个 PR。

反代复用机制能走到今天 #36 / #45 / #61 / #62 都是你扛起来的,下一版 release notes 会再写一次。下次有诡异行为可以直接发 issue 带个最小复现,几小时内能落 commit,比 PR 快。

@dwgx dwgx closed this Apr 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants