# Migrate between LLM providers

> Switch agents from OpenAI to Anthropic to Gemini (or any OpenAI-compatible provider) without rewriting prompts or capabilities.

Source: <https://everruns.com/docs/how-to/migrate-providers/>

Everruns abstracts the LLM behind a uniform interface, so the same agent can run on OpenAI, Anthropic, Gemini, or any OpenAI-compatible provider. This guide swaps providers cleanly without losing sessions or rewriting agents.

## Concepts

Two pieces decide which model runs:

* **LLM Provider**: a configured API provider with encrypted credentials (e.g., `openai`, `openrouter`, `anthropic`, `gemini`, `openai_completions`).
* **LLM Model**: a specific model on a provider (e.g., `gpt-6.1-sol`, `claude-sonnet-5-5`, `gemini-3.8-flash`).

Model resolution priority on each turn:

1. Message-level `controls.model_id` (if present on the incoming message).
2. Session override (`session.default_model_id`).
3. Agent default (`agent.default_model_id`).
4. System default.

## Add a new provider

```bash
curl -X POST http://localhost:9300/api/v1/providers \
  -H "Content-Type: application/json" \
  -d '{
    "name": "anthropic",
    "provider_type": "anthropic",
    "api_key": "sk-ant-..."
  }'
```

The API key is encrypted at rest. The provider’s models are discovered on creation; manually-added models are also supported.

## Switch an agent’s default model

```bash
curl -X PATCH http://localhost:9300/api/v1/agents/$AGENT_ID \
  -H "Content-Type: application/json" \
  -d '{ "default_model_id": "model_..." }'
```

Model IDs have the form `model_` followed by 32 hex characters. Find the ID of the model you want with `GET /api/v1/models` (or the model list in the UI), and substitute it for `model_...` throughout this guide.

New sessions inherit the new default. **Existing sessions keep running on the model they started with** unless you override per-session or per-message.

## Override per session

For an A/B comparison, override at the session level:

```bash
curl -X POST http://localhost:9300/api/v1/sessions \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agent_...",
    "default_model_id": "model_..."
  }'
```

## Override per message

The most targeted form, run a single turn on a different model:

```python
from everruns_sdk import Controls


await client.messages.create(
    session.id,
    "Re-analyse the above with extra rigour.",
    controls=Controls(model_id="model_..."),
)
```

## Compatibility caveats

Most behaviour ports across providers, but a few things differ:

* **Extended thinking / reasoning effort.** Supported on Anthropic Claude, OpenAI GPT-5.x, and o-series. Other models silently ignore the `reasoning_effort` control.
* **Execution phases on the wire.** OpenAI Responses API on the GPT-5.4 and GPT-5.5 families accepts `phase` annotations on replayed messages; other providers (and earlier OpenAI models) ignore them. Internal tracking continues regardless. See [Execution phases](https://everruns.com/docs/explanation/agentic-loop/#execution-phases).
* **Tool call format differences.** The platform handles translation, but very large tool schemas may compress better on one provider than another.
* **Per-token cost.** USD budgets adjust automatically since they use per-model pricing. Token budgets are model-agnostic.

## Verify before flipping production

A safe migration sequence:

1. Add the new provider and verify discovered models.
2. Create a test agent that mirrors production, with `default_model_id` set to a model on the new provider.
3. Run an evaluation suite against the test agent.
4. Once happy, update the production agent’s `default_model_id`, new sessions migrate over.
5. Leave old sessions on the old model; they age out naturally.

## See also

* [Concepts: LLM Provider and Model](https://everruns.com/docs/getting-started/concepts/), entity model.
* [Observability with Braintrust](https://everruns.com/docs/observability/braintrust/), evaluate cross-provider quality.