Skip to content

fix(sse): dynamically inject skills beta only when code_execution tool is present (#14200) - #14310

Merged
diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.51from
HouMinXi:fix/14200-anthropic-skills-beta-toolless
Sep 24, 2026
Merged

diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.51from
HouMinXi:fix/14200-anthropic-skills-beta-toolless

Conversation

@HouMinXi

Copy link
Copy Markdown
Contributor

fix(sse): dynamically inject skills beta only when code_execution tool is present (#14200)

Summary

Fixes #14200.

skills-2025-10-02 beta was previously statically declared in ANTHROPIC_BETA_BASE, which caused upstream Anthropic to reject all tool-less requests (such as plain text completions) with HTTP 400:

[400]: Skills beta requires the code_execution tool to be included in the request.

This PR moves skills-2025-10-02 out of the static beta lists and injects it dynamically only when a code_execution tool is detected in the request body. It also strips the beta if forwarded by client headers when the request contains no code_execution tool.

⚠️ base-red inherited: #13866

Changes

  • open-sse/config/anthropicHeaders.ts:
    • Removed skills-2025-10-02 from ANTHROPIC_BETA_BASE, ANTHROPIC_BETA_API_KEY, and ANTHROPIC_BETA_CLAUDE_OAUTH.
    • Added hasCodeExecutionTool(body) helper to detect code_execution_20250825, code_execution tool types or functions.
    • Added maybeAppendSkillsBeta(headers, provider, body, extraCondition) to dynamically append skills-2025-10-02 when appropriate for Anthropic family providers.
    • Added syncSkillsBeta(headers, provider, body, extraCondition) and removeAnthropicBetaHeader(headers, token) to synchronize the header with the finalized request body.
    • Updated mergeClientAnthropicBeta(headers, clientBeta, model, body) to drop skills-2025-10-02 when client attempts to negotiate it on tool-less requests.
  • open-sse/executors/base.ts:
    • buildHeaders: dynamically evaluates skills beta on initial headers.
    • execute: invokes syncSkillsBeta on transformedBody after transformRequest() to guarantee headers stay in sync with the body actually sent upstream.
  • open-sse/executors/default.ts:
    • Passed body into buildHeaders.
  • open-sse/services/provider.ts:
    • Added dynamic skills beta gating to both the CC-compatible early exit and the main header path.
  • open-sse/services/claudeCodeCompatible.ts:
    • Re-exported new header helpers.
  • tests/unit/issue-14200-anthropic-skills-beta-toolless.test.ts:
    • Added test suite covering tool-less requests, tool requests, client header filtering, CC-compatible providers, and null/undefined body safety.

Verification

  • npm run typecheck:core: 0 errors
  • npm run check:cycles: 0 cycles
  • node --test-force-exit --import tsx/esm --test tests/unit/issue-14200-anthropic-skills-beta-toolless.test.ts ...: 34/34 passed

@diegosouzapw

Copy link
Copy Markdown
Owner

This is a P0 fix — every tool-less request on the API-key Anthropic path is 400ing on the current tip right now, and I confirmed it directly (skills-2025-10-02 is still unconditional in ANTHROPIC_BETA_BASE). Your fix threading maybeAppendSkillsBeta/syncSkillsBeta through base.ts, default.ts, provider.ts and the CC-compatible path, plus re-syncing after transformRequest reshapes the body, is thorough — that's the part a narrower fix would have missed. Ran both your new suite and the existing #9064 regression guard locally: 13/13 pass. Merging.

For the record: the same gate was first proposed in #10651 (@dpozimski, August) and closed by its author before merging; we'll add a courtesy Co-authored-by trailer at squash. Also worth stating in the PR body that the Claude OAuth / Claude-Code-protocol path was never affected (selectBetaFlags() replaces the header there) — only the API-key path sent the beta unconditionally.

…l is present (diegosouzapw#14200)

Anthropic requires the 'skills-2025-10-02' beta header only when a code_execution
tool is present in the request body. Statically including it in ANTHROPIC_BETA_BASE
causes upstream Anthropic to reject all tool-less requests with HTTP 400:
'Skills beta requires the code_execution tool to be included in the request.'

Move skills-2025-10-02 out of the static beta lists and introduce maybeAppendSkillsBeta
to conditionally append it only when a code_execution tool is detected in the body,
while preserving explicit client-negotiated skills betas.

Signed-off-by: Minxi Hou <houminxi@gmail.com>
@HouMinXi HouMinXi closed this Sep 24, 2026
@HouMinXi
HouMinXi force-pushed the fix/14200-anthropic-skills-beta-toolless branch from 962f95c to 7d23bcf Compare September 24, 2026 09:09
@HouMinXi HouMinXi reopened this Sep 24, 2026
@diegosouzapw
diegosouzapw merged commit 6ad5f73 into diegosouzapw:release/v3.8.51 Sep 24, 2026
9 of 16 checks passed
@HouMinXi
HouMinXi deleted the fix/14200-anthropic-skills-beta-toolless branch September 25, 2026 14:23
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.

fix(providers): Anthropic API-key path always sends skills-2025-10-02, so every tool-less request fails with 400 (regression from #9064)

2 participants