Skip to content

OAuth Anthropic provider: clear_thinking_20251015 strategy forwarded without thinking block → 400 from upstream #894

@ojsol

Description

@ojsol

Summary

When Claude Code is configured with an OAuth-authenticated Anthropic provider in Tingly Box and the orchestrator model has extended thinking enabled (default for Opus 4.7), every request to POST /tingly/claude_code/v1/messages?beta=true fails with a 400 from upstream:

{"type":"error","error":{"type":"invalid_request_error","message":"`clear_thinking_20251015` strategy requires `thinking` to be enabled or adaptive"},"request_id":"req_011CasKQviFdqAv4S7D1CcqU"}

Anthropic is rejecting the upstream request because the body contains context_management.strategy: clear_thinking_20251015 but no matching thinking block. Hypothesis: Tingly's protocol-translation pipeline preserves the context_management field while dropping the thinking field somewhere on the OAuth Anthropic path. The two must travel together.

The error is non-recoverable from the client side — Claude Code retries up to 10 times with exponential backoff, each retry burning quota against the user's Anthropic 7-day window before the session times out.

Environment

  • Tingly Box: v0.260507.1 (binary at ~/.cache/tingly-box/v0.260507.1/bin/tingly-box)
  • Claude Code: 2.1.138
  • OS: Linux x86_64
  • Provider auth type: OAuth (Claude Code) — Claude.ai Pro/Max subscription
  • Provider name (auto-generated): claude_code-YYYYMMDD-HHMM
  • Upstream model selected by routing: claude-opus-4-7
  • Endpoint receiving traffic: POST /tingly/claude_code/v1/messages?beta=true

Steps to reproduce

  1. Add an OAuth Anthropic provider via the UI (OAuth → Add Auth Provider → Claude Code).
  2. Run tingly-box apply cc --provider <oauth-provider-name> --model claude-opus-4-7 (or wire ~/.claude/settings.json manually) so Claude Code routes through http://127.0.0.1:12580/tingly/claude_code with ANTHROPIC_DEFAULT_OPUS_MODEL=tingly/cc-opus.
  3. Configure the Tingly rule for tingly/cc-opus to point at the OAuth provider with model claude-opus-4-7.
  4. Launch Claude Code with "model": "opus" in ~/.claude/settings.json and the default thinking effort (High). Do not set MAX_THINKING_TOKENS=0.
  5. Send any prompt.

Expected: a normal response from Anthropic Opus 4.7.

Actual: tight retry loop with 500s from Tingly wrapping the 400 above.

Relevant log lines

From ~/.tingly-box/log/tingly-box.jsonl:

[error] POST /tingly/claude_code/v1/messages?beta=true 500 — error: "Failed to forward request: POST \"https://api.anthropic.com/v1/messages?beta=true\": 400 Bad Request ... `clear_thinking_20251015` strategy requires `thinking` to be enabled or adaptive"

Earlier in the same log (after rule reconfiguration but before the strategy error surfaced), a related 500 also appeared with CLAUDE_CODE_MAX_OUTPUT_TOKENS=32000:

[error] POST /tingly/claude_code/v1/messages?beta=true 500 — error: "streaming is required for operations that may take longer than 10 minutes"

That one was sidestepped by lowering CLAUDE_CODE_MAX_OUTPUT_TOKENS from the apply-default of 32000 to 8192. Worth noting because the apply CLI ships a default that Anthropic's policy now rejects without streaming — possibly a separate small bug.

Workaround

Setting MAX_THINKING_TOKENS=0 in ~/.claude/settings.json env block disables Claude Code's extended thinking, which in turn stops Claude Code from attaching the clear_thinking_20251015 strategy. Requests then succeed.

This is acceptable as a temporary workaround but disables Opus 4.7's reasoning quality on the orchestrator — the very feature most users pay for the subscription to get.

Suggested fix

In the protocol-transform pipeline that handles the OAuth Anthropic path (likely internal/protocol/transform/... and the assembler/dispatch layer touched by recent PRs like #865, #875), preserve the thinking field alongside context_management when forwarding to upstream Anthropic. The two are coupled — if context_management.strategy is one of the clear_thinking_* family, thinking must be present (or removed together).

Either option resolves it:

  • (a) Forward thinking alongside context_management whenever both are present in the incoming request.
  • (b) Strip context_management.strategy matching ^clear_thinking_ whenever thinking is being stripped.

Option (a) preserves Claude Code behavior; (b) is safer if there's a reason thinking must be removed for OAuth.

Related

  • The streaming is required error suggests the apply CLI's default CLAUDE_CODE_MAX_OUTPUT_TOKENS=32000 value is now too high for non-streaming paths. Consider lowering the default to 8192 in internal/agent/apply.go::GenerateClaudeCodeEnv.
  • This blocks the canonical "Opus orchestrator + DeepSeek subagents" topology Tingly Box markets toward Claude Code users with a Pro/Max subscription.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions