#21517: fix: preserve pi-ai default betas when context1m/anthropicBeta overrides anthropic-beta header
agents
size: S
## Summary
- Fixes #21011
- When `context1m: true` or `anthropicBeta` is configured, `createAnthropicBetaHeadersWrapper` sets `options.headers["anthropic-beta"]` which gets passed to pi-ai's `createClient`. Because the Anthropic SDK's `buildHeaders` uses `Object.assign` semantics where `options.headers` comes last, this **completely replaces** pi-ai's `defaultHeaders["anthropic-beta"]` — which contains `oauth-2025-04-20` for OAuth tokens (`sk-ant-oat01-*`). Without that beta, OAuth tokens get HTTP 401.
- The fix detects OAuth tokens at stream time via `options.apiKey` (set by pi-agent-core's agent loop) and includes pi-ai's default betas (`oauth-2025-04-20`, `claude-code-20250219`, `fine-grained-tool-streaming-2025-05-14`, `interleaved-thinking-2025-05-14`) in the merged header so they are never dropped.
## Test plan
- [x] `pnpm build` succeeds
- [x] `pnpm check` (lint + format) passes
- [x] New test: context1m + OAuth token preserves all OAuth betas alongside `context-1m-2025-08-07`
- [x] New test: context1m + regular API key does NOT include OAuth-only betas
- [x] New test: custom `anthropicBeta` + OAuth preserves OAuth betas alongside custom betas
- [x] New test: no extra betas configured → wrapper is NOT applied (regression check)
- [x] Updated existing beta header tests to expect pi-ai base betas in output
- [ ] Manual: re-enable `context1m: true` locally, restart gateway, verify agent responds without 401
> This PR was authored with AI assistance.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Fixed OAuth token authentication by preserving pi-ai's default beta headers when `context1m` or custom `anthropicBeta` config overrides the `anthropic-beta` header. The fix detects OAuth tokens at stream time and ensures required betas (`oauth-2025-04-20`, `claude-code-20250219`) are never dropped, preventing HTTP 401 errors.
- Detects OAuth tokens via `sk-ant-oat` prefix check at stream time
- Merges pi-ai default betas with user-configured betas instead of replacing them
- Comprehensive test coverage for OAuth and regular API key scenarios
- Clean implementation with well-documented constants
<h3>Confidence Score: 5/5</h3>
- Safe to merge - fixes a critical OAuth authentication bug with comprehensive test coverage
- The implementation correctly addresses the root cause (header replacement via Object.assign), includes thorough test coverage for all scenarios (OAuth/regular keys, context1m/custom betas), and follows the codebase patterns. No logical errors or edge cases identified.
- No files require special attention
<sub>Last reviewed commit: b8a8f60</sub>
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#10108: fix: override stale Anthropic OAuth stealth headers for Opus 4.6
by CivilBooks · 2026-02-06
82.7%
#20104: Fix Anthropic 1M model ID: strip -1m suffix before API call
by Clawborn · 2026-02-18
74.0%
#15397: feat: support Anthropic speed:"fast" parameter passthrough
by mode80 · 2026-02-13
73.3%
#19885: test(gateway,browser): isolate tests from ambient OPENCLAW_GATEWAY_...
by NewdlDewdl · 2026-02-18
73.0%
#8805: [Bug Fix][AI-assisted] Refresh Copilot token before expiry and retr...
by Arthur742Ramos · 2026-02-04
72.5%
#10831: fix(agents): set Opus 4.6 context window to 1M in forward-compat fa...
by slawt · 2026-02-07
72.3%
#2123: fix(auth): sync from Claude CLI keychain before OAuth refresh
by jorge123255 · 2026-01-26
72.1%
#15689: fix: propagate provider headers to inline model objects
by julius2016 · 2026-02-13
72.0%
#16684: fix:(antigravity): align Antigravity OAuth project discovery header...
by vincentkoc · 2026-02-15
71.7%
#16100: fix: convert unsigned thinking blocks to text to prevent signature ...
by claw-sylphx · 2026-02-14
71.5%