# Understanding the Model Identifier Format in aisuite: Parsing 'provider:model' Strings

> Learn the aisuite model identifier format provider:model. Understand how aisuite routes requests by splitting the string to load specific LLM provider classes.

- Repository: [Andrew Ng/aisuite](https://github.com/andrewyng/aisuite)
- Tags: internals
- Published: 2026-08-04

---

**The `provider:model` string format is the canonical way aisuite routes requests to specific LLM providers, splitting on the colon to separate the provider key from the model name before lazy-loading the appropriate provider class.**

Every request in the `andrewyng/aisuite` library starts with a simple string like `"openai:gpt-4o"` or `"anthropic:claude-3-opus-20240229"`. This article explains how aisuite parses these model identifier formats to validate, route, and execute calls across multiple AI providers using a consistent interface.

## The Anatomy of a Provider:Model String

The `provider:model` format follows a strict convention that enables aisuite to determine both *where* to send a request and *which* model to invoke. The parsing logic resides in `Client._resolve_provider` within [`aisuite/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/client.py) (lines 52-65), which serves as the entry point for both chat completions and audio transcriptions.

### Validation and Splitting Logic

Before any provider interaction occurs, aisuite validates the identifier format using a defensive check:

```python
if ":" not in model:
    raise ValueError(
        f"Invalid model format. Expected 'provider:model', got '{model}'"
    )
provider_key, model_name = model.split(":", 1)

```

This ensures **exactly one** colon separates the components. The `provider_key` (e.g., `"openai"`, `"anthropic"`) determines which SDK to initialize, while the `model_name` (e.g., `"gpt-4o"`, `"claude-3-opus-20240229"`) passes through unchanged to the provider's API call. If the colon is missing, aisuite raises a `ValueError` immediately, preventing ambiguous routing.

## How aisuite Resolves Provider Instances

Once split, the `provider_key` undergoes a two-phase resolution process: validation against supported providers and lazy instantiation.

### Lazy Provider Instantiation

The `Client` class caches provider instances to avoid redundant initialization overhead. In [`aisuite/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/client.py), the `_resolve_provider` method checks an internal dictionary before creating new connections:

```python
if provider_key not in self.client.providers:
    config = self.client.provider_configs.get(provider_key, {})
    self.client.providers[provider_key] = ProviderFactory.create_provider(
        provider_key, dict(config)
    )

```

This **lazy-loading** approach defers SDK imports and network connections until the first actual request, improving startup performance. The provider instance persists in `self.client.providers` for subsequent calls, ensuring one initialization per process.

### The ProviderFactory Convention

The mapping from `provider_key` to Python class follows a **convention-over-configuration** pattern implemented in `ProviderFactory.create_provider` ([`aisuite/provider.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/provider.py), lines 96-106):

```python
provider_class_name = f"{provider_key.capitalize()}Provider"
provider_module_name = f"{provider_key}_provider"
module_path = f"aisuite.providers.{provider_module_name}"

```

For a key like `"openai"`, the factory imports `aisuite.providers.openai_provider` and instantiates the `OpenaiProvider` class. All provider implementations live under `aisuite/providers/` (e.g., [`anthropic_provider.py`](https://github.com/andrewyng/aisuite/blob/main/anthropic_provider.py), [`groq_provider.py`](https://github.com/andrewyng/aisuite/blob/main/groq_provider.py)), making the system extensible—adding support for a new service requires only a module following this naming convention.

## Error Handling and Validation

If the `provider_key` extracted from the identifier does not exist in the set returned by `ProviderFactory.get_supported_providers()` (defined in [`aisuite/provider.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/provider.py)), aisuite raises a `ValueError` listing all supported providers. This defensive programming provides immediate feedback when users mistype provider names or attempt to use unsupported services, eliminating silent failures or ambiguous routing errors.

## Practical Implementation Examples

The following examples demonstrate the complete flow from identifier string to API execution:

```python
from aisuite import Client

# Initialize with provider configurations

client = Client(provider_configs={"openai": {"api_key": "sk-..."}})

# Chat completion using the provider:model format

response = client.chat.completions.create(
    model="openai:gpt-4o",
    messages=[{"role": "user", "content": "Explain the provider:model format"}]
)

# Audio transcription with the same identifier pattern

audio_response = client.audio.transcriptions.create(
    model="openai:whisper-1",
    file="audio.wav",
    language="en"
)

```

Both calls trigger identical internal mechanics:

1. `Client._resolve_provider` splits `"openai:gpt-4o"` into `provider_key="openai"` and `model_name="gpt-4o"`
2. `ProviderFactory.create_provider` loads the `OpenaiProvider` class from [`aisuite/providers/openai_provider.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/providers/openai_provider.py)
3. The provider method receives only the `model_name` portion, routing it to the underlying SDK

## Summary

- **Strict format requirement**: Every model identifier must contain exactly one colon separating the provider key from the model name, validated in [`aisuite/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/client.py).
- **Lazy initialization**: Provider instances cache upon first use via `Client._resolve_provider`, avoiding unnecessary startup costs.
- **Convention-based loading**: `ProviderFactory` in [`aisuite/provider.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/provider.py) maps keys like `"openai"` to `OpenaiProvider` classes using predictable naming conventions.
- **Uniform interface**: The model name passes unchanged to provider-specific implementations, enabling aisuite to maintain a provider-agnostic API surface.
- **Clear error messaging**: Invalid formats or unsupported providers trigger immediate `ValueError` exceptions with actionable feedback.

## Frequently Asked Questions

### What happens if I forget the colon in the model identifier?

aisuite raises a `ValueError` with the message `"Invalid model format. Expected 'provider:model', got '{your_input}'"`. This validation occurs in `Client._resolve_provider` before any provider initialization begins, ensuring you receive immediate feedback rather than a failed API call.

### How does aisuite handle unsupported providers?

After splitting the identifier, aisuite compares the `provider_key` against the set returned by `ProviderFactory.get_supported_providers()`. If the key is missing, the library raises a `ValueError` listing all supported providers, helping you identify typos or configuration issues instantly.

### Can I use custom provider keys that don't match the built-in naming convention?

The current implementation in [`aisuite/provider.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/provider.py) requires provider keys to follow the convention where the module name is `{provider_key}_provider` and the class name is `{Provider_key}Provider`. To use custom keys, you must create a module in `aisuite/providers/` that follows this pattern, as `ProviderFactory.create_provider` relies on this naming convention for dynamic imports.

### Is the provider instance created every time I make a request?

No. The `Client` class implements **lazy caching**—the provider instance is created only on the first request requiring that specific provider, then stored in `self.client.providers`. Subsequent calls reuse the cached instance, avoiding repeated module imports and SDK initializations.