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

Ouroboros stores all runtime settings in immutable, frozen Pydantic v2 data models located in 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 (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:

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:

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):

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:

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:

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:

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:

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:

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:

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 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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →