Skip to content

fix: preserve thinking blocks in recall follow-up to prevent API rejection#326

Merged
BYK merged 1 commit into
mainfrom
fix/recall-followup-thinking-blocks
May 14, 2026
Merged

fix: preserve thinking blocks in recall follow-up to prevent API rejection#326
BYK merged 1 commit into
mainfrom
fix/recall-followup-thinking-blocks

Conversation

@BYK
Copy link
Copy Markdown
Owner

@BYK BYK commented May 14, 2026

Summary

  • Fix recall follow-up stripping thinking blocks: When extended thinking is enabled (default in Claude Code), the model produces thinking tokens before calling recall. The follow-up request was built with only the tool_use block, 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.
  • Fix Sentry visibility for recall follow-up errors: The log.error() call on upstream error responses only passed a string, so captureException() was never called (it requires an Error instance). Added an Error object so these failures create Sentry issues instead of being silently logged.

Repro scenario

  1. Run lore --dangerously-skip-permissions (or any thinking-enabled Claude Code session)
  2. On the first message, the model thinks and then calls recall
  3. Gateway intercepts recall, executes it, builds follow-up request
  4. Before fix: Follow-up's assistant message has only [tool_use] — API returns 400
  5. After fix: Follow-up's assistant message has [thinking, tool_use] — API accepts it

Files changed

File Change
packages/gateway/src/recall.ts Filter thinking blocks from response and include them before tool_use in follow-up
packages/gateway/src/pipeline.ts Pass Error object to log.error() on recall follow-up upstream error
packages/gateway/test/recall.test.ts 4 new tests: thinking blocks preserved, text excluded, multiple thinking blocks, backward compat

…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).
@BYK BYK force-pushed the fix/recall-followup-thinking-blocks branch from d87996e to caeae2a Compare May 14, 2026 21:01
@BYK BYK merged commit e9089c1 into main May 14, 2026
7 checks passed
@BYK BYK deleted the fix/recall-followup-thinking-blocks branch May 14, 2026 21:04
@craft-deployer craft-deployer Bot mentioned this pull request May 14, 2026
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 |
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.

1 participant