fix: always route Gemini through api-proxy sidecar when --enable-api-proxy is active#1946
fix: always route Gemini through api-proxy sidecar when --enable-api-proxy is active#1946
Conversation
When --enable-api-proxy is active, set GEMINI_API_BASE_URL and the
GEMINI_API_KEY placeholder unconditionally in the agent environment,
regardless of whether config.geminiApiKey is present in the AWF runner
environment.
Previously, both were only set when config.geminiApiKey was truthy,
causing the Gemini CLI to fail with exit code 41 ("no auth method")
whenever the key was available only as a GitHub Actions secret and not
as a runner-level env var.
The api-proxy sidecar returns 503 when the real key is absent — a
clear, actionable failure vs a confusing missing-auth error.
Also update docs/api-proxy-sidecar.md to:
- Add GEMINI_API_KEY to the api-proxy env table
- Add GEMINI_API_BASE_URL / GEMINI_API_KEY placeholder rows to the
agent env table with a :::note explaining the always-set behaviour
- Add GitHub Actions caution note in the required env vars section
- Add a Gemini CLI exit-code-41 troubleshooting entry
- Fix the Limitations section (was incorrectly "only OpenAI/Anthropic")
- Fix the container ports list to include port 10003 (Gemini)
Agent-Logs-Url: https://github.com/github/gh-aw-firewall/sessions/d29ba1a1-4886-4755-ab93-12a3eb6fa4a3
There was a problem hiding this comment.
Pull request overview
Ensures that when --enable-api-proxy is enabled, the agent is always configured to route Google Gemini traffic through the api-proxy sidecar (including always injecting GEMINI_API_BASE_URL and a placeholder GEMINI_API_KEY) to avoid Gemini CLI auth-preflight failures when the real key isn’t visible to the AWF process.
Changes:
- Update
generateDockerComposeto always setGEMINI_API_BASE_URL+ placeholderGEMINI_API_KEYwhenever the api-proxy is enabled, and warn when the real key is missing. - Adjust/add unit tests to assert the always-set Gemini env behavior under api-proxy mode.
- Expand api-proxy sidecar documentation for Gemini support, env vars, ports, and troubleshooting.
Show a summary per file
| File | Description |
|---|---|
src/docker-manager.ts |
Always injects Gemini proxy base URL + placeholder key when api-proxy is enabled; keeps warning when real key is missing. |
src/docker-manager.test.ts |
Updates/extends tests to validate Gemini env vars are present even without geminiApiKey. |
docs/api-proxy-sidecar.md |
Documents Gemini env vars/port and adds guidance/troubleshooting for key exposure and failures. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (1)
docs/api-proxy-sidecar.md:351
- The "API keys not detected" snippet and suggested remediation mention only OPENAI_API_KEY/ANTHROPIC_API_KEY, but the CLI warning message includes Copilot tokens and GEMINI_API_KEY as well. Consider updating this block to mirror the actual warning text and list of supported env vars.
### API keys not detected
Set OPENAI_API_KEY or ANTHROPIC_API_KEY to use the proxy
- Files reviewed: 3/3 changed files
- Comments generated: 4
| **Required environment variables** (at least one): | ||
| - `OPENAI_API_KEY` — OpenAI API key | ||
| - `ANTHROPIC_API_KEY` — Anthropic API key | ||
| - `GEMINI_API_KEY` — Google Gemini API key |
There was a problem hiding this comment.
The "Required environment variables" list appears incomplete: the CLI warning path treats COPILOT_GITHUB_TOKEN / COPILOT_API_KEY as valid ways to enable the api-proxy as well, but they are not listed here. Consider updating this list so it matches the actual supported credentials for --enable-api-proxy.
This issue also appears on line 346 of the same file.
| - `GEMINI_API_KEY` — Google Gemini API key | |
| - `GEMINI_API_KEY` — Google Gemini API key | |
| - `COPILOT_GITHUB_TOKEN` — GitHub Copilot access token | |
| - `COPILOT_API_KEY` — GitHub Copilot API key |
| :::caution[GitHub Actions: expose keys as runner env vars] | ||
| When running AWF in a GitHub Actions workflow, API keys must be available as **runner-level environment variables** — not just as GitHub Actions secrets. AWF reads the key from the environment at startup to pass it to the api-proxy sidecar container. Use `env:` in the workflow step: | ||
|
|
||
| ```yaml | ||
| - name: Run agent | ||
| env: | ||
| GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} | ||
| run: sudo awf --enable-api-proxy ... | ||
| ``` |
There was a problem hiding this comment.
In GitHub Actions, setting GEMINI_API_KEY under a step's env: does not automatically make it visible to the awf process if awf is executed via sudo (sudo typically drops non-whitelisted env vars). Consider updating this caution/example to show using sudo -E/--preserve-env=GEMINI_API_KEY (or otherwise ensure GEMINI_API_KEY is available to the privileged awf process), so users don't still hit the "key not set" warning unexpectedly.
docs/api-proxy-sidecar.md
Outdated
| ### Gemini CLI exits with "no auth method" (exit code 41) | ||
|
|
||
| ``` | ||
| Please set an Auth method in your settings.json or specify one of the following | ||
| environment variables before running: GEMINI_API_KEY, GOOGLE_GENAI_USE_VERTEXAI, GOOGLE_GENAI_USE_GCA | ||
| ``` | ||
|
|
||
| This error occurs when `GEMINI_API_KEY` is not set in the runner environment — the proxy placeholder is present but the sidecar has no real key to authenticate with. | ||
|
|
||
| **Solution**: Export `GEMINI_API_KEY` in the runner environment before invoking AWF. In GitHub Actions, this means adding it to the step's `env:` block, not only storing it as a secret: |
There was a problem hiding this comment.
This troubleshooting section describes exit code 41 occurring when GEMINI_API_KEY is missing in the runner env, but with the new behavior GEMINI_API_KEY placeholder is always set in the agent when --enable-api-proxy is active. That should prevent the Gemini CLI from failing its "no auth method" preflight; instead, Gemini requests should fail with the sidecar's 503 response when the real key is absent. Consider rewriting this section to reflect the post-change failure mode (503 from proxy) and/or clarify the specific conditions where exit code 41 can still occur.
| logger.warn('--enable-api-proxy is active but GEMINI_API_KEY is not set.'); | ||
| logger.warn(` The api-proxy Gemini listener (port ${API_PROXY_PORTS.GEMINI}) will start in fallback mode and return 503 responses until GEMINI_API_KEY is set.`); | ||
| logger.warn(' Set GEMINI_API_KEY in the AWF runner environment to enable Gemini credential isolation.'); |
There was a problem hiding this comment.
Now that GEMINI_API_BASE_URL / GEMINI_API_KEY placeholder are always set when --enable-api-proxy is active, the agent's pre-flight health check should also validate Gemini proxy configuration/connectivity (similar to OpenAI/Anthropic/Copilot). Currently the health check script only keys off OPENAI_BASE_URL, ANTHROPIC_BASE_URL, and COPILOT_API_URL, so a Gemini-only setup can skip checks entirely and proceed to runtime failures. Consider extending the pre-flight health check to include GEMINI_API_BASE_URL and placeholder validation.
| logger.warn('--enable-api-proxy is active but GEMINI_API_KEY is not set.'); | |
| logger.warn(` The api-proxy Gemini listener (port ${API_PROXY_PORTS.GEMINI}) will start in fallback mode and return 503 responses until GEMINI_API_KEY is set.`); | |
| logger.warn(' Set GEMINI_API_KEY in the AWF runner environment to enable Gemini credential isolation.'); | |
| throw new Error( | |
| `--enable-api-proxy is active but GEMINI_API_KEY is not set. ` + | |
| `Refusing to continue because Gemini proxy traffic would be configured with a placeholder key only, ` + | |
| `and the api-proxy Gemini listener on port ${API_PROXY_PORTS.GEMINI} would otherwise fail later with 503 responses.` | |
| ); |
- Add COPILOT_GITHUB_TOKEN/COPILOT_API_KEY to required env vars list - Add sudo --preserve-env note for GitHub Actions usage - Update troubleshooting: exit 41 replaced by 503 (placeholder key now satisfies CLI pre-flight) - Update 'API keys not detected' message to list all providers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
✅ Coverage Check PassedOverall Coverage
📁 Per-file Coverage Changes (1 files)
Coverage comparison generated by |
🤖 Smoke Test Results
Overall: PASS PR by
|
|
Smoke Test Results — Run 24314916431 ✅ GitHub MCP: #1940 "perf(security-guard): reduce Claude token cost ~32%", #1937 "fix: increase claude-token-optimizer timeout from 10 to 15 minutes" Overall: PASS
|
|
Smoke Test Results (Codex)
|
Smoke Test: GitHub Actions Services Connectivity ✅All connectivity checks passed:
Note:
|
Chroot Version Comparison Results
Overall: ❌ Not all versions match — Python minor patch differs (3.12.13 vs 3.12.3) and Node.js major version differs (v24 vs v20).
|
🏗️ Build Test Suite Results
Overall: 8/8 ecosystems passed — ✅ PASS Notes
|
When
--enable-api-proxyis enabled,GEMINI_API_BASE_URLand theGEMINI_API_KEYplaceholder were only injected into the agent whenGEMINI_API_KEYwas already readable by the AWF process. If the key existed only as a GitHub Actions secret (not a runner-level env var), the Gemini CLI received neither — causing exit code 41 ("no auth method").Changes
src/docker-manager.tsif (config.geminiApiKey)guard aroundGEMINI_API_BASE_URLand placeholderGEMINI_API_KEYassignment--enable-api-proxyis active; sidecar returns503if the real key is absent — explicit failure vs. silent auth errorsrc/docker-manager.test.tsGEMINI_API_BASE_URLwasundefinedwithout ageminiApiKeygeminiApiKeydocs/api-proxy-sidecar.mdGEMINI_API_KEYto the api-proxy env tableGEMINI_API_BASE_URL/ placeholder rows to agent env table with explanatory note on always-set behavior:::cautionblock:GEMINI_API_KEYmust be exposed viaenv:in the workflow step, not only stored as a secretBefore / after (agent environment when
--enable-api-proxyis active, nogeminiApiKeyin runner env):