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

# Adding Providers

> How to add a new inference provider to Mibyan — auth, runtime resolution, CLI flows, adapters, tests, and docs

Mibyan can already talk to any OpenAI-compatible endpoint through the custom provider path. Do not add a built-in provider unless you want first-class UX for that service:

* provider-specific auth or token refresh
* a curated model catalog
* setup / `mibyan model` menu entries
* provider aliases for `provider:model` syntax
* a non-OpenAI API shape that needs an adapter

If the provider is just "another OpenAI-compatible base URL and API key", a named custom provider may be enough.

## The mental model

A built-in provider has to line up across a few layers:

1. `mibyan_cli/auth.py` decides how credentials are found.
2. `mibyan_cli/runtime_provider.py` turns that into runtime data:
   * `provider`
   * `api_mode`
   * `base_url`
   * `api_key`
   * `source`
3. `run_agent.py` uses `api_mode` to decide how requests are built and sent.
4. `mibyan_cli/models.py` and `mibyan_cli/main.py` make the provider show up in the CLI. (`mibyan_cli/setup.py` delegates to `main.py` automatically — no changes needed there.)
5. `agent/auxiliary_client.py` and `agent/model_metadata.py` keep side tasks and token budgeting working.

The important abstraction is `api_mode`.

* Most providers use `chat_completions`.
* Codex and Meta Model API (`api.meta.ai` — Muse Spark) use `codex_responses` (auto-sends `prompt_cache_retention: 24h` for prompt caching; `api.meta.ai` achieves 93–99% cache hits only on `/v1/responses`).
* Ramp Router (`api.router.com`) also uses `codex_responses` — Responses is Router's native wire (`/v1/chat/completions` is only a minimal compatibility shim), and it validates `reasoning.effort` per model, which the router profile handles by declaring each model's vocabulary from the live catalog (`ProviderProfile.supported_reasoning_efforts`).
* Anthropic uses `anthropic_messages`.
* A new non-OpenAI protocol usually means adding a new adapter and a new `api_mode` branch.

### Tool-call wire format

Mibyan stores conversation history in the OpenAI chat-completions shape internally, so the `chat_completions` transport's `convert_messages` / `convert_tools` (`agent/transports/chat_completions.py`) are near-identity, and every other transport converts *from* that shape into its native protocol. The canonical reference for the shape — `tools` definitions with JSON-schema `parameters`, assistant `tool_calls` entries with stringified `function.arguments`, and `role: "tool"` result messages keyed by `tool_call_id` — is the [OpenAI chat completions API reference](https://platform.openai.com/docs/api-reference/chat/create). When you write a native adapter, that page defines the input side of your conversion; your provider's docs define the output side.

## Choose the implementation path first

### Path A — OpenAI-compatible provider

Use this when the provider accepts standard chat-completions style requests.

Typical work:

* add auth metadata
* add model catalog / aliases
* add runtime resolution
* add CLI menu wiring
* add aux-model defaults
* add tests and user docs

You usually do not need a new adapter or a new `api_mode`.

### Path B — Native provider

Use this when the provider does not behave like OpenAI chat completions.

Examples in-tree today:

* `codex_responses` (OpenAI Codex, xAI Grok, Meta Muse Spark via `api.meta.ai` — the latter auto-sends `prompt_cache_retention: 24h` — and Ramp Router via `api.router.com`)
* `anthropic_messages`

This path includes everything from Path A plus:

* a provider adapter in `agent/`
* `run_agent.py` branches for request building, dispatch, usage extraction, interrupt handling, and response normalization
* adapter tests

## File checklist

### Required for every built-in provider

1. `mibyan_cli/auth.py`
2. `mibyan_cli/models.py`
3. `mibyan_cli/runtime_provider.py`
4. `mibyan_cli/main.py`
5. `agent/auxiliary_client.py`
6. `agent/model_metadata.py`
7. tests
8. user-facing docs under `website/docs/`

<Tip>
  `mibyan_cli/setup.py` does **not** need changes. The setup wizard delegates provider/model selection to `select_provider_and_model()` in `main.py` — any provider added there is automatically available in `mibyan setup`.
</Tip>

### Additional for native / non-OpenAI providers

10. `agent/<provider>_adapter.py`
11. `run_agent.py`
12. `pyproject.toml` if a provider SDK is required

## Fast path: Simple API-key providers

If your provider is just an OpenAI-compatible endpoint that authenticates with a single API key, you do not need to touch `auth.py`, `runtime_provider.py`, `main.py`, or any of the other files in the full checklist below.

All you need is:

1. A plugin directory under `plugins/model-providers/<your-provider>/` containing:
   * `__init__.py` — calls `register_provider(profile)` at module-level
   * `plugin.yaml` — manifest (name, kind: model-provider, version, description)
2. That's it. Provider plugins auto-load the first time anything calls `get_provider_profile()` or `list_providers()` — bundled plugins (this repo) and user plugins at `$mibyan_HOME/plugins/model-providers/` both get picked up.

When you add a plugin and it calls `register_provider()`, the following wire up automatically:

1. `PROVIDER_REGISTRY` entry in `auth.py` (credential resolution, env-var lookup)
2. `api_mode` set to `chat_completions`
3. `base_url` sourced from the config or the declared env var
4. `env_vars` checked in priority order for the API key
5. `fallback_models` list registered for the provider
6. `--provider` CLI flag accepts the provider id
7. `mibyan model` menu includes the provider
8. `mibyan setup` wizard delegates to `main.py` automatically
9. `provider:model` alias syntax works
10. Runtime resolver returns the correct `base_url` and `api_key`
11. `--provider <name>` CLI flag accepts the provider id
12. Fallback model activation can switch into the provider cleanly

User plugins at `$mibyan_HOME/plugins/model-providers/<name>/` override bundled plugins of the same name (last-writer-wins in `register_provider()`) — so third parties can monkey-patch or replace any built-in profile without editing the repo.

See `plugins/model-providers/nvidia/` or `plugins/model-providers/gmi/` as a template, and the full [Model Provider Plugin guide](/desktop/developer-guide/model-provider-plugin) for field reference, hook idioms, and end-to-end examples.

## Full path: OAuth and complex providers

Use the full checklist below when your provider needs any of the following:

* OAuth or token refresh (Nous Portal, Codex, Qwen Portal, Copilot)
* A non-OpenAI API shape that requires a new adapter (Anthropic Messages, Codex Responses)
* Custom endpoint detection or multi-region probing (z.ai, Kimi)
* A curated static model catalog or live `/models` fetch
* Provider-specific `mibyan model` menu entries with bespoke auth flows

## Step 1: Pick one canonical provider id

Choose a single provider id and use it everywhere.

Examples from the repo:

* `openai-codex`
* `kimi-coding`
* `minimax-cn`

That same id should appear in:

* `PROVIDER_REGISTRY` in `mibyan_cli/auth.py`
* `_PROVIDER_LABELS` in `mibyan_cli/models_catalog_static.py` (re-exported by `mibyan_cli/models.py`)
* `_PROVIDER_ALIASES` in both `mibyan_cli/auth.py` and `mibyan_cli/models_catalog_static.py`
* CLI `--provider` choices in `mibyan_cli/main.py`
* setup / model selection branches
* auxiliary-model defaults
* tests

If the id differs between those files, the provider will feel half-wired: auth may work while `/model`, setup, or runtime resolution silently misses it.

## Step 2: Add auth metadata in `mibyan_cli/auth.py`

For API-key providers, add a `ProviderConfig` entry to `PROVIDER_REGISTRY` with:

* `id`
* `name`
* `auth_type="api_key"`
* `inference_base_url`
* `api_key_env_vars`
* optional `base_url_env_var`

Also add aliases to `_PROVIDER_ALIASES`.

Use the existing providers as templates:

* simple API-key path: Z.AI, MiniMax
* API-key path with endpoint detection: Kimi, Z.AI
* native token resolution: Anthropic
* OAuth / auth-store path: Nous, OpenAI Codex

Questions to answer here:

* What env vars should Mibyan check, and in what priority order?
* Does the provider need base-URL overrides?
* Does it need endpoint probing or token refresh?
* What should the auth error say when credentials are missing?

If the provider needs something more than "look up an API key", add a dedicated credential resolver instead of shoving logic into unrelated branches.

## Step 3: Add model catalog and aliases in `mibyan_cli/models.py`

Update the provider catalog so the provider works in menus and in `provider:model` syntax.

Typical edits:

* `_PROVIDER_MODELS`
* `_PROVIDER_LABELS`
* `_PROVIDER_ALIASES`
* provider display order inside `list_available_providers()`
* `provider_model_ids()` if the provider supports a live `/models` fetch

If the provider exposes a live model list, prefer that first and keep `_PROVIDER_MODELS` as the static fallback.

This file is also what makes inputs like these work:

```text theme={null}
anthropic:claude-sonnet-4-6
kimi:model-name
```

If aliases are missing here, the provider may authenticate correctly but still fail in `/model` parsing.

## Step 4: Resolve runtime data in `mibyan_cli/runtime_provider.py`

`resolve_runtime_provider()` is the shared path used by CLI, gateway, cron, ACP, and helper clients.

Add a branch that returns a dict with at least:

```python theme={null}
{
    "provider": "your-provider",
    "api_mode": "chat_completions",  # or your native mode
    "base_url": "https://...",
    "api_key": "...",
    "source": "env|portal|auth-store|explicit",
    "requested_provider": requested_provider,
}
```

If the provider is OpenAI-compatible, `api_mode` should usually stay `chat_completions`.

Be careful with API-key precedence. Mibyan already contains logic to avoid leaking an OpenRouter key to unrelated endpoints. A new provider should be equally explicit about which key goes to which base URL.

## Step 5: Wire the CLI in `mibyan_cli/main.py`

A provider is not discoverable until it shows up in the interactive `mibyan model` flow.

Update these in `mibyan_cli/main.py`:

* `provider_labels` dict
* `providers` list in `select_provider_and_model()`
* provider dispatch (`if selected_provider == ...`)
* `--provider` argument choices
* login/logout choices if the provider supports those flows
* a `_model_flow_<provider>()` function, or reuse `_model_flow_api_key_provider()` if it fits

<Tip>
  `mibyan_cli/setup.py` does not need changes — it calls `select_provider_and_model()` from `main.py`, so your new provider appears in both `mibyan model` and `mibyan setup` automatically.
</Tip>

## Step 6: Keep auxiliary calls working

Two files matter here:

### `agent/auxiliary_client.py`

Add a cheap / fast default aux model to `_API_KEY_PROVIDER_AUX_MODELS` if this is a direct API-key provider.

Auxiliary tasks include things like:

* vision summarization
* web extraction summarization
* context compression summaries
* session-search summaries
* memory flushes

If the provider has no sensible aux default, side tasks may fall back badly or use an expensive main model unexpectedly.

### `agent/model_metadata.py`

Add context lengths for the provider's models so token budgeting, compression thresholds, and limits stay sane.

## Step 7: If the provider is native, add an adapter and `run_agent.py` support

If the provider is not plain chat completions, isolate the provider-specific logic in `agent/<provider>_adapter.py`.

Keep `run_agent.py` focused on orchestration. It should call adapter helpers, not hand-build provider payloads inline all over the file.

A native provider usually needs work in these places:

### New adapter file

Typical responsibilities:

* build the SDK / HTTP client
* resolve tokens
* convert OpenAI-style conversation messages to the provider's request format
* convert tool schemas if needed
* normalize provider responses back into what `run_agent.py` expects
* extract usage and finish-reason data

### `run_agent.py`

Search for `api_mode` and audit every switch point. At minimum, verify:

* `__init__` chooses the new `api_mode`
* client construction works for the provider
* `_build_api_kwargs()` knows how to format requests
* `_interruptible_api_call()` dispatches to the right client call
* interrupt / client rebuild paths work
* response validation accepts the provider's shape
* finish-reason extraction is correct
* token-usage extraction is correct
* fallback-model activation can switch into the new provider cleanly
* summary-generation and memory-flush paths still work

Also search `run_agent.py` for `self.client.`. Any code path that assumes the standard OpenAI client exists can break when a native provider uses a different client object or `self.client = None`.

### Prompt caching and provider-specific request fields

Prompt caching and provider-specific knobs are easy to regress.

Examples already in-tree:

* Anthropic has a native prompt-caching path
* OpenRouter gets provider-routing fields
* not every provider should receive every request-side option

When you add a native provider, double-check that Mibyan is only sending fields that provider actually understands.

## Step 8: Tests

At minimum, touch the tests that guard provider wiring.

Common places:

* `tests/mibyan_cli/test_runtime_provider_resolution.py`
* `tests/mibyan_cli/test_cli_provider_resolution.py`
* `tests/mibyan_cli/test_model_switch_custom_providers.py` (and adjacent `tests/mibyan_cli/test_model_switch_*.py`)
* `tests/mibyan_cli/test_setup_model_provider.py`
* `tests/agent/test_provider_parity.py`
* `tests/agent/test_run_agent.py`
* `tests/agent/test_<provider>_adapter.py` for a native provider

For docs-only examples, the exact file set may differ. The point is to cover:

* auth resolution
* CLI menu / provider selection
* runtime provider resolution
* agent execution path
* provider:model parsing
* any adapter-specific message conversion

Prepare the [independent test environment](/desktop/developer-guide/contributing#manual-development-and-test-environment),
then use the canonical runner, which isolates each file and scrubs credentials:

```bash theme={null}

scripts/run_tests.sh tests/mibyan_cli/test_runtime_provider_resolution.py tests/mibyan_cli/test_cli_provider_resolution.py tests/mibyan_cli/test_setup_model_provider.py tests/agent/test_provider_parity.py -q
```

For deeper changes, run the full suite before pushing:

```bash theme={null}
scripts/run_tests.sh tests/ -q
```

## Step 9: Live verification

After tests, run a real smoke test from the checkout using the
[PM developer workflow](/desktop/reference/package-management#developer-workflow) and
its isolated development home. Leave any test venv before PM activation.

```bash theme={null}
source ./activate
python mibyan chat -q "Say hello" --provider your-provider --model your-model
```

Also test the interactive flows if you changed menus:

```bash theme={null}
source ./activate
python mibyan model
python mibyan setup
```

For native providers, verify at least one tool call too, not just a plain text response.

## Step 10: Update user-facing docs

If the provider is meant to ship as a first-class option, update the user docs too:

* `website/docs/getting-started/quickstart.md`
* `website/docs/user-guide/configuration.md`
* `website/docs/reference/environment-variables.md`

A developer can wire the provider perfectly and still leave users unable to discover the required env vars or setup flow.

## OpenAI-compatible provider checklist

Use this if the provider is standard chat completions.

* [ ] `ProviderConfig` added in `mibyan_cli/auth.py`
* [ ] aliases added in `mibyan_cli/auth.py` and `mibyan_cli/models.py`
* [ ] model catalog added in `mibyan_cli/models.py`
* [ ] runtime branch added in `mibyan_cli/runtime_provider.py`
* [ ] CLI wiring added in `mibyan_cli/main.py` (setup.py inherits automatically)
* [ ] aux model added in `agent/auxiliary_client.py`
* [ ] context lengths added in `agent/model_metadata.py`
* [ ] runtime / CLI tests updated
* [ ] user docs updated

## Native provider checklist

Use this when the provider needs a new protocol path.

* [ ] everything in the OpenAI-compatible checklist
* [ ] adapter added in `agent/<provider>_adapter.py`
* [ ] new `api_mode` supported in `run_agent.py`
* [ ] interrupt / rebuild path works
* [ ] usage and finish-reason extraction works
* [ ] fallback path works
* [ ] adapter tests added
* [ ] live smoke test passes

## Common pitfalls

### 1. Adding the provider to auth but not to model parsing

That makes credentials resolve correctly while `/model` and `provider:model` inputs fail.

### 2. Forgetting that `config["model"]` can be a string or a dict

A lot of provider-selection code has to normalize both forms.

### 3. Assuming a built-in provider is required

If the service is just OpenAI-compatible, a custom provider may already solve the user problem with less maintenance.

### 4. Forgetting auxiliary paths

The main chat path can work while summarization, memory flushes, or vision helpers fail because aux routing was never updated.

### 5. Native-provider branches hiding in `run_agent.py`

Search for `api_mode` and `self.client.`. Do not assume the obvious request path is the only one.

### 6. Sending OpenRouter-only knobs to other providers

Fields like provider routing belong only on the providers that support them.

### 7. Updating `mibyan model` but not `mibyan setup`

Both flows need to know about the provider.

## Good search targets while implementing

If you are hunting for all the places a provider touches, search these symbols:

* `PROVIDER_REGISTRY`
* `_PROVIDER_ALIASES`
* `_PROVIDER_MODELS`
* `resolve_runtime_provider`
* `_model_flow_`
* `select_provider_and_model`
* `api_mode`
* `_API_KEY_PROVIDER_AUX_MODELS`
* `self.client.`

## Related docs

* [Provider Runtime Resolution](/desktop/developer-guide/provider-runtime)
* [Architecture](/desktop/developer-guide/architecture)
* [Contributing](/desktop/developer-guide/contributing)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.