Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/api-proxy-sidecar.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ When enabled, the API proxy sidecar:
│ │ │ Agent Container │ │
│ │ │ 172.30.0.20 │ │
│ │ │ OPENAI_BASE_URL= │ │
│ │ │ http://172.30.0.30:10000/v1│────┘
│ │ │ http://172.30.0.30:10000 │────┘
│ │ │ ANTHROPIC_BASE_URL= │
│ │ │ http://172.30.0.30:10001 │
│ │ └──────────────────────────────┘
Expand Down Expand Up @@ -76,7 +76,7 @@ sudo awf --enable-api-proxy \
-- npx @openai/codex -p "write a hello world function"
```

The agent container automatically uses `http://172.30.0.30:10000/v1` as the OpenAI base URL.
The agent container automatically uses `http://172.30.0.30:10000` as the OpenAI base URL.

### Claude Code example

Expand Down Expand Up @@ -138,7 +138,7 @@ The agent container receives **redacted placeholders** and proxy URLs:

| Variable | Value | When set | Description |
|----------|-------|----------|-------------|
| `OPENAI_BASE_URL` | `http://172.30.0.30:10000/v1` | `OPENAI_API_KEY` provided to host | Redirects OpenAI SDK to proxy |
| `OPENAI_BASE_URL` | `http://172.30.0.30:10000` | `OPENAI_API_KEY` provided to host | Redirects OpenAI SDK to proxy |
| `ANTHROPIC_BASE_URL` | `http://172.30.0.30:10001` | `ANTHROPIC_API_KEY` provided to host | Redirects Anthropic SDK to proxy |
| `ANTHROPIC_AUTH_TOKEN` | `placeholder-token-for-credential-isolation` | `ANTHROPIC_API_KEY` provided to host | Placeholder token (real auth via BASE_URL) |
| `CLAUDE_CODE_API_KEY_HELPER` | `/usr/local/bin/get-claude-key.sh` | `ANTHROPIC_API_KEY` provided to host | Helper script for Claude Code CLI |
Expand Down Expand Up @@ -231,7 +231,7 @@ When you pass `--enable-api-proxy`:

```
Agent Code
↓ (HTTP request to 172.30.0.30:10000/v1)
↓ (HTTP request to 172.30.0.30:10000)
Node.js API Proxy
↓ (strips client auth headers)
↓ (injects Authorization: Bearer $OPENAI_API_KEY)
Expand Down
10 changes: 5 additions & 5 deletions docs/authentication-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ AWF uses a **3-container architecture** when API proxy mode is enabled:
│ ✓ HTTP_PROXY=172.30.0.10:3128 │ │ ✓ ANTHROPIC_BASE_URL= │
│ ✓ HTTPS_PROXY=172.30.0.10:3128 │ │ http://172.30.0.30:10001 │
│ │ │ ✓ OPENAI_BASE_URL= │
│ Ports: │ │ http://172.30.0.30:10000/v1
│ Ports: │ │ http://172.30.0.30:10000
│ - 10000 (OpenAI proxy) │◄──────│ ✓ GITHUB_TOKEN=ghp_... │
│ - 10001 (Anthropic proxy) │ │ (protected by one-shot-token) │
│ │ │ │
Expand Down Expand Up @@ -113,7 +113,7 @@ agent:
environment:
# NO API KEYS - only base URLs pointing to api-proxy
- ANTHROPIC_BASE_URL=http://172.30.0.30:10001
- OPENAI_BASE_URL=http://172.30.0.30:10000/v1
- OPENAI_BASE_URL=http://172.30.0.30:10000
# GitHub token for MCP servers (protected separately)
- GITHUB_TOKEN=ghp_...
networks:
Expand Down Expand Up @@ -174,7 +174,7 @@ The agent container sees these environment variables:

```bash
ANTHROPIC_BASE_URL=http://172.30.0.30:10001
OPENAI_BASE_URL=http://172.30.0.30:10000/v1
OPENAI_BASE_URL=http://172.30.0.30:10000
```

These are standard environment variables recognized by the official SDKs:
Expand Down Expand Up @@ -209,7 +209,7 @@ import openai

client = openai.OpenAI()
# SDK reads OPENAI_BASE_URL from environment
# Sends request to http://172.30.0.30:10000/v1 instead of api.openai.com
# Sends request to http://172.30.0.30:10000 instead of api.openai.com

response = client.chat.completions.create(
model="gpt-4",
Expand Down Expand Up @@ -250,7 +250,7 @@ Without the NAT `RETURN` rule, traffic to `172.30.0.30` would be redirected to S

**Traffic flow for OpenAI/Codex:**

1. Agent SDK makes HTTP request to `172.30.0.30:10000/v1`
1. Agent SDK makes HTTP request to `172.30.0.30:10000`
2. iptables allows direct TCP connection (NAT `RETURN` rule)
3. API proxy receives request on port 10000
4. API proxy injects `Authorization: Bearer sk-...` header
Expand Down
12 changes: 6 additions & 6 deletions src/docker-manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2345,7 +2345,7 @@ describe('docker-manager', () => {
const result = generateDockerCompose(configWithProxy, mockNetworkConfigWithProxy);
const agent = result.services.agent;
const env = agent.environment as Record<string, string>;
expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000/v1');
expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000');
});

it('should configure HTTP_PROXY and HTTPS_PROXY in api-proxy to route through Squid', () => {
Expand All @@ -2372,7 +2372,7 @@ describe('docker-manager', () => {
const result = generateDockerCompose(configWithProxy, mockNetworkConfigWithProxy);
const agent = result.services.agent;
const env = agent.environment as Record<string, string>;
expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000/v1');
expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000');
expect(env.ANTHROPIC_BASE_URL).toBe('http://172.30.0.30:10001');
expect(env.ANTHROPIC_AUTH_TOKEN).toBe('sk-ant-placeholder-key-for-credential-isolation');
expect(env.CLAUDE_CODE_API_KEY_HELPER).toBe('/usr/local/bin/get-claude-key.sh');
Expand All @@ -2395,7 +2395,7 @@ describe('docker-manager', () => {
const agent = result.services.agent;
const env = agent.environment as Record<string, string>;
expect(env.ANTHROPIC_BASE_URL).toBeUndefined();
expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000/v1');
expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000');
});

it('should set AWF_API_PROXY_IP in agent environment', () => {
Expand Down Expand Up @@ -2467,7 +2467,7 @@ describe('docker-manager', () => {
// Agent should NOT have the raw API key — only the sidecar gets it
expect(env.OPENAI_API_KEY).toBeUndefined();
// Agent should have OPENAI_BASE_URL to proxy through sidecar
expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000/v1');
expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000');
} finally {
if (origKey !== undefined) {
process.env.OPENAI_API_KEY = origKey;
Expand All @@ -2490,7 +2490,7 @@ describe('docker-manager', () => {
// CODEX_API_KEY should NOT be passed to agent when api-proxy is enabled
expect(env.CODEX_API_KEY).toBeUndefined();
// OPENAI_BASE_URL should be set when api-proxy is enabled with openaiApiKey
expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000/v1');
expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000');
} finally {
if (origKey !== undefined) {
process.env.CODEX_API_KEY = origKey;
Expand All @@ -2512,7 +2512,7 @@ describe('docker-manager', () => {
// Even with envAll, agent should NOT have OPENAI_API_KEY when api-proxy is enabled
expect(env.OPENAI_API_KEY).toBeUndefined();
// Agent should have OPENAI_BASE_URL to proxy through sidecar
expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000/v1');
expect(env.OPENAI_BASE_URL).toBe('http://172.30.0.30:10000');
} finally {
if (origKey !== undefined) {
process.env.OPENAI_API_KEY = origKey;
Expand Down
4 changes: 2 additions & 2 deletions src/docker-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1802,8 +1802,8 @@ export function generateDockerCompose(
// container names in chroot mode
environment.AWF_API_PROXY_IP = networkConfig.proxyIp;
if (config.openaiApiKey) {
environment.OPENAI_BASE_URL = `http://${networkConfig.proxyIp}:${API_PROXY_PORTS.OPENAI}/v1`;
logger.debug(`OpenAI API will be proxied through sidecar at http://${networkConfig.proxyIp}:${API_PROXY_PORTS.OPENAI}/v1`);
environment.OPENAI_BASE_URL = `http://${networkConfig.proxyIp}:${API_PROXY_PORTS.OPENAI}`;
logger.debug(`OpenAI API will be proxied through sidecar at http://${networkConfig.proxyIp}:${API_PROXY_PORTS.OPENAI}`);
if (config.openaiApiTarget) {
logger.debug(`OpenAI API target overridden to: ${config.openaiApiTarget}`);
}
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ export interface WrapperConfig {
*
* When the corresponding API key is provided, the following environment
* variables are set in the agent container:
* - OPENAI_BASE_URL=http://api-proxy:10000/v1 (set when OPENAI_API_KEY is provided)
* - OPENAI_BASE_URL=http://api-proxy:10000 (set when OPENAI_API_KEY is provided)
* - ANTHROPIC_BASE_URL=http://api-proxy:10001 (set when ANTHROPIC_API_KEY is provided)
* - COPILOT_API_URL=http://api-proxy:10002 (set when COPILOT_GITHUB_TOKEN or COPILOT_API_KEY is provided)
* - CLAUDE_CODE_API_KEY_HELPER=/usr/local/bin/get-claude-key.sh (set when ANTHROPIC_API_KEY is provided)
Expand Down
Loading