For a rotating Claude gateway, key off the provider, not the token prefix

If you put Pi behind a local Anthropic gateway that rotates multiple Claude accounts, the interesting part is not the token format. The gateway may hand Pi a placeholder token like claude, while the real upstream auth happens inside the proxy. That means request shaping should be attached to the anthropic provider itself, not gated on whether the token looks like sk-ant-oat....

In pi-anthropic-auth, the fix was to make the transport wrapper unconditional for Anthropic requests. Pi already routes the built-in anthropic provider through the same registry transport, so once the request is in that lane, it can be shaped every time:

pi.registerProvider("anthropic", {
  oauth: anthropicOAuthOverride,
  api: "anthropic-messages",
  streamSimple: createAnthropicOAuthStreamSimple(builtinTransport.streamSimple),
});

That lets the proxy stay dumb and flexible. I ended up using ~/.pi/agent/models.json to point anthropic.baseUrl at the local gateway, and a placeholder OAuth record in ~/.pi/agent/auth.json:

{
  "providers": {
    "anthropic": {
      "baseUrl": "http://gateway-host:9949"
    }
  }
}
{
  "anthropic": {
    "type": "oauth",
    "access": "claude",
    "refresh": "",
    "expires": 1813218019502
  }
}

The gateway can then rotate across multiple Claude accounts behind the scenes, so one account hitting the 5-hour wall does not interrupt the session. Pi still sees a normal Anthropic provider, and the shaping layer still injects the Claude Code billing header and prompt normalization before the request leaves the machine.

Comments

  1. Markdown is allowed. HTML tags allowed: <strong>, <em>, <blockquote>, <code>, <pre>, <a>.