# How Ouroboros Defines Configuration Models Using Pydantic v2: Tiers, Credentials, and Economics

> Learn how Ouroboros defines configuration models with Pydantic v2. Explore immutable data models for LLM selection, cost tiers, provider credentials, and economics, ensuring strict validation and hashability.

- Repository: [Q00/ouroboros](https://github.com/Q00/ouroboros)
- Tags: how-to-guide
- Published: 2026-03-14

---

**Ouroboros stores all runtime settings in immutable, frozen Pydantic v2 data models located in [`src/ouroboros/config/models.py`](https://github.com/Q00/ouroboros/blob/main/src/ouroboros/config/models.py), using a hierarchical structure that separates LLM selection, cost tiers, provider credentials, and economic policies into strictly validated, hashable configuration objects.**

The Q00/ouroboros repository leverages **Pydantic v2** to create a type-safe, declarative configuration system that governs how the orchestrator selects models, manages API keys, and balances cost against capability. Understanding these Configuration Models defined using Pydantic v2 in Ouroboros is essential for customizing tier-based routing, credential management, and economic thresholds that drive automatic escalation logic.

## The Configuration Model Hierarchy

All configuration models inherit from **`BaseModel`** with **`frozen=True`**, ensuring thread-safe, immutable objects that validate on instantiation. The source code in [`src/ouroboros/config/models.py`](https://github.com/Q00/ouroboros/blob/main/src/ouroboros/config/models.py) (lines 28-124) defines six primary models that compose the complete runtime configuration.

### ModelConfig: LLM Selection

The `ModelConfig` class (lines 28-38) represents a single LLM endpoint:

```python
class ModelConfig(BaseModel, frozen=True):
    provider: str  # "openai", "anthropic", "google", etc.

    model: str     # Specific model identifier

```

This model pairs a provider name with a model identifier, enabling the runtime to look up the correct API credentials and endpoint.

### TierConfig: Cost and Capability Tiers

The `TierConfig` class (lines 40-62) defines a cost tier containing multiple models:

```python
class TierConfig(BaseModel, frozen=True):
    cost_factor: float
    intelligence_range: tuple[int, int]
    models: list[ModelConfig]
    use_cases: list[str]

```

Each tier specifies a **cost factor** (relative multiplier), an **intelligence range** (min/max capability score), and a list of `ModelConfig` objects available within that tier. The model includes `@field_validator` methods to ensure `min ≤ max` in the intelligence range.

### ProviderCredentials and CredentialsConfig: API Key Management

API keys are encapsulated in `ProviderCredentials` (lines 65-74):

```python
class ProviderCredentials(BaseModel, frozen=True):
    api_key: str
    base_url: str | None = None

```

The `CredentialsConfig` class (lines 77-85) aggregates these into a provider-indexed mapping:

```python
class CredentialsConfig(BaseModel, frozen=True):
    providers: dict[str, ProviderCredentials]

```

This structure allows Ouroboros to resolve `api_key` values using the same provider strings referenced in `ModelConfig.provider`.

### EconomicsConfig: Policy and Escalation

The `EconomicsConfig` class (lines 87-100) ties the system together:

```python
class EconomicsConfig(BaseModel, frozen=True):
    default_tier: str  # "frugal", "standard", or "frontier"

    tiers: dict[str, TierConfig]
    escalation_threshold: int
    downgrade_success_streak: int

```

This model stores the **default tier** for initial requests, a dictionary mapping tier names to `TierConfig` objects, and thresholds for automatic tier escalation (on failure) and downgrade (on success streaks).

### OuroborosConfig: Top-Level Composition

The `OuroborosConfig` class embeds `EconomicsConfig`, clarification settings, execution parameters, and orchestrator configuration into a single, validated object that serves as the single source of truth for the entire runtime.

## Tier and Credentials Flow

The relationship between tiers, models, and credentials follows a strict lookup chain implemented in the model definitions:

1. **EconomicsConfig** references a **`dict[str, TierConfig]`** (`tiers`). Each `TierConfig` contains a **list of `ModelConfig`** objects enumerating the LLMs available within that cost band.
2. **CredentialsConfig** maintains a **`dict[str, ProviderCredentials]`** keyed by provider name. The runtime uses `ModelConfig.provider` to index into this dictionary and retrieve the appropriate `api_key` and optional `base_url`.
3. The **default tier** (`default_tier`) specifies which tier's models to select when no explicit tier is requested by the user or orchestrator.
4. **Escalation** (`escalation_threshold`) and **downgrade** (`downgrade_success_streak`) thresholds drive automatic tier-up and tier-down logic based on task success and failure metrics.

## Implementation Details: Validation and Immutability

The Ouroboros Configuration Models defined using Pydantic v2 enforce data integrity through several Pydantic v2-specific mechanisms:

- **Immutable models** – Every configuration class uses `class ModelConfig(BaseModel, frozen=True)`, making instances hashable and thread-safe for sharing across async workers.
- **Typed literals** – Tier names use `Literal["frugal", "standard", "frontier"]` type hints, providing IDE autocomplete and runtime validation that restricts tier identifiers to supported levels.
- **Custom validators** – `TierConfig.validate_intelligence_range` guarantees that the minimum intelligence score does not exceed the maximum, while `DriftConfig.validate_critical_threshold` ensures critical thresholds are not set lower than warning thresholds.
- **Helper constructors** – `get_default_config()` (lines 88-124) builds a fully populated `OuroborosConfig` with a sensible three-tier layout (frugal, standard, frontier) pre-populated with default `ModelConfig` entries. The `get_default_credentials()` function returns a template `CredentialsConfig` with placeholder API keys for all supported providers.

## Working with Configuration Models

### Loading Default Configuration

To instantiate the pre-configured tier hierarchy:

```python
from ouroboros.config.models import get_default_config

config = get_default_config()
print(config.economics.default_tier)          # → "frugal"

print(config.economics.tiers["standard"].models)  # list of ModelConfig objects

```

### Accessing Tier Model Lists

Iterate through available models for a specific tier:

```python
standard_tier = config.economics.tiers["standard"]
for model_cfg in standard_tier.models:
    print(f"{model_cfg.provider}:{model_cfg.model}")

# Output:

# openai:gpt-4o

# anthropic:claude-sonnet-4-6

# google:gemini-2.5-pro

```

### Resolving Provider Credentials

Retrieve API keys using the provider index:

```python
from ouroboros.config.models import get_default_credentials

creds = get_default_credentials()
provider = standard_tier.models[0].provider   # "openai"

api_key = creds.providers[provider].api_key   # → "YOUR_OPENAI_API_KEY"

base_url = creds.providers[provider].base_url # → None or custom endpoint

```

### Creating Custom Tier Configurations

Override specific tiers while maintaining validation:

```python
from ouroboros.config.models import (
    OuroborosConfig, TierConfig, ModelConfig, get_default_config
)

custom = get_default_config()
custom.economics.tiers["frontier"] = TierConfig(
    cost_factor=50,
    intelligence_range=(19, 20),
    models=[
        ModelConfig(provider="openai", model="gpt-4o-mini"),
        ModelConfig(provider="anthropic", model="claude-3-5-haiku")
    ],
    use_cases=["advanced_consensus"]
)

```

## Summary

- Ouroboros Configuration Models defined using Pydantic v2 reside in [`src/ouroboros/config/models.py`](https://github.com/Q00/ouroboros/blob/main/src/ouroboros/config/models.py) and enforce strict validation through frozen `BaseModel` classes.
- The hierarchy consists of `ModelConfig` (LLM selection), `TierConfig` (cost/capability grouping), `ProviderCredentials` (API keys), `CredentialsConfig` (provider mapping), and `EconomicsConfig` (policy orchestration).
- All models use `frozen=True` for immutability and thread safety, with custom `@field_validator` decorators ensuring logical constraints like ordered intelligence ranges.
- The runtime resolves credentials by matching `ModelConfig.provider` strings against keys in `CredentialsConfig.providers`.
- Default configurations are generated via `get_default_config()` (lines 88-124), which populates three standard tiers with pre-selected models.

## Frequently Asked Questions

### What file contains the Pydantic v2 configuration models in Ouroboros?

The core schema definitions are located in [`src/ouroboros/config/models.py`](https://github.com/Q00/ouroboros/blob/main/src/ouroboros/config/models.py). This file contains all `BaseModel` subclasses including `ModelConfig`, `TierConfig`, `ProviderCredentials`, `CredentialsConfig`, and `EconomicsConfig`, along with the `get_default_config()` helper function (lines 88-124).

### Why are Ouroboros configuration models frozen?

All configuration classes use `frozen=True` to ensure immutability after instantiation. This makes the objects hashable (usable as dictionary keys or in sets) and thread-safe, allowing the runtime to share configuration instances across multiple async workers without risk of mutation or race conditions.

### How does Ouroboros validate that intelligence ranges are logical?

The `TierConfig` class (lines 40-62) includes a `@field_validator` method named `validate_intelligence_range` that executes during model instantiation. This validator ensures that the minimum intelligence value is less than or equal to the maximum value, raising a `ValidationError` if the range is inverted.

### Can I use custom base URLs for API providers in Ouroboros?

Yes. The `ProviderCredentials` model (lines 65-74) includes an optional `base_url` field of type `str | None`. When provided, this URL overrides the default API endpoint for that provider, enabling compatibility with proxy servers, regional endpoints, or self-hosted model gateways.