> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xpander.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# AI vendors

> Which model providers xpander speaks to, how their keys reach xpander on cloud, hybrid and air-gapped installs, and what changes when you bring your own key.

xpander runs any model, frontier or open-weight, through the [AI gateway](/run/integrations/ai-gateway). The provider decides which harness a new agent starts on and whether calls are charged in credits or run on your own key.

## Providers

| Provider                                                      | Key                                                                             | Notes                                                                                                                                                                                |
| ------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Anthropic                                                     | `ANTHROPIC_API_KEY`                                                             | Default for Claude Code. Baked default model: Fable 5.1 (`claude-fable-5-1`)                                                                                                         |
| OpenAI                                                        | `AGENTS_OPENAI_API_KEY`                                                         | Default for Codex. Baked default: `gpt-6-astra`                                                                                                                                      |
| Amazon Bedrock                                                | `AWS_BEARER_TOKEN_BEDROCK`, or keyless through the pods' AWS identity           | Fable- and Mythos-class Anthropic models need the account's data-retention opt-in per region, or Bedrock answers `400 data retention mode 'default' is not available for this model` |
| Google                                                        | `GOOGLE_API_KEY`                                                                |                                                                                                                                                                                      |
| Fireworks, Nebius, OpenRouter, Helicone                       | `FIREWORKS_API_KEY`, `NEBIUS_API_KEY`, `OPENROUTER_API_KEY`, `HELICONE_API_KEY` | OpenCode takes any `<provider>/<model>` slot the proxy routes                                                                                                                        |
| Your own OpenAI-compatible runtime (vLLM, Ollama, NVIDIA NIM) | None, or whatever the runtime requires                                          | Required on Air-Gapped; register it under Settings > LLM settings > **Add custom provider** ([steps](#add-a-custom-provider))                                                        |

## Where keys live

Three places, checked in this order for a model call:

1. **An agent-level credential** on one agent.
2. **An organization-level key per provider** under **Settings > LLM settings** (**Add key** on a built-in provider, **Add custom provider** for your own endpoint, **Workspace defaults** for the default model).
3. **The install's keys** on a self-hosted cluster: chart values `secrets.static.<provider>ApiKey`, or a Kubernetes secret referenced with `envFromSecretKeys`.

```bash theme={"dark"}
helm upgrade xpander xpander/xpander --namespace xpander --reuse-values \
  --set secrets.static.anthropicApiKey=<KEY> --timeout 5m
```

Pods that use an updated secret restart on their own. The `xpander-static` secret has a Helm keep policy; if a key is not picked up after an upgrade, patch the secret directly and restart `xpander-agent-worker`. The full value-to-secret mapping is on [Hybrid: managing LLM API keys](/self-hosted/hybrid#managing-llm-api-keys).

<Frame caption="Add provider key for a built-in provider: name, provider, API key, optional description. Shown with sample data.">
  <img src="https://mintcdn.com/xpanderai-099931d1/OdLxX9OyFVicAV0l/images/verify/llm-add-key-anthropic-1.png?fit=max&auto=format&n=OdLxX9OyFVicAV0l&q=85&s=e09071666cf468a90967efe2a49c80a6" alt="Add provider key dialog" width="1440" height="900" data-path="images/verify/llm-add-key-anthropic-1.png" />
</Frame>

## Credits against your own keys

Model calls are charged in credits when they run on keys xpander provides. A call that runs on a key you brought, agent-level or organization-level, is never charged credits. Hybrid relays xpander's vendor keys but never Bedrock: Claude Code on Bedrock on a Hybrid install needs your own Bedrock auth on the controller.

## Provider setup on a self-hosted install

Claude Code speaks to Anthropic; Codex speaks to OpenAI; OpenCode takes any `<provider>/<model>` slot the proxy routes. Credentials live **only on the Agent Controller**.

### Anthropic direct

An Anthropic API key on the controller, the same key wiring as the rest of xpander. The controller egresses to `api.anthropic.com`; override the upstream with `LLM_PROXY_ANTHROPIC_BASE_URL` for a gateway of your own.

### Anthropic on Amazon Bedrock

Claude Code can run Anthropic models on Bedrock through the proxy's `amazon_bedrock` leg. The controller resolves AWS auth in this order, and no executor ever sees it:

| Method                   | Controller environment                                                           | Notes                                                    |
| ------------------------ | -------------------------------------------------------------------------------- | -------------------------------------------------------- |
| Bearer token             | `AWS_BEARER_TOKEN_BEDROCK` (+ `BEDROCK_REGION` / `AWS_REGION`)                   | Relayed as-is, no signing. The simplest option           |
| Assume role              | `BEDROCK_ASSUME_ROLE_ARN` (+ `BEDROCK_ASSUME_ROLE_EXTERNAL_ID`, `_SESSION_NAME`) | STS credentials, self-refreshing, SigV4 signed           |
| Static keys              | `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` (/ `AWS_SESSION_TOKEN`)            | SigV4 signed                                             |
| Default credential chain | `AGENT_GATEWAY_BEDROCK_DEFAULT_CHAIN=true` (default)                             | IRSA / EKS Pod Identity / instance profile, SigV4 signed |

On Air-Gapped there is no public Bedrock: point `LLM_PROXY_AMAZON_BEDROCK_BASE_URL` at a VPC (PrivateLink) Bedrock runtime endpoint and set the matching region, or leave Bedrock off. The Air-Gapped chart exposes all of this under `global.llm.bedrock`: `region`, `bearerTokenSecret` (a Secret you create carrying a Bedrock API key), `assumeRoleArn` and `assumeRoleExternalId` (the STS path), and `baseUrl` (the VPC endpoint the `amazon_bedrock` leg dials on a sealed install). Leave the token and the role empty to use the pod's own credential chain (EKS Pod Identity or IRSA). On Hybrid, set the same variables on the Agent Controller through the chart's env values.

<Warning>
  **Fable- and Mythos-class Anthropic models on Bedrock need the account's data-retention opt-in, per region.** Bedrock serves those models only to accounts whose data retention mode is one Anthropic accepts (`provider_data_share`, or `aws_review` where offered); with the default mode every call fails with `400 data retention mode 'default' is not available for this model`, even though the model id resolved. There is no console switch: set it once per region with the Bedrock control-plane API, `PUT https://bedrock.<region>.amazonaws.com/data-retention` with the body `{"mode": "provider_data_share"}` (SigV4-signed, IAM action `bedrock:PutAccountDataRetention`), for every region a `global.` inference profile can route to. The first call after the change can still fail while it propagates; retry before debugging. This applies to **whichever AWS account signs the call**: the proxy prefers an organization's own stored Bedrock key over the install's credential, so an org that brings its own Bedrock key must opt that account in too. Older Anthropic models on Bedrock need no opt-in, which is why the symptom looks model-specific.
</Warning>

<Info>
  **Bedrock in a Hybrid deployment needs your own credentials.** xpander cloud sends a Hybrid cluster its own Anthropic, OpenAI and Google keys, so agents work before you add anything and those calls are charged in credits. It never sends Bedrock credentials. Until an admin adds a Bedrock key or role under **Settings > LLM**, or the cluster has its own AWS identity for Bedrock, Claude Code agents there run on xpander's Anthropic key. The Bedrock account also needs the opt-in above.
</Info>

<Info>
  The keyless (role / Pod Identity) methods above apply to the AI gateway's proxy on the Agent Controller. The `agent-worker` service has a separate constraint on keyless Bedrock; see [Amazon Bedrock: key vs IAM](/self-hosted/hybrid#amazon-bedrock-key-vs-iam) on the Hybrid page.
</Info>

## Add a custom provider

Any endpoint that speaks the OpenAI-compatible API (vLLM, Ollama, NVIDIA NIM) is registered once for the organization under **Settings > LLM settings > Add custom provider**:

1. **Name**, and the **Slug** derived from it (lowercase, underscores).
2. **Protocol**: **OpenAI-compatible**. **Base URL**: the address as the pods reach it, for example `http://vllm.<namespace>.svc.cluster.local:8000/v1`.
3. **API key**: **No key (local or unauthenticated server)**, **Use an existing key**, or **Create a new key** with a **Key name** and the key.
4. **Test connection** under **Models** reports **Reachable** with the round-trip time and lists the models the endpoint serves; a model that accepts function calls carries a `tools` badge. **Add** the models agents may use, then **Add provider**.
5. On the model row choose **Set model cost** and enter the **Price per 1M tokens (USD)** for **Input** and **Output**; the cache rates are optional. The dialog's own words: "Agents can use the model once it has a cost." The prices measure credit burn and are never charged.

`POST /v1/agents` accepts only the built-in providers in `model_provider`; a custom slug is refused with `422`. A custom provider is picked per conversation instead. The composer's **Harness and model** popover has a left rail with **Claude Code**, **Codex** and **OpenCode**: the **Claude Code** pane lists Amazon Bedrock and Anthropic, **Codex** lists OpenAI models, and **OpenCode** lists every provider, custom ones included. A custom model is selectable there once it has a cost. A local model also needs a context window well above the prompt xpander composes. A worked example, vLLM on a GPU node in the same cluster with the flags that make the probe pass and the context length that runs, is on [Air-Gapped: a worked vLLM setup](/self-hosted/airgap#a-worked-vllm-setup-on-eks-auto-mode).

<Frame caption="Add custom provider: name and slug, protocol, base URL, the API key choice, and Test connection under Models. Shown with sample data.">
  <img src="https://mintcdn.com/xpanderai-099931d1/OdLxX9OyFVicAV0l/images/verify/lab-llm-add-custom-provider.png?fit=max&auto=format&n=OdLxX9OyFVicAV0l&q=85&s=fc3ef88ef885532eac462ed4b59681ea" alt="Add provider dialog with Name, Slug, Protocol OpenAI-compatible, Base URL, API key options No key, Use an existing key and Create a new key, and a Models section with Test connection and Add model" width="1440" height="900" data-path="images/verify/lab-llm-add-custom-provider.png" />
</Frame>

## Which harness and model a new agent gets

A create that names a runtime, a provider, a model or harness settings is honored as written. A create that names none of them is **defaulted**, in the same order everywhere (cloud, Hybrid, Air-Gapped):

1. **The organization's default LLM** (Settings > LLM) maps to a CLI as follows:

   * Anthropic maps to Claude Code, on that model.
   * Amazon Bedrock with an Anthropic model id maps to Claude Code on Bedrock.
   * OpenAI maps to Codex.
   * Any other provider the LLM proxy routes maps to OpenCode, with that `<provider>/<model>` slot.

   A provider no CLI can run, or no org default at all, falls through to the next step.
2. **The install's default knobs** (env on the `agents` and `agent-controller` services; on Air-Gapped the chart values below).
3. **The baked defaults**: Claude Code on Anthropic direct with Fable 5.1 (`claude-fable-5-1`), Codex on `gpt-6-astra`, OpenCode on `anthropic/claude-opus-5`.

So a fresh Air-Gapped install whose organization has not set a default LLM creates Claude Code agents on **Fable 5.1 over Anthropic direct**. The install needs an Anthropic key reachable from the controller, or Amazon Bedrock declared as the org default or through the knobs (with the data-retention opt-in above). Changing these defaults later does not touch agents that already exist. Each conversation can pick another CLI or model in the composer.

| Deployment | Knob                                                                                                                                                                          | Effect                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Air-Gapped | `global.harness.defaultModels.{claudeCode,codex,opencode,xpander}` (rendered as `XPANDER_HARNESS_DEFAULT_MODEL_<CLI>` on both `agent-controller` and the `agents` Deployment) | The per-CLI model a defaulted agent gets when the org has no default LLM. The baked vendor ids are unreachable on a sealed network, so name the models your endpoint serves. `claudeCode` and `codex` take a bare model id; `opencode` and `xpander` take a `<provider>/<model>` slot whose provider the proxy routes. A Bedrock inference-profile id in `claudeCode` (for example `us.anthropic.claude-sonnet-4-6`) is enough on its own: the provider is inferred from it. An explicit `agents.env` / `agent-controller.env` entry wins |
| Air-Gapped | `global.harness.defaultProviders.claudeCode` (rendered as `XPANDER_HARNESS_DEFAULT_PROVIDER_CLAUDE_CODE` on the `agents` Deployment)                                          | Empty = Anthropic direct. `amazon_bedrock` routes defaulted Claude Code agents to Bedrock through `global.llm.bedrock`, keeping the default model                                                                                                                                                                                                                                                                                                                                                                                         |
| Hybrid     | none in the chart                                                                                                                                                             | The `agents` service runs in xpander cloud, so step 2 is the cloud's own default: defaulted Claude Code agents run on **Anthropic direct** over the relayed key (the cloud never relays Bedrock). Configure the org default LLM to steer defaulted agents elsewhere; the controller in your cluster needs credentials for whichever provider your agents use                                                                                                                                                                              |

**Claude Code on Bedrock on Air-Gapped needs the chart's harness defaults set.** `global.harness.defaultProviders.claudeCode: amazon_bedrock` and `global.harness.defaultModels.claudeCode: <Bedrock model id>` tell a defaulted agent to run Claude Code through Bedrock. Without them the agent targets Anthropic directly, and its first turn fails with `503 no anthropic credential configured for harness agents` even when the organization's default model is on Bedrock.

## Model access per group

**Settings > LLM settings** lists which models each group may use. A model outside the group's allow-list does not appear in the harness picker, and a run that names it is refused.

<Frame caption="Access for a provider: a workspace-wide switch, then groups that narrow it. Shown with sample data.">
  <img src="https://mintcdn.com/xpanderai-099931d1/OdLxX9OyFVicAV0l/images/verify/llm-model-access-group-1.png?fit=max&auto=format&n=OdLxX9OyFVicAV0l&q=85&s=3c95bd40b1f92df55c7c3850de094d7d" alt="Manage access popover for a provider" width="1440" height="900" data-path="images/verify/llm-model-access-group-1.png" />
</Frame>
