fix: always apply Anthropic beta headers wrapper for OAuth token support#41461
fix: always apply Anthropic beta headers wrapper for OAuth token support#41461hnykda wants to merge 1 commit intoopenclaw:mainfrom
Conversation
The `createAnthropicBetaHeadersWrapper` was only applied when `resolveAnthropicBetas` returned non-empty (i.e., when `context1m` or `anthropicBeta` was set in agent extra params). When `context-1m` was configured via model-level headers instead of extra params, the wrapper was never applied, so the critical `oauth-2025-04-20` beta was never injected for OAuth tokens (`sk-ant-oat-*`). This caused Anthropic to reject all requests with HTTP 401 "OAuth authentication is currently not supported." Now the wrapper is always applied for Anthropic providers, ensuring OAuth token detection and beta injection runs unconditionally. Fixes openclaw#41444 Related: openclaw#19769, openclaw#19789 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR fixes a critical bug where the Key changes:
Minor observation: The debug log is only emitted when explicit betas are non-empty. When the wrapper runs with only default/OAuth betas, nothing is logged, which could make runtime diagnostics harder when troubleshooting OAuth failures in production. Confidence Score: 5/5
Last reviewed commit: efdb349 |
| if (provider === "anthropic") { | ||
| const betas = anthropicBetas ?? []; | ||
| if (betas.length) { | ||
| log.debug(`applying Anthropic beta header for ${provider}/${modelId}: ${betas.join(",")}`); | ||
| } | ||
| agent.streamFn = createAnthropicBetaHeadersWrapper(agent.streamFn, betas); | ||
| } |
There was a problem hiding this comment.
The debug log is only emitted when betas.length > 0. When the wrapper runs with no explicit betas (lines 362–367), nothing is logged, even though the wrapper actively injects PI_AI_DEFAULT_ANTHROPIC_BETAS (or PI_AI_OAUTH_ANTHROPIC_BETAS for OAuth tokens) into headers.
For production debugging—especially with OAuth failures that return HTTP 401—this silent operation could be misleading. Developers troubleshooting may not realize the wrapper actually ran.
Consider logging unconditionally (or at least the effective betas being injected):
| if (provider === "anthropic") { | |
| const betas = anthropicBetas ?? []; | |
| if (betas.length) { | |
| log.debug(`applying Anthropic beta header for ${provider}/${modelId}: ${betas.join(",")}`); | |
| } | |
| agent.streamFn = createAnthropicBetaHeadersWrapper(agent.streamFn, betas); | |
| } | |
| if (provider === "anthropic") { | |
| const betas = anthropicBetas ?? []; | |
| log.debug( | |
| `applying Anthropic beta headers wrapper for ${provider}/${modelId}` + | |
| (betas.length ? `: configured betas=[${betas.join(",")}]` : " (no explicit betas; defaults/OAuth betas still applied)"), | |
| ); | |
| agent.streamFn = createAnthropicBetaHeadersWrapper(agent.streamFn, betas); | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-runner/extra-params.ts
Line: 362-368
Comment:
The debug log is only emitted when `betas.length > 0`. When the wrapper runs with no explicit betas (lines 362–367), nothing is logged, even though the wrapper actively injects `PI_AI_DEFAULT_ANTHROPIC_BETAS` (or `PI_AI_OAUTH_ANTHROPIC_BETAS` for OAuth tokens) into headers.
For production debugging—especially with OAuth failures that return HTTP 401—this silent operation could be misleading. Developers troubleshooting may not realize the wrapper actually ran.
Consider logging unconditionally (or at least the effective betas being injected):
```suggestion
if (provider === "anthropic") {
const betas = anthropicBetas ?? [];
log.debug(
`applying Anthropic beta headers wrapper for ${provider}/${modelId}` +
(betas.length ? `: configured betas=[${betas.join(",")}]` : " (no explicit betas; defaults/OAuth betas still applied)"),
);
agent.streamFn = createAnthropicBetaHeadersWrapper(agent.streamFn, betas);
}
```
How can I resolve this? If you propose a fix, please make it concise.|
This pull request has been automatically marked as stale due to inactivity. |
|
Codex review: needs changes before merge. Summary Reproducibility: yes. source-backed. Direct Anthropic OAuth with an Next step before merge Security Review findings
Review detailsBest possible solution: Land a narrow replacement in the bundled Anthropic provider plugin that preserves required OAuth/default betas for direct Anthropic OAuth requests even without extra-param betas, keeps custom endpoint suppression, and adds focused regression coverage plus changelog. Do we have a high-confidence way to reproduce the issue? Yes, source-backed. Direct Anthropic OAuth with an Is this the best way to solve the issue? No. Always applying beta merging is the right direction for direct Anthropic OAuth, but this PR changes obsolete embedded-runner glue instead of the active Anthropic plugin and does not preserve the custom-endpoint guard required by current docs and tests. Full review comments:
Overall correctness: patch is incorrect Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 89a15fddaf84. |
Summary
createAnthropicBetaHeadersWrapperfor Anthropic providers, not just whenresolveAnthropicBetas()returns non-emptyoauth-2025-04-20beta is injected for OAuth tokens (sk-ant-oat-*) even whencontext1mis configured via model-levelheadersinstead of agent extra paramsProblem
When
context-1m-2025-08-07is set inmodels.providers.anthropic.models[].headers(model-level) rather than inagents.defaults.models[].params.context1m(extra params),resolveAnthropicBetas()returnsundefined, socreateAnthropicBetaHeadersWrapperis never applied. The pi-ai SDK detects thesk-ant-oatprefix and usesAuthorization: Bearer, but without the requiredoauth-2025-04-20beta header, Anthropic rejects with:The fix from #19789 correctly handles this inside the wrapper, but the wrapper was gated behind a non-empty betas check that prevented it from running.
Changes
extra-params.ts: Always apply the beta headers wrapper forprovider === "anthropic", passing an empty array when no explicit betas are configured. The wrapper's internal OAuth detection then runs unconditionally.pi-embedded-runner-extraparams.test.ts: Updated existing test and added new test for OAuth tokens withoutcontext1mconfigured.Test plan
sk-ant-oattokens even withoutcontext1mFixes #41444
Related: #19769, #19789
🤖 Generated with Claude Code