Add LLM Provider
Use this skill whenever a new agent engine or LLM provider needs to work behind AWF and it is unclear how to "set it up." AWF supports two fundamentally different integration paths — picking the wrong one is the most common source of confusion (e.g. "why is token-usage.jsonl empty for this engine?").
Step 1 — Determine how the engine talks to its LLM backend
Ask: does the engine call the provider's API directly (its own base URL, its own auth), or can it be configured to route through AWF's API-proxy sidecar? The sidecar is always enabled; --enable-api-proxy is deprecated and ignored. Its provider ports are http://172.30.0.30:10000 (OpenAI), :10001 (Anthropic), :10002 (Copilot), :10003 (Gemini), and :10004 (Vertex AI).
- If the engine has built-in support for pointing at AWF's api-proxy ports (env vars like
OPENAI_BASE_URL,ANTHROPIC_BASE_URLrewritten to the sidecar) → Path A: Proxied provider. - If the engine always calls its own hardcoded/native endpoint regardless of proxy env vars (e.g. Cursor CLI calling
api2.cursor.sh/api3.cursor.shdirectly), or manages its own credentials outside AWF → Path B: Direct-API engine.
When unsure, run the engine once with --keep-containers and inspect docker exec awf-squid cat /var/log/squid/access.log (see docs/squid_log_filtering.md) to see which hosts it actually contacts and whether traffic reaches the api-proxy sidecar or goes straight out through Squid.
Path A — Proxied provider (credentials injected by api-proxy)
Choose this when you want AWF to hold the API key/OIDC token and inject it, keeping secrets out of the agent container.
Use containers/api-proxy/providers/ADDING-A-PROVIDER.md for the adapter interface, then:
- Create
containers/api-proxy/providers/<name>.jsimplementing theProviderAdapterinterface. - Register it in
containers/api-proxy/providers/index.js. - Add its port to
src/config/sandbox-network-policy.json, then extend the closedNetworkPolicyshape and validation insrc/config/network-policy.tsand the compatibility mapping insrc/types/ports.ts. Add it to the DockerfileEXPOSElist; the wholeproviders/directory is already copied.src/host-iptables-rules.tsconsumesObject.values(API_PROXY_PORTS), so it normally needs no change. - Add each credential to the API-proxy environment pipeline in
src/services/api-proxy-env-config.tsand explicitly exclude it from agent passthrough insrc/services/agent-environment/excluded-vars.ts; never forward a provider credential generically or fromsrc/docker-manager.ts. - Add the upstream domain(s) to the allowlist wherever the caller configures
--allow-domains(AWF itself does not hardcode per-provider domains). - Document auth details in docs/auth-matrix.md if it's a net-new auth pattern.
- Write adapter unit tests (
providers/<name>.test.js) and runcd containers/api-proxy && npm test -- providers/<name>.test.js.
Path B — Direct-API engine (no proxy adapter needed)
Choose this when the engine calls its own API directly and either manages its own credentials, or credential injection isn't feasible/needed through AWF.
- No API-proxy adapter is required. The API proxy remains enabled, but do not try to force an engine through it when it cannot use the sidecar.
- Just allowlist the domain(s) the engine needs, either via the CLI flag or config file:
or in the AWF config file underawf --allow-domains api2.cursor.sh,api3.cursor.sh -- cursor-agent ...network.allowDomains(see docs/awf-config-spec.md and docs/awf-config.schema.json). - If the engine requires its API key in the agent environment, it cannot receive API-proxy credential isolation. Pass only a minimally scoped credential by an intentional mechanism appropriate to the caller, and do not use
sensitiveAllowedDomainsfor the key: that setting only redacts secret-derived endpoint hostnames in logs and audit artifacts. - Telemetry caveat: because traffic never passes through the API-proxy sidecar, AWF's
token-usage.jsonl/ token-tracking metrics will stay empty for this engine. Any downstream check that assumes all engines produce proxy telemetry (e.g. a "token usage present" CI gate) must exclude direct-API engines instead of trying to make them populate it. - Confirm the domains are correct by testing with
--keep-containersand checking Squid's access log forTCP_DENIEDentries, then iterating on the allowlist (see docs/quickstart.md "Test Domain Blocking" section).
Checklist
- Identified whether the engine is proxied (Path A) or direct-API (Path B)
- Path A: adapter created and registered; network policy, credential isolation, image port, and tests updated
- Path B: domain(s) allowlisted, telemetry-dependent checks updated to exclude this engine
- Verified with
--keep-containers+ Squid access log that the engine's real traffic is allowed and nothing extraneous is