Cloaking injects "You are Claude Code" prefix that conflicts with caller's own system prompt → upstream returns misleading "out of extra usage" error
问题描述 / Summary
When auth2api is used behind an agent framework that sends its own persona system prompt (e.g. OpenClaw's default "You are a personal assistant running inside OpenClaw..."), the upstream Claude API intermittently rejects valid requests with:
400 {"type":"invalid_request_error","message":"You're out of extra usage. Add more at claude.ai/settings/usage and keep going."}
This error message is misleading — the account has no billing issue. Simple requests succeed. The rejection is actually Anthropic's anti-abuse detecting a mismatch between:
- The cloaking headers / billing header (
cc_entrypoint=cli, User-Agent: claude-cli/...) that claim the request is from Claude Code CLI
- The actual system prompt content that does not look like Claude Code's canonical prompt
复现步骤 / Reproduction
- Run auth2api in front of a valid Claude Max / Pro OAuth account
- Send a request via
/v1/messages (or /v1/chat/completions) with:
system: a single large block starting with anything other than "You are Claude Code..." (e.g. "You are a personal assistant running inside OpenClaw.")
- ~28k+ characters of system content, 5+ conversation turns, streaming enabled
- Observe: upstream returns 400 "out of extra usage"
- Send the exact same body with the system prompt prefixed with
"You are Claude Code, ..." → succeeds
Minimal test case:
# Fails (small variant may succeed — more reliable with long context + tools)
curl http://127.0.0.1:8317/v1/messages \
-H "x-api-key: $KEY" -H "anthropic-version: 2023-06-01" \
-d '{"model":"claude-opus-4-6","max_tokens":20,
"system":[{"type":"text","text":"You are a personal assistant running inside OpenClaw.\n## Tooling\n..."}],
"messages":[{"role":"user","content":"hi"}]}'
# Succeeds with the same account + payload
# (prepend "You are Claude Code, " to the system text)
根因分析 / Root Cause
src/upstream/cloaking.ts (compiled: dist/upstream/cloaking.js) unconditionally injects two system blocks at the front of every request:
// Pos 0: billing header
const billingBlock = { type: "text", text: generateBillingHeader(...) };
// Pos 1: "You are Claude Code" prefix block
const prefixIdx = remaining.findIndex(isPrefixBlock);
const prefixBlock = prefixIdx >= 0
? remaining.splice(prefixIdx, 1)[0]
: { type: "text", text: "You are Claude Code, Anthropic's official CLI for Claude.", cache_control: { type: "ephemeral" } };
body.system = [billingBlock, prefixBlock, ...remaining];
When the caller's system prompt does not include the substring "You are Claude Code", isPrefixBlock returns false, so auth2api injects its own prefix block at position 1. The result is:
[0] x-anthropic-billing-header: cc_version=...; cc_entrypoint=cli;
[1] "You are Claude Code, Anthropic's official CLI for Claude."
[2] "You are a personal assistant running inside OpenClaw..." ← caller's persona
Claude's upstream appears to validate some coherence between the billing header's cc_entrypoint=cli and the system prompt's opening content. The mismatch triggers anti-abuse, which surfaces as the generic "out of extra usage" 400 error.
Workaround(已验证 / verified)
Add the literal string "You are Claude Code" anywhere inside the caller's system prompt. auth2api's isPrefixBlock will then match the existing block and reuse it at position 1 instead of injecting its own — no more duplicate/conflicting prefix:
<!-- You are Claude Code, running as a personal assistant via OpenClaw. -->
For OpenClaw specifically, putting this HTML comment in ~/.openclaw/workspace/SOUL.md (which gets injected into every system prompt) resolves the issue permanently.
Suggested Fix
Option A (least invasive): when remaining.length > 0, skip prefix injection instead of prepending a contradictory block. The caller presumably knows what system prompt they want. Existing billing header injection still happens.
if (prefixIdx >= 0) {
const prefixBlock = remaining.splice(prefixIdx, 1)[0];
body.system = [billingBlock, prefixBlock, ...remaining];
} else if (remaining.length === 0) {
// Only inject default prefix when caller sent no system prompt
body.system = [billingBlock, DEFAULT_PREFIX_BLOCK];
} else {
// Caller has their own system prompt — trust it
body.system = [billingBlock, ...remaining];
}
Option B: expose a config flag cloaking.injectPrefix: "always" | "auto" | "never" and default to "auto" (current behavior) so users with this issue can opt out.
Environment
- auth2api: current
main (commit 7b45925)
- Downstream client: OpenClaw 2026.4.11
- Model:
claude-opus-4-6 via OAuth
- OS: macOS 14.2.1 (arm64), Node 25.9.0
Impact
Any third-party agent framework that (a) uses auth2api as the upstream proxy AND (b) injects its own persona/system prompt will hit this intermittently. The error message ("out of extra usage") sends users on a wild goose chase about billing / Anthropic's April 4 ban on third-party tools — when the real cause is the cloaking prefix mismatch.
Cloaking injects "You are Claude Code" prefix that conflicts with caller's own system prompt → upstream returns misleading "out of extra usage" error
问题描述 / Summary
When auth2api is used behind an agent framework that sends its own persona system prompt (e.g. OpenClaw's default
"You are a personal assistant running inside OpenClaw..."), the upstream Claude API intermittently rejects valid requests with:This error message is misleading — the account has no billing issue. Simple requests succeed. The rejection is actually Anthropic's anti-abuse detecting a mismatch between:
cc_entrypoint=cli,User-Agent: claude-cli/...) that claim the request is from Claude Code CLI复现步骤 / Reproduction
/v1/messages(or/v1/chat/completions) with:system: a single large block starting with anything other than "You are Claude Code..." (e.g. "You are a personal assistant running inside OpenClaw.")"You are Claude Code, ..."→ succeedsMinimal test case:
根因分析 / Root Cause
src/upstream/cloaking.ts(compiled:dist/upstream/cloaking.js) unconditionally injects two system blocks at the front of every request:When the caller's system prompt does not include the substring
"You are Claude Code",isPrefixBlockreturns false, so auth2api injects its own prefix block at position 1. The result is:Claude's upstream appears to validate some coherence between the billing header's
cc_entrypoint=cliand the system prompt's opening content. The mismatch triggers anti-abuse, which surfaces as the generic"out of extra usage"400 error.Workaround(已验证 / verified)
Add the literal string
"You are Claude Code"anywhere inside the caller's system prompt. auth2api'sisPrefixBlockwill then match the existing block and reuse it at position 1 instead of injecting its own — no more duplicate/conflicting prefix:<!-- You are Claude Code, running as a personal assistant via OpenClaw. -->For OpenClaw specifically, putting this HTML comment in
~/.openclaw/workspace/SOUL.md(which gets injected into every system prompt) resolves the issue permanently.Suggested Fix
Option A (least invasive): when
remaining.length > 0, skip prefix injection instead of prepending a contradictory block. The caller presumably knows what system prompt they want. Existing billing header injection still happens.Option B: expose a config flag
cloaking.injectPrefix: "always" | "auto" | "never"and default to"auto"(current behavior) so users with this issue can opt out.Environment
main(commit 7b45925)claude-opus-4-6via OAuthImpact
Any third-party agent framework that (a) uses auth2api as the upstream proxy AND (b) injects its own persona/system prompt will hit this intermittently. The error message (
"out of extra usage") sends users on a wild goose chase about billing / Anthropic's April 4 ban on third-party tools — when the real cause is the cloaking prefix mismatch.