<!-- source: https://deepwiki.com/qhkm/zeptoclaw/10.4-runtime-model-switching -->

# Runtime Model Switching

- docs/superpowers/plans/2026-03-21-tool-conformance-edit-truncation.md
- docs/superpowers/plans/2026-03-23-model-discoverability.md
- docs/superpowers/specs/2026-03-21-tool-conformance-edit-truncation-design.md
- docs/superpowers/specs/2026-03-23-model-discoverability-design.md
- src/channels/model_switch.rs
- src/kernel/provider.rs
- src/providers/mod.rs
- src/providers/registry.rs

## Purpose and Scope

This page documents the **runtime model switching** system, which allows users to dynamically change the LLM provider and model on a per-chat (or per-topic) basis without modifying configuration files. Users send commands like `/model openai:gpt-5.4` in a channel, and subsequent messages in that conversation use the specified model.

This feature is distinct from:

- Provider configuration ( 10.1 ) — the static provider setup in config.json .
- Provider resolution ( 10.1 ) — the startup-time selection of default provider.
- Provider decorators ( 10.3 ) — retry, fallback, and quota wrappers.

The system includes a **Model Discoverability** engine that can fetch live model lists from provider APIs (Anthropic, OpenAI, OpenRouter, Groq, Gemini, Ollama, DeepSeek) to ensure users always have access to the latest available models [docs/superpowers/specs/2026-03-23-model-discoverability-design.md76-110](https://github.com/qhkm/zeptoclaw/blob/2c743d31/docs/superpowers/specs/2026-03-23-model-discoverability-design.md?plain=1#L76-L110)

## Architecture Overview

Title: Runtime Model Switching and Discovery Flow

```

```

The system operates in two phases:

1. Command Phase : Channel intercepts /model commands, updates the ModelOverrideStore , and persists to long-term memory. If /model fetch is called, it triggers live discovery via provider endpoints src/channels/model_switch.rs 153-155
2. Message Phase : Channel attaches model_override and provider_override metadata to regular messages. Agent loop reads this metadata and overrides the default provider/model selection src/providers/registry.rs 262-332

**Sources**: [src/channels/model_switch.rs1-10](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/channels/model_switch.rs#L1-L10) [src/providers/registry.rs262-332](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/registry.rs#L262-L332) [docs/superpowers/specs/2026-03-23-model-discoverability-design.md76-86](https://github.com/qhkm/zeptoclaw/blob/2c743d31/docs/superpowers/specs/2026-03-23-model-discoverability-design.md?plain=1#L76-L86)

## Command Syntax and Parsing

### Supported Commands

The `/model` command supports the following subcommands [src/channels/model_switch.rs144-155](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/channels/model_switch.rs#L144-L155):

- /model : Show current model ( ModelCommand::Show ).
- /model list : List available models from the known registry and user config ( ModelCommand::List ).
- /model fetch : Fetch live models from provider APIs ( ModelCommand::Fetch ).
- /model <model> : Set model for current provider ( ModelCommand::Set ).
- /model <provider>:<model> : Set specific provider and model ( ModelCommand::Set ).
- /model reset : Clear override and return to defaults ( ModelCommand::Reset ).

### Command Parser

The `parse_model_command` function strictly validates the command prefix to avoid false matches. It includes logic to distinguish between a `provider:model` string and local provider tags (like `llama3.3:latest` in Ollama) by checking the `PROVIDER_REGISTRY` [src/channels/model_switch.rs172-218](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/channels/model_switch.rs#L172-L218)

Title: Command Parsing Logic

```

```

**Sources**: [src/channels/model_switch.rs172-218](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/channels/model_switch.rs#L172-L218) [src/channels/model_switch.rs144-155](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/channels/model_switch.rs#L144-L155) [src/providers/registry.rs55-195](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/registry.rs#L55-L195)

## Live Model Discovery

ZeptoClaw can dynamically query provider APIs to discover available models. This is primarily used during onboarding and via the `/model fetch` command.

### fetch_provider_models

Located in `src/cli/common.rs`, this function performs the following [docs/superpowers/specs/2026-03-23-model-discoverability-design.md81-103](https://github.com/qhkm/zeptoclaw/blob/2c743d31/docs/superpowers/specs/2026-03-23-model-discoverability-design.md?plain=1#L81-L103):

1. Identifies the provider's models endpoint (e.g., /v1/models for Anthropic/OpenAI).
2. Sends an authenticated GET request.
3. Parses the response (handling differences like Ollama's /api/tags vs OpenAI's data array).
4. Returns a sorted list of model IDs.

**Sources**: [docs/superpowers/specs/2026-03-23-model-discoverability-design.md76-110](https://github.com/qhkm/zeptoclaw/blob/2c743d31/docs/superpowers/specs/2026-03-23-model-discoverability-design.md?plain=1#L76-L110)

## Override Store and Persistence

### Core Types

- ModelOverride : Stores the optional provider name and the required model identifier src/channels/model_switch.rs 135-140
- ModelOverrideStore : A thread-safe Arc<RwLock<HashMap<String, ModelOverride>>> where the key is the chat ID or thread ID src/channels/model_switch.rs 158

### Persistence Flow

Overrides are persisted to `~/.zeptoclaw/memory/model_prefs.json` using the `LongTermMemory` backend.

Title: Persistence Sequence

```

```

**Sources**: [src/channels/model_switch.rs153-162](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/channels/model_switch.rs#L153-L162) [src/channels/model_switch.rs298-343](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/channels/model_switch.rs#L298-L343)

## Known Models Registry

The `KNOWN_MODELS` registry contains curated recommendations. The compile-time default model is `claude-sonnet-4-6` [src/channels/model_switch.rs27-131](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/channels/model_switch.rs#L27-L131) [docs/superpowers/specs/2026-03-23-model-discoverability-design.md70-72](https://github.com/qhkm/zeptoclaw/blob/2c743d31/docs/superpowers/specs/2026-03-23-model-discoverability-design.md?plain=1#L70-L72)

### Registry (Sample)

The `format_model_list` function merges this registry with models found in the user's `config.json`, tagging them as `(configured)` if they are missing from the static list [src/channels/model_switch.rs225-250](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/channels/model_switch.rs#L225-L250)

**Sources**: [src/channels/model_switch.rs27-131](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/channels/model_switch.rs#L27-L131) [src/channels/model_switch.rs225-281](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/channels/model_switch.rs#L225-L281)

## Agent Loop Resolution

When the `AgentLoop` receives an `InboundMessage`, it extracts the metadata to apply provider or model overrides.

Title: Override Resolution Logic

```

```

The `resolve_runtime_provider` function in `src/providers/registry.rs` ensures that if a model is specified without a provider, the system attempts to resolve the most appropriate provider based on model name keywords defined in the `ProviderSpec` [src/providers/registry.rs262-332](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/registry.rs#L262-L332) [src/providers/registry.rs11-29](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/registry.rs#L11-L29)

**Sources**: [src/providers/registry.rs262-332](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/registry.rs#L262-L332) [src/providers/registry.rs11-29](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/registry.rs#L11-L29) [src/providers/registry.rs55-195](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/providers/registry.rs#L55-L195)
