github / github/gh-aw

Feature request: support GitHub Actions Services as user-provided proxies for engine (Claude Code) egress (LLM header injection + OTLP fan-out/mutation)

Open
#38,925 1 comment 0 reactions 0 assignees View on GitHub
awf community
Dominant language
Go
Stars
5.1k
Forks
541
Avg merge
5h 46m
Merged PRs (30d)
760

Description

🤖 _This issue has been generated by Claude Code._

## Feature request

Support using **GitHub Actions Services** (job-level `services:` containers) as **user-provided proxies for the agent engine's outbound requests** (e.g. Claude Code), with gh-aw wiring the engine's egress through the declared service and allow-listing it through the sandbox/firewall.

Two concrete use cases motivate this:

1. **LLM request proxy** — interpose a user-controlled proxy in front of the model endpoint to **inject request headers carrying secret values** (a hard requirement in some corporate environments, e.g. a gateway that demands a secret header on every model call).
2. **OTLP/telemetry proxy** — route the engine's OTLP traces through a user-controlled proxy to **fan out to multiple backends and/or mutate spans** originating from the engine (see related #38915 / #38901 for the fan-out gap).

A GitHub Actions Service is a clean, standard place to run such a proxy: it's a container GitHub already manages for the job lifecycle and exposes on the job network. gh-aw would need to (a) let a workflow declare it, (b) point the engine's relevant base URL/endpoint at it (`ANTHROPIC_BASE_URL` / `OTEL_EXPORTER_OTLP_(TRACES_)ENDPOINT`), and (c) permit it through the egress allowlist.

## Why the built-in proxy isn't enough (LLM case)

I tried to implement the LLM header-injection proxy described in use case (1), but could not, because gh-aw's **own built-in LLM proxy** owns the engine→model path and offers no extension point for this.

From a run's sandbox configuration, the engine is routed through gh-aw's `api-proxy` (`ghcr.io/github/gh-aw-firewall/api-proxy`):

- The engine's `ANTHROPIC_BASE_URL` points at the gh-aw api-proxy (e.g. `…:10001`), and the engine's `ANTHROPIC_API_KEY` is deliberately **excluded** from its environment — so the engine cannot reach the model except through this proxy.
- The api-proxy container is the one that holds `ANTHROPIC_API_KEY` and performs auth injection, **token steering** (`enableTokenSteering: true`), **credit/run caps** (`maxAiCredits`, `maxRuns`), a **model allowlist**, and **target-host rewriting** (`apiProxy.targets.anthropic.host`).

So the built-in proxy fully owns and rewrites the outbound model request, but provides **no supported hook to inject custom (secret-bearing) request headers**, and **no supported way to interpose a user proxy** in front of or behind it. That makes the corporate "inject a secret header on every model call" requirement unachievable today. Rather than expand the built-in proxy's config surface to cover every such need, exposing a GitHub Actions Service as a pluggable proxy in the egress path would be a general, composable solution.

## Requested behavior

- Allow a workflow to declare a **Service container** (or otherwise register a user-provided proxy) intended to sit in the engine's egress path.
- Provide a supported way to route the engine's **LLM** traffic and/or **OTLP** traffic through that service — i.e. set the engine's base URL / OTLP endpoint to the service, while keeping the existing firewall and (optionally) the built-in api-proxy in the chain.
- Ensure the service is reachable from inside the sandbox and **allow-listed** by the firewall, without the user having to weaken the global egress allowlist.

## Why it's valuable

- **Corporate compliance**: satisfies environments that require secret headers / custom auth on model calls, which the fixed built-in proxy cannot express.
- **Telemetry flexibility**: enables engine-trace fan-out and span mutation/redaction via a user proxy (complements #38915 / #38901).
- **Composable & engine-agnostic**: a generic egress extension point avoids growing the built-in proxy's config for every bespoke requirement, and works for any engine that honors a configurable base URL / OTLP endpoint.

## Related

- #38915 — fan out engine OTLP traces to all backends (a user OTLP proxy is one way to achieve this).
- #38901 — MCP gateway spans only reach the primary OTLP endpoint.

---

*Note: observed in a private repository. Repo/workflow names, hostnames, endpoint URLs, and secret values are redacted; proxy/component names and behavior are quoted from the run's sandbox configuration with hosts removed.*

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.