How to Configure Authentication Keys for Upstream Providers in Switchyard

Configure upstream authentication in Switchyard by referencing environment variables in your TOML configuration rather than embedding secrets directly.

Switchyard, an open-source LLM routing layer from NVIDIA, handles authentication through environment variable references in deployment configuration files. This design keeps API keys out of version control while supporting flexible authentication patterns—from single static keys to per-call credential forwarding.

Understanding the Two-Layer Authentication Model

The authentication flow in Switchyard operates across two distinct layers: the native server configuration and launcher-specific overrides. Understanding this separation helps you choose the right approach for your deployment.

Layer 1: TOML Deployment Configuration

Each upstream provider is defined under the [llm_clients] table in your routes.toml. The critical field is api_key_env, which specifies the name of the environment variable containing the actual key—not the key itself.

In docs/reference/toml_schema.md (lines 41–48), the schema defines this behavior:

  • api_key_env = environment variable name to read at startup
  • If omitted, requests are sent without any authentication header
  • forward_auth = boolean to forward the caller's credentials instead

Layer 2: Launcher-Specific Overrides

When Switchyard launches clients like Codex or Claude Code, it constructs transient provider configurations that override or supplement the TOML settings.

In switchyard/cli/launchers/codex_cli_launcher.py (lines 78–90), the _provider_overrides dictionary is built with conditional logic:

  • requires_openai_auth flag controls whether a key is injected
  • env_key points to "OPENAI_API_KEY" when credential forwarding is desired
  • _codex_env (lines 97–102) sets OPENAI_API_KEY="switchyard" as a fallback

For Claude Code, switchyard/cli/launchers/claude_code_launcher.py (lines 70–92) demonstrates a different pattern: ANTHROPIC_API_KEY="" suppresses conflict warnings while routing through the proxy.

Configuration Methods for Different Use Cases

Static Server-Owned Key (Most Common)

Use this pattern when the Switchyard server owns a single credential for an upstream provider.

Step 1: Define the environment variable name in your TOML:

[llm_clients.openai]
base_url = "https://api.openai.com/v1"
api_key_env = "OPENAI_API_KEY"
model = "gpt-4o"

Step 2: Export the actual key before starting Switchyard:

export OPENAI_API_KEY="sk-..."
switchyard-server --config routes.toml

The native server reads docs/reference/toml_schema.md, resolves api_key_env to the concrete value, and injects the Authorization: Bearer ... header on every request.

Forward Caller's Credential (Multi-Tenant)

Use this pattern when each user presents their own API key and you want to proxy requests without server-side authentication.

[llm_clients.openai]
base_url = "https://api.openai.com/v1"
forward_auth = true

# api_key_env intentionally omitted

With forward_auth = true, Switchyard forwards the caller's Authorization header—or provider-specific headers like X-API-Key—to the upstream unchanged. This enables multi-tenant deployments where the server never handles raw credentials.

Testing with Launcher-Provided Keys (Local Development)

Launchers automatically inject synthetic keys when appropriate, keeping secrets out of configuration during testing.

Codex CLI pattern (switchyard/cli/launchers/codex_cli_launcher.py):


# When forward_auth is disabled, inject placeholder

_codex_env["OPENAI_API_KEY"] = "switchyard"

Claude Code pattern (switchyard/cli/launchers/claude_code_launcher.py):

_claude_env["ANTHROPIC_API_KEY"] = ""  # Silences conflict warning

These defaults allow local testing against rate-limited internal services that require a key without exposing actual credentials.

Provider-Specific Environment Variables

Switchyard supports any provider following the Bearer token convention. Common variable names as implemented in the_source code:

Provider Typical api_key_env Value Header Format
OpenAI OPENAI_API_KEY Authorization: Bearer sk-...
Anthropic ANTHROPIC_API_KEY x-api-key: sk-ant-...
OpenRouter OPENROUTER_API_KEY Authorization: Bearer sk-or-...
NVIDIA NVIDIA_API_KEY Authorization: Bearer nvapi-...

The exact variable name is user-defined in api_key_env—Switchyard does not enforce provider-specific conventions.

Where Keys Are Consumed in the Codebase

File Path Authentication Role
docs/reference/toml_schema.md Defines TOML schema including api_key_env and forward_auth
switchyard/cli/launchers/native_server.py Starts server that reads TOML and resolves environment variables
switchyard/cli/launchers/codex_cli_launcher.py Constructs _provider_overrides with env_key and "switchyard" fallback
switchyard/cli/launchers/claude_code_launcher.py Builds _claude_env with empty ANTHROPIC_API_KEY workaround

Common Configuration Pitfalls

Mistake: Embedding the key directly


# WRONG - never do this

api_key_env = "sk-live-actual-key"

The api_key_env field expects a variable name, not the key value. Embedding secrets exposes credentials in logs and version control.

Mistake: Setting both api_key_env and forward_auth


# Undefined behavior - choose one pattern

api_key_env = "OPENAI_API_KEY"
forward_auth = true

These options are mutually exclusive. The server uses api_key_env if present; forward_auth only applies when api_key_env is absent.

Summary

  • Never embed secrets in TOML files—use api_key_env to reference environment variables
  • Export variables before launching: export PROVIDER_API_KEY="..."
  • Use forward_auth = true for multi-tenant credential forwarding instead of server-side keys
  • Rely on launcher defaults ("switchyard", empty strings) for local testing without real credentials
  • Verify in source: docs/reference/toml_schema.md defines the schema; launcher files show override behavior

Frequently Asked Questions

What happens if I omit api_key_env entirely?

Requests to that provider are sent without any authentication header. This works for open endpoints or when using forward_auth = true to pass through caller credentials. Per the TOML schema (docs/reference/toml_schema.md, lines 41–48), the field is optional and defaults to no authentication.

Can I use the same environment variable for multiple providers?

Yes. Multiple [llm_clients.<name>] sections can reference the same api_key_env value. However, best practice is using provider-specific variables (e.g., OPENAI_API_KEY, ANTHROPIC_API_KEY) to enable credential rotation per service without affecting others.

How do I rotate credentials without restarting Switchyard?

You must restart the native server. Environment variables are read once at startup in switchyard/cli/launchers/native_server.py. There is no hot-reload mechanism for authentication configuration. For zero-downtime rotation, deploy a new instance with updated variables and migrate traffic.

Why does Claude Code use an empty ANTHROPIC_API_KEY?

As implemented in switchyard/cli/launchers/claude_code_launcher.py (lines 70–92), the empty string suppresses a conflict warning from Claude Code's internal validation. The actual request routing goes through Switchyard's proxy, so the upstream never receives the empty value—authentication is handled by the proxy configuration instead.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →