EXPERIMENTAL
A configurable reverse proxy that provides access to AI APIs without exposing credentials to clients.
NOTE: This gateway should NEVER be used with require_auth set to false in uncontrolled or even public networks.
The gateway sits between your application and AI provider APIs. Clients send requests to the gateway using plain paths (e.g. /openai/chat/completions), and the gateway injects the real API credentials before forwarding to the upstream endpoint.
Credentials are currently read from environment variables in the form <KEY>_CREDENTIAL (uppercased), where <KEY> matches the key field in the config.
Create a config.yaml (or pass a custom path via -config):
listen_addr: "127.0.0.1:4180"
require_auth: true
proxies:
- key: openai
path: openai
credential_header: "Authorization: Bearer {credential}"
endpoint: "https://api.openai.com/v1"
- key: anthropic
path: anthropic
credential_header: "x-api-key: {credential}"
endpoint: "https://api.anthropic.com/v1"
- key: githubcopilot
path: githubcopilot
credential_header: "Authorization: Bearer {credential}"
endpoint: "https://api.githubcopilot.com"| Field | Description |
|---|---|
listen_addr |
Address and port the gateway listens on |
grpc_addr |
Address for gRPC live stream server (disabled if not set) |
require_auth |
Require client authentication (default: true if not set) |
key |
Unique identifier; also determines the env var name (<KEY>_CREDENTIAL) |
path |
URL path prefix the gateway listens on |
credential_header |
Header template — {credential} is replaced with the actual secret |
endpoint |
Upstream API base URL |
If require_auth is true (default) the gateway will refuse to start unless the GATEWAY_SECRET environment variable is set. When authentication is enabled, the gateway extracts the credential from each incoming request using the same header format defined by credential_header for that proxy entry. For example, OpenAI-bound requests must send Authorization: Bearer <gateway-token> and Anthropic-bound requests must send x-api-key: <gateway-token>. The client's auth header is stripped before forwarding; the real upstream credential is injected by the gateway.
If require_auth is set to false, authentication is optional — but if GATEWAY_SECRET is still provided, client authentication will be enforced.
go build -o acg ./cmd/gateway/
# Set credentials via environment variables
export OPENAI_CREDENTIAL="sk-..."
export ANTHROPIC_CREDENTIAL="sk-ant-..."
# Optionally require clients to authenticate to the gateway (e.g. generating a secret with `openssl rand -hex 40`)
export GATEWAY_SECRET=<secret>
./acg -config config.yamlClients can then replace configured endpoints like https://api.openai.com/v1 and https://api.anthropic.com/v1 to http://127.0.0.1:4180/openai and http://127.0.0.1:4180/anthropic respectively. The real tokens then can be removed from this clients. (if a GATEWAY_SECRET is set, that one has to be provided instead.)
curl http://127.0.0.1:4180/openai/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4","messages":[{"role":"user","content":"Hello"}]}'curl http://127.0.0.1:4180/anthropic/messages \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{"model":"claude-sonnet-4-6","max_tokens":1024,"messages":[{"role":"user","content":"Hello"}]}'When GATEWAY_SECRET is set, clients must include the gateway token using the same header format as the target API:
# OpenAI — uses Authorization header
curl http://127.0.0.1:4180/openai/chat/completions \
-H "Authorization: Bearer my-secret-gateway-token" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4","messages":[{"role":"user","content":"Hello"}]}'# Anthropic — uses x-api-key header
curl http://127.0.0.1:4180/anthropic/messages \
-H "x-api-key: my-secret-gateway-token" \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{"model":"claude-sonnet-4-6","max_tokens":1024,"messages":[{"role":"user","content":"Hello"}]}'docker build -t ai-credential-gateway .
Use the Docker image in a way the AI agent that should be isolated has no access to the ENV variables passed to the ai-credential-gateway. (e.g. using Docker Compose)
The gateway can expose a gRPC server that streams live request/response information to connected clients. This is useful for debugging and monitoring.
To enable it, add grpc_addr to your config.yaml:
grpc_addr: "127.0.0.1:4181"If grpc_addr is not set, the gRPC server is not started.
A built-in TUI client displays live requests with colored output:
# Stream all requests
go run ./cmd/streamclient --addr 127.0.0.1:4181
# Filter by proxy key
go run ./cmd/streamclient --addr 127.0.0.1:4181 --proxy-key openai
# Filter by path prefix
go run ./cmd/streamclient --addr 127.0.0.1:4181 --path-prefix /v1/chatSee GRPC.md for full documentation including the proto service definition and development commands.