/anthropic-sub-proxy
Troubleshoot and configure the Anthropic Subscription Proxy for OpenClaw. Use when the user has "The AI service returned an error", 401 auth failures through the proxy, key routing issues, pi-ai baseUrl overwrites, or needs help setting up the Claude Code proxy with OpenClaw.
$ npx -y skills add John-Rood/claude-proxy --skill anthropic-sub-proxy --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/anthropic-sub-proxy
Context preview
The summary Claude sees to decide when to auto-load this skill.
Troubleshoot and configure the Anthropic Subscription Proxy for OpenClaw. Use when the user has "The AI service returned an error", 401 auth failures through the proxy, key routing issues, pi-ai baseUrl overwrites, or needs help setting up the Claude Code proxy with OpenClaw.
SKILL.md
anthropic-sub-proxy.SKILL.mdname: anthropic-sub-proxy
description: Troubleshoot and configure the Anthropic Subscription Proxy for OpenClaw. Use when the user has "The AI service returned an error", 401 auth failures through the proxy, key routing issues, pi-ai baseUrl overwrites, or needs help setting up the Claude Code proxy with OpenClaw. Also use when the proxy is not receiving requests, or requests bypass the proxy entirely.
Anthropic Subscription Proxy — Troubleshooting
The proxy is a lightweight Node.js server (~150 lines, zero dependencies) that sits between OpenClaw and api.anthropic.com. It adds the Claude Code envelope (beta header + system prompt) to requests so Claude Code subscription billing applies instead of direct API billing.
**Proxy repo:** Separate from this skill. The user should already have `index.js` and `config.json` deployed.
How It Works
OpenClaw → localhost:<port> → Proxy → api.anthropic.com
↓
1. Pass through client's API key unchanged
2. Add anthropic-beta: claude-code-20250219
3. Prepend "You are Claude Code..." system prompt
4. Stream response back untouchedThe proxy is **passthrough by default** — it forwards whatever API key the client sends. No keys need to be configured in the proxy itself.
Critical: How Keys Actually Work
The only key that reliably works
The key managed by Claude Code CLI in the **macOS Keychain** (`sk-ant-api03-...`). This is the key tied to whichever account is currently logged into Claude Code CLI. It gets auto-synced into OpenClaw's auth system at runtime, regardless of what's in config files.
setup-token keys (`sk-ant-oat01-...`) are unreliable
Tokens generated via `claude setup-token` consistently arrive invalid (401 `invalid x-api-key`) even when generated moments before testing. The reason is unknown — they may not be activating server-side, or they may require a different auth flow. **Do not rely on these for the proxy.**
What this means
- **One subscription at a time.** Claude Code CLI only stores one account's credentials. The proxy can only use that one key.
- **auth-profiles.json is misleading.** OpenClaw's auth system auto-syncs from the Keychain on every load, overriding whatever is manually configured. The token Claudius actually sends may not match any named profile in the config.
- **Round-robin across multiple subscriptions is not currently possible** unless multiple valid `sk-ant-api03` keys can be captured from separate Claude Code CLI sessions (which requires logging in and out — and logging out may revoke the previous key).
To identify which key is actually being used
Check the runtime auth log, not the config files:
grep "ANTHROPIC-AUTH" <openclaw-log> | tail -5
The `tokenPrefix` field shows what's actually being sent. Compare against:
- Config keys in `auth-profiles.json`
- Keychain-synced keys (auto-injected, no profile name)
If the token prefix doesn't match any configured profile, it's coming from the Keychain sync.
Diagnostic Checklist
When the user reports errors, run through these checks in order:
1. Is the proxy running?
lsof -iTCP:<port> -sTCP:LISTEN -P
curl -s http://127.0.0.1:<port>/health
If not running, start it:
cd <proxy-dir> && nohup node index.js >> proxy.log 2>&1 &
2. Is OpenClaw actually hitting the proxy?
curl -s http://127.0.0.1:<port>/status
# Check requestsServed — if 0 after sending a message, requests aren't reaching the proxy
Also check the proxy log:
tail -20 <proxy-dir>/proxy.log
3. Is the baseUrl override being respected?
**This is the #1 issue.** OpenClaw's pi-ai model catalog (`models.generated.js`) hardcodes `baseUrl` for every model, **overriding** whatever is in the OpenClaw config.
Find and patch the model catalog:
# Find the file
find <openclaw-install-dir> -name "models.generated.js" -path "*/pi-ai/*"
# Check current Anthropic baseUrls
grep "baseUrl" <path-to-models.generated.js> | sort -u
# Patch all Anthropic models to point at the proxy
sed -i '' 's|https://api.anthropic.com|http://127.0.0.1:<port>|g' <path-to-models.generated.js>
# Verify
grep -c "127.0.0.1:<port>" <path-to-models.generated.js>
**⚠️ This patch gets wiped on OpenClaw updates/reinstalls.** Re-run after any update.
4. Auth token issues (401 errors)
If the proxy returns 401 or Anthropic returns 401:
**Check what token OpenClaw is actually sending** — look for `ANTHROPIC-AUTH` in OpenClaw's logs:
grep "ANTHROPIC-AUTH" <openclaw-log> | tail -5
Common problems:
a. OpenClaw syncs tokens from Claude Code's Keychain
OpenClaw's auth system auto-syncs credentials from Claude Code CLI's macOS Keychain on every load. This **overrides** whatever is in `auth-profiles.json`. If old/expired tokens exist in the Keychain, OpenClaw will use them.
**Fix:** The proxy should NOT validate client keys. Ensure the proxy accepts any key (passthrough mode). The proxy's job is only to add the envelope, not to authenticate.
b. Multiple auth profiles cycling
If OpenClaw has multiple Anthropic auth profiles (manual, manual2, manual3, default), it round-robins through them. Some may be dead/expired.
**Check config:**
# Show auth order
cat <openclaw-config> | python3 -c "
import json, sys
cfg = json.load(sys.stdin)
order = cfg.get('auth',{}).get('order',{}).get('anthropic',[])
print('Auth order:', order)
profiles = cfg.get('auth',{}).get('profiles',{})
for name, p in profiles.items():
if 'anthropic' in name:
print(f' {name}: mode={p.get(\"mode\",\"?\")}')"**Fix:** Either ensure all profiles have valid keys, or trim the auth order to only valid profiles.
c. OAuth tokens expire
OAuth tokens (`sk-ant-oat01-...`) expire and need refresh. If refresh fails, the request fails.
**Fix:** Remove dead OAuth profiles fro
Read more
name: anthropic-sub-proxy description: Troubleshoot and configure the Anthropic Subscription Proxy for OpenClaw. Use when the user has "The AI service returned an error", 401 auth failures through the proxy, key routing issues, pi-ai baseUrl overwrites, or needs help setting up the Claude Code proxy with OpenClaw. Also use when the proxy is not receiving requests, or requests bypass the proxy entirely.
Anthropic Subscription Proxy — Troubleshooting
The proxy is a lightweight Node.js server (~150 lines, zero dependencies) that sits between OpenClaw and api.anthropic.com. It adds the Claude Code envelope (beta header + system prompt) to requests so Claude Code subscription billing applies instead of direct API billing.
**Proxy repo:** Separate from this skill. The user should already have `index.js` and `config.json` deployed.
How It Works
OpenClaw → localhost:<port> → Proxy → api.anthropic.com
↓
1. Pass through client's API key unchanged
2. Add anthropic-beta: claude-code-20250219
3. Prepend "You are Claude Code..." system prompt
4. Stream response back untouchedThe proxy is **passthrough by default** — it forwards whatever API key the client sends. No keys need to be configured in the proxy itself.
Critical: How Keys Actually Work
The only key that reliably works
The key managed by Claude Code CLI in the **macOS Keychain** (`sk-ant-api03-...`). This is the key tied to whichever account is currently logged into Claude Code CLI. It gets auto-synced into OpenClaw's auth system at runtime, regardless of what's in config files.
setup-token keys (`sk-ant-oat01-...`) are unreliable
Tokens generated via `claude setup-token` consistently arrive invalid (401 `invalid x-api-key`) even when generated moments before testing. The reason is unknown — they may not be activating server-side, or they may require a different auth flow. **Do not rely on these for the proxy.**
What this means
- **One subscription at a time.** Claude Code CLI only stores one account's credentials. The proxy can only use that one key.
- **auth-profiles.json is misleading.** OpenClaw's auth system auto-syncs from the Keychain on every load, overriding whatever is manually configured. The token Claudius actually sends may not match any named profile in the config.
- **Round-robin across multiple subscriptions is not currently possible** unless multiple valid `sk-ant-api03` keys can be captured from separate Claude Code CLI sessions (which requires logging in and out — and logging out may revoke the previous key).
To identify which key is actually being used
Check the runtime auth log, not the config files:
grep "ANTHROPIC-AUTH" <openclaw-log> | tail -5
The `tokenPrefix` field shows what's actually being sent. Compare against:
- Config keys in `auth-profiles.json`
- Keychain-synced keys (auto-injected, no profile name)
If the token prefix doesn't match any configured profile, it's coming from the Keychain sync.
Diagnostic Checklist
When the user reports errors, run through these checks in order:
1. Is the proxy running?
lsof -iTCP:<port> -sTCP:LISTEN -P curl -s http://127.0.0.1:<port>/health
If not running, start it:
cd <proxy-dir> && nohup node index.js >> proxy.log 2>&1 &
2. Is OpenClaw actually hitting the proxy?
curl -s http://127.0.0.1:<port>/status # Check requestsServed — if 0 after sending a message, requests aren't reaching the proxy
Also check the proxy log:
tail -20 <proxy-dir>/proxy.log
3. Is the baseUrl override being respected?
**This is the #1 issue.** OpenClaw's pi-ai model catalog (`models.generated.js`) hardcodes `baseUrl` for every model, **overriding** whatever is in the OpenClaw config.
Find and patch the model catalog:
# Find the file find <openclaw-install-dir> -name "models.generated.js" -path "*/pi-ai/*" # Check current Anthropic baseUrls grep "baseUrl" <path-to-models.generated.js> | sort -u # Patch all Anthropic models to point at the proxy sed -i '' 's|https://api.anthropic.com|http://127.0.0.1:<port>|g' <path-to-models.generated.js> # Verify grep -c "127.0.0.1:<port>" <path-to-models.generated.js>
**⚠️ This patch gets wiped on OpenClaw updates/reinstalls.** Re-run after any update.
4. Auth token issues (401 errors)
If the proxy returns 401 or Anthropic returns 401:
**Check what token OpenClaw is actually sending** — look for `ANTHROPIC-AUTH` in OpenClaw's logs:
grep "ANTHROPIC-AUTH" <openclaw-log> | tail -5
Common problems:
a. OpenClaw syncs tokens from Claude Code's Keychain
OpenClaw's auth system auto-syncs credentials from Claude Code CLI's macOS Keychain on every load. This **overrides** whatever is in `auth-profiles.json`. If old/expired tokens exist in the Keychain, OpenClaw will use them.
**Fix:** The proxy should NOT validate client keys. Ensure the proxy accepts any key (passthrough mode). The proxy's job is only to add the envelope, not to authenticate.
b. Multiple auth profiles cycling
If OpenClaw has multiple Anthropic auth profiles (manual, manual2, manual3, default), it round-robins through them. Some may be dead/expired.
**Check config:**
# Show auth order
cat <openclaw-config> | python3 -c "
import json, sys
cfg = json.load(sys.stdin)
order = cfg.get('auth',{}).get('order',{}).get('anthropic',[])
print('Auth order:', order)
profiles = cfg.get('auth',{}).get('profiles',{})
for name, p in profiles.items():
if 'anthropic' in name:
print(f' {name}: mode={p.get(\"mode\",\"?\")}')"**Fix:** Either ensure all profiles have valid keys, or trim the auth order to only valid profiles.
c. OAuth tokens expire
OAuth tokens (`sk-ant-oat01-...`) expire and need refresh. If refresh fails, the request fails.
**Fix:** Remove dead OAuth profiles fro
A lightweight Node.js proxy (~150 lines, zero dependencies) that wraps Anthropic API requests with the Claude Code envelope, routing billing through your Claude Code subscription instead of direct API credits.

