anthropics / anthropics/claude-code-action
403 when using ANTHROPIC_BASE_URL with LiteLLM proxy
- Dominant language
- TypeScript
- Stars
- 8.9k
- Forks
- 2.1k
- Avg merge
- 3d 9h
- Merged PRs (30d)
- 10
Description
## Bug description
Using `claude-code-action@v1` with `ANTHROPIC_BASE_URL` pointing to a LiteLLM proxy results in a `403 Forbidden` nginx error. The same credentials and endpoint work fine with the Anthropic SDK (`@anthropic-ai/sdk`) from the same GitHub Actions runner.
## Reproduction
```yaml
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.LITELLM_API_KEY }}
prompt: "Review this PR"
settings: >-
{"env":{"ANTHROPIC_AUTH_TOKEN":"${{ secrets.LITELLM_API_KEY }}","ANTHROPIC_BASE_URL":"https://litellm.example.com"}}
env:
ANTHROPIC_BASE_URL: https://litellm.example.com
```
## Error
```
Failed to authenticate. API Error: 403
403 Forbidden
403 Forbidden
```
## What works from the same runner
```yaml
- name: SDK test (works)
env:
ANTHROPIC_API_KEY: ${{ secrets.LITELLM_API_KEY }}
ANTHROPIC_BASE_URL: https://litellm.example.com
run: |
cd /tmp && npm install @anthropic-ai/sdk@latest
node -e "
const Anthropic = require('@anthropic-ai/sdk');
new Anthropic().messages.create({
model: 'claude-sonnet-4-6', max_tokens: 10,
messages: [{role: 'user', content: 'hi'}]
}).then(r => console.log('SUCCESS:', r.content[0].text));
"
```
This returns `SUCCESS: Hi there! How are you...` — proving the endpoint, credentials, and network path all work.
## Configurations attempted
| Config | Result |
|--------|--------|
| `anthropic_api_key` only | 403 |
| `ANTHROPIC_CUSTOM_HEADERS: "Authorization: Bearer "` | 403 |
| `settings` with `ANTHROPIC_AUTH_TOKEN` (matching Claude Code's setup.py) | 403 |
| `DISABLE_PROMPT_CACHING` + `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` | 403 |
| `classify_inline_comments: false` | 403 (main SDK call still fails) |
## Analysis
The 403 originates from the Claude Code binary spawned by `@anthropic-ai/claude-agent-sdk`, not from the action's JavaScript or the Anthropic SDK. The agent SDK's internal HTTP client appears to make API calls differently from the standard `@anthropic-ai/sdk`.
The LiteLLM proxy requires `Authorization: Bearer` or `x-api-key` headers. The standard SDK sends `x-api-key` and works. The agent SDK binary seems to either:
1. Make a side-channel API call to `api.anthropic.com` directly (bypassing `ANTHROPIC_BASE_URL`)
2. Not forward `ANTHROPIC_AUTH_TOKEN` from settings to its HTTP client
3. Use a different auth mechanism that the proxy rejects
## Environment
- `claude-code-action@v1`
- LiteLLM proxy (v1.82.3) → AWS Bedrock
- GitHub Actions ubuntu-latest (Node v20.20.1)
- Claude Code CLI works locally with the same LiteLLM proxy via `ANTHROPIC_AUTH_TOKEN` in `~/.claude/settings.json`
Contributor guide
Research direction
Start with the action configuration in the reproduction and trace how it launches the @anthropic-ai/claude-agent-sdk binary, comparing its request setup with the working @anthropic-ai/sdk example. Investigate whether ANTHROPIC_BASE_URL and the listed authentication settings reach the binary's HTTP client; done means the reproduced action call authenticates successfully through the LiteLLM proxy.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- github-actions, typescript
- Domain
- api, authentication, ci-cd
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100