Skip to main content

Provider & Model Configuration

Archived design document. Preserved for historical context; not part of the current normative reference/ contract.

Specification v1.0 | @a5c-ai/agent-mux


1. Overview

This spec defines how amux resolves which LLM provider and model a harness should use, covering both the CLI surface (amux launch, amux run) and the programmatic SDK. It introduces a provider configuration system that abstracts away per-harness differences in how providers and models are specified.

The core problem: each harness has its own way of configuring providers — Claude uses env vars (ANTHROPIC_API_KEY, CLAUDE_CODE_USE_BEDROCK), Codex uses config.toml profiles, Gemini uses settings.json and env vars, OpenCode uses opencode.json with Vercel AI SDK provider packages. amux unifies this into a single configuration surface that is then translated into harness-specific configuration at launch time.

1.1 Cross-References

ConceptSpec
amux launch commanddocs/launcher.md
amux-proxy packagedocs/provider-mux.md
Config & auth08-config-and-auth.md
Capabilities & models06-capabilities-and-models.md
CLI reference10-cli-reference.md

2. Provider Configuration Schema

2.1 Core Type

interface ProviderConfig {
/** Provider identifier from the taxonomy */
provider: ProviderId;

/** Model identifier (provider-specific format) */
model: string;

/** Wire protocol the provider's API speaks */
transport: TransportId;

/** Authentication configuration */
auth: ProviderAuth;

/** Provider-specific parameters */
params: Record<string, string>;
}

type ProviderId =
| 'anthropic' // Anthropic direct API
| 'openai' // OpenAI direct API
| 'google' // Google AI Studio
| 'bedrock' // AWS Bedrock
| 'vertex' // Google Vertex AI
| 'azure' // Azure OpenAI
| 'foundry' // Azure AI Foundry
| 'ollama' // Local Ollama instance
| 'local' // Generic local model server
| 'openrouter' // OpenRouter
| 'groq' // Groq
| 'fireworks' // Fireworks AI
| 'together' // Together AI
| 'deepseek' // DeepSeek
| 'mistral' // Mistral AI
| 'cerebras' // Cerebras
| 'sambanova' // SambaNova
| 'custom'; // User-defined endpoint

type TransportId =
| 'anthropic' // Anthropic Messages API
| 'openai-chat' // OpenAI Chat Completions
| 'openai-responses' // OpenAI Responses API
| 'google'; // Google GenerateContent

interface ProviderAuth {
/** Auth mechanism */
type: 'api_key' | 'oauth' | 'iam' | 'adc' | 'service_account' | 'spn' | 'bearer' | 'none' | 'command';

/** API key value (or env var name prefixed with $) */
apiKey?: string;

/** OAuth/bearer token */
token?: string;

/** External command that outputs a token */
command?: string;

/** AWS-specific */
awsProfile?: string;
awsRoleArn?: string;
awsSessionToken?: string;

/** GCP-specific */
gcpCredentialsFile?: string;

/** Azure-specific */
azureTenantId?: string;
azureClientId?: string;
azureClientSecret?: string;
}

2.2 Provider Defaults

Each ProviderId has default values that reduce configuration burden:

ProviderDefault TransportDefault Auth TypeDefault API BaseDefault Model Format
anthropicanthropicapi_keyhttps://api.anthropic.comclaude-sonnet-4-20250514
openaiopenai-responsesapi_keyhttps://api.openai.comgpt-4o
googlegoogleapi_keyhttps://generativelanguage.googleapis.comgemini-2.5-pro
bedrockanthropiciamhttps://bedrock-runtime.{region}.amazonaws.comanthropic.claude-sonnet-4-20250514-v1:0
vertexgoogleadchttps://{region}-aiplatform.googleapis.comclaude-sonnet-4@20250514
azureopenai-chatapi_keyhttps://{resource}.openai.azure.com{deployment-name}
foundryopenai-chatapi_keyhttps://{resource}.services.ai.azure.com{deployment-name}
ollamaopenai-chatnonehttp://localhost:11434qwen3:latest
localopenai-chatnonehttp://localhost:8080(required)
openrouteropenai-chatapi_keyhttps://openrouter.ai/apianthropic/claude-sonnet-4
groqopenai-chatapi_keyhttps://api.groq.com/openaillama-4-scout-17b-16e-instruct
fireworksopenai-chatapi_keyhttps://api.fireworks.ai/inferenceaccounts/fireworks/models/llama-v3p3-70b-instruct
togetheropenai-chatapi_keyhttps://api.together.xyzmeta-llama/Meta-Llama-3.3-70B-Instruct-Turbo
deepseekopenai-chatapi_keyhttps://api.deepseek.comdeepseek-chat
mistralopenai-chatapi_keyhttps://api.mistral.aimistral-large-latest
cerebrasopenai-chatapi_keyhttps://api.cerebras.aillama-4-scout-17b-16e-instruct
sambanovaopenai-chatapi_keyhttps://api.sambanova.aiMeta-Llama-3.3-70B-Instruct
custom(required)(required)(required)(required)

3. Configuration Sources (Precedence Order)

Provider configuration is resolved from multiple sources, with later sources overriding earlier ones:

1. Provider defaults (§2.2) ← lowest priority
2. Global config: ~/.amux/providers.json
3. Project config: .amux/providers.json
4. Named profile: --profile <name>
5. Environment variables
6. CLI flags ← highest priority

3.1 Configuration File Format

~/.amux/providers.json and .amux/providers.json:

{
"$schema": "https://a5c.ai/schemas/amux-providers.json",
"version": 1,

"defaults": {
"provider": "anthropic",
"model": "claude-sonnet-4-20250514"
},

"profiles": {
"work-bedrock": {
"provider": "bedrock",
"model": "anthropic.claude-sonnet-4-20250514-v1:0",
"auth": {
"type": "iam",
"awsProfile": "work-sso"
},
"params": {
"region": "us-east-1"
}
},
"home-vertex": {
"provider": "vertex",
"model": "claude-sonnet-4@20250514",
"auth": {
"type": "adc"
},
"params": {
"project": "my-home-project",
"region": "us-central1"
}
},
"local-ollama": {
"provider": "ollama",
"model": "qwen3:32b",
"auth": { "type": "none" },
"params": {
"apiBase": "http://localhost:11434"
}
},
"corp-proxy": {
"provider": "custom",
"transport": "openai-chat",
"model": "internal-claude-proxy",
"auth": {
"type": "command",
"command": "corp-auth-helper get-token --scope llm"
},
"params": {
"apiBase": "https://llm-proxy.corp.internal/v1"
}
}
}
}

3.2 Environment Variables

Environment variables follow the pattern AMUX_PROVIDER_*:

VariableMaps ToExample
AMUX_PROVIDERproviderbedrock
AMUX_MODELmodelanthropic.claude-sonnet-4-20250514-v1:0
AMUX_TRANSPORTtransportanthropic
AMUX_API_KEYauth.apiKeysk-ant-...
AMUX_API_BASEparams.apiBasehttps://custom.endpoint.com
AMUX_REGIONparams.regionus-east-1
AMUX_PROJECTparams.projectmy-project
AMUX_PROFILEProfile namework-bedrock
AMUX_AUTH_COMMANDauth.commandmy-token-script

Additionally, provider-native env vars are respected as fallbacks:

Native VariableUsed When Provider Is
ANTHROPIC_API_KEYanthropic
OPENAI_API_KEYopenai
GOOGLE_API_KEY, GEMINI_API_KEYgoogle
AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEYbedrock
AWS_PROFILEbedrock (profile-based auth)
GOOGLE_APPLICATION_CREDENTIALSvertex
AZURE_API_KEYazure, foundry
OPENROUTER_API_KEYopenrouter
GROQ_API_KEYgroq
FIREWORKS_API_KEYfireworks
TOGETHER_API_KEYtogether
DEEPSEEK_API_KEYdeepseek
MISTRAL_API_KEYmistral

3.3 CLI Flag Mapping

CLI FlagConfig Field
--model / -mmodel
--api-keyauth.apiKey
--api-baseparams.apiBase
--regionparams.region
--projectparams.project
--resource-groupparams.resourceGroup
--endpoint-nameparams.endpointName
--transport / -ttransport
--profileLoads named profile
--auth-commandauth.command

4. Provider → Harness Translation

Once a ProviderConfig is resolved, it must be translated into the harness-specific configuration format. This section defines the translation rules.

4.1 Translation Interface

interface HarnessProviderTranslation {
/** Environment variables to set */
env: Record<string, string>;

/** CLI arguments to prepend */
args: string[];

/** Config file content to write (for harnesses that need it) */
configContent?: string;

/** Config file path (if configContent is set) */
configPath?: string;

/** Whether a proxy is required */
proxyRequired: boolean;

/** If proxy is required, what transport should it expose */
proxyExposedTransport?: TransportId;
}

4.2 Claude Code Translation Rules

ProviderTranslation
anthropicenv.ANTHROPIC_API_KEY = auth.apiKey
bedrockenv.CLAUDE_CODE_USE_BEDROCK = "1", env.AWS_REGION = params.region, AWS auth env vars
vertexenv.CLAUDE_CODE_USE_VERTEX = "1", env.GOOGLE_CLOUD_PROJECT = params.project, env.GOOGLE_CLOUD_LOCATION = params.region
foundryenv.CLAUDE_CODE_USE_FOUNDRY = "1", Foundry auth env vars
ollamaenv.ANTHROPIC_BASE_URL = params.apiBase, env.ANTHROPIC_API_KEY = "", env.ANTHROPIC_AUTH_TOKEN = "ollama", model override env vars
OthersproxyRequired = true, proxyExposedTransport = "anthropic"

Model mapping for Claude: when model ID doesn't match a known Claude model, set ANTHROPIC_DEFAULT_SONNET_MODEL, ANTHROPIC_DEFAULT_OPUS_MODEL, ANTHROPIC_DEFAULT_HAIKU_MODEL to the resolved model ID.

4.3 Codex Translation Rules

ProviderTranslation
openaienv.OPENAI_API_KEY = auth.apiKey
ollamaargs = ["--oss"] (native Ollama support)
Custom OpenAI-compatenv.OPENAI_BASE_URL = params.apiBase, env.OPENAI_API_KEY = auth.apiKey
OthersproxyRequired = true, proxyExposedTransport = "openai-responses"

For providers with config.toml support, generate a profile entry:

configContent = `
[model_providers.amux]
name = "amux-proxy"
base_url = "${proxyBaseUrl}/v1/"
wire_api = "responses"
env_key = "AMUX_PROXY_KEY"
`;
configPath = path.join(os.homedir(), '.codex', 'config.toml');
args = ['--profile', 'amux'];

4.4 Gemini CLI Translation Rules

ProviderTranslation
googleenv.GEMINI_API_KEY = auth.apiKey or env.GOOGLE_API_KEY = auth.apiKey
vertexenv.GOOGLE_GENAI_USE_VERTEXAI = "true", env.GOOGLE_CLOUD_PROJECT = params.project, env.GOOGLE_CLOUD_LOCATION = params.region
OthersproxyRequired = true, proxyExposedTransport = "google"

4.5 OpenCode Translation Rules

OpenCode is the most flexible harness — it supports many providers natively via Vercel AI SDK packages:

ProviderTranslation
anthropicOPENCODE_CONFIG_CONTENT with @ai-sdk/anthropic provider, ANTHROPIC_API_KEY
openaiOPENCODE_CONFIG_CONTENT with @ai-sdk/openai provider, OPENAI_API_KEY
googleOPENCODE_CONFIG_CONTENT with @ai-sdk/google provider, GOOGLE_GENERATIVE_AI_API_KEY
vertexOPENCODE_CONFIG_CONTENT with @ai-sdk/google-vertex provider
bedrockOPENCODE_CONFIG_CONTENT with @ai-sdk/amazon-bedrock provider
azureOPENCODE_CONFIG_CONTENT with @ai-sdk/azure provider
ollama, local, othersOPENCODE_CONFIG_CONTENT with @ai-sdk/openai-compatible, baseURL = params.apiBase
Via proxySame as ollama/local but baseURL = proxyBaseUrl
function buildOpenCodeConfig(resolved: ProviderConfig, proxyUrl?: string): string {
const baseUrl = proxyUrl || resolved.params.apiBase;
const npm = proxyUrl
? '@ai-sdk/openai-compatible'
: resolveOpenCodeNpm(resolved.provider);

return JSON.stringify({
$schema: 'https://opencode.ai/config.json',
provider: {
amux: { npm, options: { baseURL: baseUrl } },
},
model: {
default: `amux/${resolved.model}`,
},
});
}

5. Programmatic API

5.1 SDK Surface

import { resolveProvider, translateForHarness } from '@a5c-ai/agent-mux-core';

// Resolve from mixed sources
const config: ProviderConfig = resolveProvider({
provider: 'bedrock',
model: 'anthropic.claude-sonnet-4-20250514-v1:0',
region: 'us-east-1',
// ... other overrides
});

// Translate to harness-specific config
const translation: HarnessProviderTranslation = translateForHarness('claude', config);
console.log(translation.env); // { CLAUDE_CODE_USE_BEDROCK: "1", AWS_REGION: "us-east-1", ... }
console.log(translation.args); // []
console.log(translation.proxyRequired); // false

// Use with RunOptions
const runOptions: RunOptions = {
agent: 'claude',
prompt: 'hello',
providerConfig: config, // new field on RunOptions
};

5.2 RunOptions Extension

interface RunOptions {
// ... existing fields ...

/** Provider configuration. When set, overrides adapter-default provider settings. */
providerConfig?: ProviderConfig;

/** Named provider profile to load. Merged with providerConfig if both set. */
providerProfile?: string;
}

5.3 Adapter Integration

Each adapter gains an optional method:

interface SubprocessAdapter {
// ... existing methods ...

/**
* Translate a ProviderConfig into harness-specific env vars and args.
* Returns proxyRequired=true if the harness cannot speak this provider natively.
*/
translateProvider?(config: ProviderConfig): HarnessProviderTranslation;
}

If translateProvider is not implemented, the harness is assumed to only support its default provider and all others require a proxy.


6. Model Discovery & Validation

6.1 Model List Integration

amux models is extended to show available models per provider:

# List models for a provider
amux models --provider bedrock
amux models --provider vertex --region us-central1

# List models available for a harness+provider combo
amux models --harness claude --provider bedrock

6.2 Model ID Translation

Some providers use different model ID formats for the same underlying model:

Canonical ModelAnthropicBedrockVertex
Claude Sonnet 4claude-sonnet-4-20250514anthropic.claude-sonnet-4-20250514-v1:0claude-sonnet-4@20250514
Claude Opus 4claude-opus-4-20250514anthropic.claude-opus-4-20250514-v1:0claude-opus-4@20250514
Claude Haiku 3.5claude-3-5-haiku-20241022anthropic.claude-3-5-haiku-20241022-v1:0claude-3-5-haiku@20241022

amux maintains a model ID translation table. When --model is given, it is translated to the provider-specific format. Users can also use the canonical format and let amux translate.

function translateModelId(canonical: string, provider: ProviderId): string {
const entry = MODEL_TRANSLATION_TABLE[canonical];
if (!entry) return canonical; // pass through unknown models
return entry[provider] ?? canonical;
}

6.3 Validation

Before launching, amux validates:

  1. The model exists in the provider's known model list (warning if unknown, not error)
  2. The model supports the required capabilities (tool calling, streaming, etc.)
  3. The auth is valid for the provider (where possible — e.g., checking AWS STS for Bedrock)

7. Local Model Management

7.1 Ollama Integration

For provider: "ollama", amux integrates with the local Ollama server:

# Launch with Ollama, auto-pull model if not present
amux launch claude ollama --model qwen3:32b --with-proxy-if-needed

# List locally available models
amux models --provider ollama

The amux-proxy package handles Ollama model management (see docs/provider-mux.md §6).

7.2 Model Pull

When launching with Ollama and the model is not locally available:

  1. Check ollama list for the model
  2. If missing, prompt the user: Model 'qwen3:32b' is not available locally. Pull it? [Y/n]
  3. If confirmed, pull with progress: ollama pull qwen3:32b
  4. On success, continue with launch

In non-interactive mode (--prompt), auto-pull is controlled by --auto-pull flag (default: false).


8. Security Considerations

8.1 Credential Handling

  • API keys passed via --api-key are not logged or written to config files
  • Keys in providers.json should use env var references: "apiKey": "$ANTHROPIC_API_KEY"
  • The --auth-command approach is preferred for dynamic credentials
  • --dry-run masks API keys in output: "ANTHROPIC_API_KEY": "sk-ant-***"

8.2 Proxy Trust

  • The proxy listens on 127.0.0.1 only (not 0.0.0.0)
  • The proxy uses a random session-scoped bearer token for auth between amux and the proxy
  • The token is passed to the harness as the API key
  • The proxy validates the token on every request

8.3 Config File Permissions

  • ~/.amux/providers.json should be 0600 (user-only read/write)
  • amux config warns if permissions are too open
  • Project-level .amux/providers.json should not contain secrets (use env var references)