A local reverse proxy for AI agents that transparently injects the agent key into every outgoing request. It sits between the agent and a Wardgate server, reading an agent key from config and adding it as an Authorization: Bearer header.
wardgate-cli replaces curl entirely and locks the agent to a single server. But some agents use their own HTTP clients (Python requests, Node fetch, etc.) and can't be forced to use a custom binary.
wardgate-proxy solves this differently: it runs as a local HTTP proxy on 127.0.0.1. The agent makes plain HTTP requests to the proxy, and the proxy forwards them to Wardgate with the agent key injected. The agent never sees the key.
| Approach | How it works | Best for |
|---|---|---|
wardgate-cli |
Replaces curl; fixed config path compiled in | Sandboxed containers where you control the toolset |
wardgate-proxy |
Local proxy; any HTTP client works | Agents with their own HTTP clients, or multi-tool setups |
Agent (any HTTP client)
→ http://127.0.0.1:18080/todoist/tasks
→ wardgate-proxy reads agent key from config
→ https://wardgate.example.com/todoist/tasks (with Bearer <agent-key>)
- Agent sends a request to
wardgate-proxy(no auth required) - Proxy reads the agent key from config (cached by mtime, auto-rotated)
- Proxy forwards the request to the Wardgate server with
Authorization: Bearer <agent-key> - Response is streamed back to the agent (SSE and chunked transfer supported)
Download from GitHub Releases.
go install github.com/wardgate/wardgate/cmd/wardgate-proxy@latestgo build -o wardgate-proxy ./cmd/wardgate-proxyCreate wardgate-proxy.yaml (default path, or specify with -config):
server: https://wardgate.example.com
key: "your-agent-key"
listen: 127.0.0.1:18080Or use an environment variable for the key:
server: https://wardgate.example.com
key_env: WARDGATE_AGENT_KEY
listen: 127.0.0.1:18080Custom CA: If Wardgate uses HTTPS with an internal CA, add ca_file:
server: https://wardgate.internal:443
key_env: WARDGATE_AGENT_KEY
ca_file: /etc/wardgate-proxy/ca.pem| Field | Description | Default |
|---|---|---|
server |
Wardgate server URL (required) | -- |
key |
Agent key (takes priority over key_env) |
-- |
key_env |
Environment variable containing the agent key | -- |
listen |
Local address to listen on | 127.0.0.1:18080 |
ca_file |
Path to custom CA certificate (PEM) | -- |
seal_headers |
Headers to auto-rename with X-Wardgate-Sealed- prefix |
-- |
One of key or key_env is required.
Flags override config file values:
wardgate-proxy \
-config wardgate-proxy.yaml \
-server https://wardgate.example.com \
-key-env WARDGATE_AGENT_KEY \
-listen 127.0.0.1:9090| Flag | Description |
|---|---|
-config |
Path to config file (default: wardgate-proxy.yaml) |
-server |
Wardgate server URL |
-key-env |
Environment variable containing agent key |
-listen |
Listen address |
-version |
Show version and exit |
When agents send pre-sealed (encrypted) credential values as regular HTTP headers, seal_headers makes the proxy automatically rename them with the X-Wardgate-Sealed- prefix. This keeps agents unaware of Wardgate conventions -- they send normal headers, and the proxy converts them transparently.
server: https://wardgate.example.com
key_env: WARDGATE_AGENT_KEY
seal_headers:
- Authorization
- X-Api-KeyWith this config, the proxy transforms requests like this:
Agent sends: Authorization: <pre-sealed-value>
X-Api-Key: <pre-sealed-value>
Proxy forwards: Authorization: Bearer <agent-key>
X-Wardgate-Sealed-Authorization: <pre-sealed-value>
X-Wardgate-Sealed-X-Api-Key: <pre-sealed-value>
The Wardgate server then decrypts the sealed headers and injects the real credentials for the upstream call.
Headers not listed in seal_headers are forwarded unchanged. If seal_headers is omitted, no conversion happens and behavior is identical to previous versions.
Priority: key > key_env. This matches wardgate-cli conventions.
- If
keyis set in the config file, it is used directly. The proxy watches the config file's mtime and re-reads thekeyfield when it changes, supporting key rotation without restart. - If
key_envis set, the named environment variable is read at startup. The key is fixed for the process lifetime (restart to rotate). - If neither is set, the proxy refuses to start.
# With config file
wardgate-proxy
# With flags
wardgate-proxy -server https://wardgate.example.com -key-env WARDGATE_AGENT_KEYThe agent makes requests to the proxy as if it were the Wardgate server:
# From the agent's perspective -- no auth needed
curl http://127.0.0.1:18080/todoist/tasks
curl -X POST -H "Content-Type: application/json" \
-d '{"content":"Buy milk"}' \
http://127.0.0.1:18080/todoist/tasksThe proxy injects the agent key and forwards to the real Wardgate server. Any Authorization header the agent sends is overwritten.
When using key in the config file, write the new key to the config and the proxy picks it up on the next request (detected by mtime change). No restart required.
If the config file is partially written (YAML parse error or empty key), the proxy falls back to the last known good key and logs a warning.
When using key_env, restart the proxy to rotate the key.
| Aspect | Behavior |
|---|---|
| Agent key storage | In config file or environment variable, never exposed to agent |
| Key injection | Authorization: Bearer header set on every request |
| Agent auth | Overwritten -- agent cannot send its own key upstream |
X-Forwarded-For |
Stripped to prevent IP leakage |
| Listen address | 127.0.0.1 by default (localhost only) |
Compared to wardgate-cli: The proxy does not restrict which paths the agent requests -- it forwards everything to the configured Wardgate server. Access control is enforced by Wardgate's policy engine, not the proxy.
services:
wardgate-proxy:
build:
context: .
dockerfile: Dockerfile
target: wardgate-proxy # if using multi-stage
volumes:
- ./wardgate-proxy.yaml:/etc/wardgate-proxy/config.yaml:ro
command: ["-config", "/etc/wardgate-proxy/config.yaml"]
network_mode: "service:agent" # share network namespace with agentBy sharing the network namespace, the agent reaches the proxy at 127.0.0.1:18080 without exposing it to other containers.