fix: preserve thinking blocks in recall follow-up to prevent API rejection#326
Merged
Conversation
…ction When extended thinking is enabled, the Anthropic API requires thinking blocks (with cryptographic signatures) to precede tool_use blocks in assistant messages. The recall follow-up was stripping all non-tool_use blocks, causing a 400 validation error after the model produced thinking tokens and then called recall. Also pass an Error object to log.error() on recall follow-up upstream errors so they are captured as Sentry issues (previously only logged as strings, which produce breadcrumbs but never trigger captureException).
d87996e to
caeae2a
Compare
6 tasks
BYK
added a commit
that referenced
this pull request
May 15, 2026
…330) ## Summary - **Fix "model called invalid tool: recall" error:** `buildRecallFollowUp()` was stripping the `recall` tool from the follow-up request's tools list, but the assistant message still contained a `tool_use` block referencing it. The Anthropic API validates that all `tool_use` blocks in messages reference tools in the tools list, causing rejection. - **Unmasked by PR #326:** The thinking blocks fix allowed the follow-up request to get past the previous 400 error, revealing this secondary tools-list validation failure. ## Repro scenario 1. Model calls `recall` as its only tool use (recall-only path) 2. Gateway intercepts, executes recall, builds follow-up with `tool_result` 3. **Before fix:** Follow-up's tools list excludes `recall`, but assistant message contains `recall` `tool_use` block → API rejects with "model called invalid tool: recall" 4. **After fix:** Follow-up preserves all tools including `recall` → API accepts ## Files changed | File | Change | |---|---| | `packages/gateway/src/recall.ts` | Remove `toolsWithoutRecall` filter — pass `originalReq.tools` through unchanged | | `packages/gateway/test/recall.test.ts` | Update assertion to verify recall tool is preserved in follow-up |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
tool_useblock, stripping the required thinking blocks (with cryptographic signatures). The Anthropic API rejects this with a 400 error. Now thinking blocks from the original response are preserved in the follow-up assistant message.log.error()call on upstream error responses only passed a string, socaptureException()was never called (it requires anErrorinstance). Added anErrorobject so these failures create Sentry issues instead of being silently logged.Repro scenario
lore --dangerously-skip-permissions(or any thinking-enabled Claude Code session)recall[tool_use]— API returns 400[thinking, tool_use]— API accepts itFiles changed
packages/gateway/src/recall.tstool_usein follow-uppackages/gateway/src/pipeline.tsErrorobject tolog.error()on recall follow-up upstream errorpackages/gateway/test/recall.test.ts