# `PtcRunner.LLM.Registry`
[🔗](https://github.com/andreasronge/ptc_runner/blob/main/lib/ptc_runner/llm/registry.ex#L1)

Behaviour and unified interface for model resolution.

Resolves model aliases (e.g., "haiku") to full provider:model strings
(e.g., "openrouter:anthropic/claude-haiku-4.5"). This enables simple
model references in SubAgent.run:

    # Instead of building callbacks manually:
    {:ok, step} = SubAgent.run(agent, llm: "haiku")
    {:ok, step} = SubAgent.run(agent, llm: "bedrock:haiku")

## Configuration

The default implementation uses built-in aliases. To swap registries:

    config :ptc_runner, :model_registry, MyApp.ModelRegistry

Or configure the default provider:

    config :ptc_runner, :default_provider, :bedrock

## Custom Registry

Implement the behaviour to add custom aliases:

    defmodule MyApp.ModelRegistry do
      @behaviour PtcRunner.LLM.Registry

      @impl true
      def resolve("fast"), do: {:ok, "anthropic:claude-haiku-4-5-20251001"}
      def resolve("smart"), do: {:ok, "anthropic:claude-sonnet-4-5-20250929"}
      def resolve(name), do: PtcRunner.LLM.DefaultRegistry.resolve(name)

      @impl true
      def resolve!(name) do
        case resolve(name) do
          {:ok, model_id} -> model_id
          {:error, reason} -> raise ArgumentError, reason
        end
      end

      @impl true
      def validate(model_string) do
        case resolve(model_string) do
          {:ok, _} -> :ok
          {:error, reason} -> {:error, reason}
        end
      end

      # Delegate remaining callbacks to DefaultRegistry
      @impl true
      defdelegate default_model(), to: PtcRunner.LLM.DefaultRegistry
      @impl true
      defdelegate default_provider(), to: PtcRunner.LLM.DefaultRegistry
      @impl true
      defdelegate aliases(), to: PtcRunner.LLM.DefaultRegistry
      @impl true
      defdelegate list_models(), to: PtcRunner.LLM.DefaultRegistry
      @impl true
      defdelegate preset_models(provider), to: PtcRunner.LLM.DefaultRegistry
      @impl true
      defdelegate available_providers(), to: PtcRunner.LLM.DefaultRegistry
      @impl true
      defdelegate provider_from_model(model), to: PtcRunner.LLM.DefaultRegistry
    end

# `aliases`

```elixir
@callback aliases() :: [String.t()]
```

Get list of all alias names.

# `available_providers`

```elixir
@callback available_providers() :: [atom()]
```

Get list of available providers based on environment.

# `default_model`

```elixir
@callback default_model() :: String.t()
```

Get the default model using the default provider.

# `default_provider`

```elixir
@callback default_provider() :: atom()
```

Get the default provider atom.

# `list_models`

```elixir
@callback list_models() :: [map()]
```

List all models with availability status.

# `preset_models`

```elixir
@callback preset_models(atom()) :: %{required(String.t()) =&gt; String.t()}
```

Get model presets for a provider as alias -> model_id map.

# `provider_from_model`

```elixir
@callback provider_from_model(String.t()) :: atom() | nil
```

Extract the provider atom from a model string.

# `resolve`

```elixir
@callback resolve(String.t()) :: {:ok, String.t()} | {:error, String.t()}
```

Resolve a model name or alias to a full provider:model string.

## Formats

- `"alias"` - Resolves using default provider (e.g., "haiku" -> "openrouter:...")
- `"provider:alias"` - Resolves with specific provider (e.g., "bedrock:haiku")
- `"provider:full/model/id"` - Passes through as-is

## Examples

    iex> PtcRunner.LLM.Registry.resolve("haiku")
    {:ok, "openrouter:anthropic/claude-haiku-4.5"}

    iex> PtcRunner.LLM.Registry.resolve("bedrock:haiku")
    {:ok, "amazon_bedrock:anthropic.claude-haiku-4-5-20251001-v1:0"}

# `resolve!`

```elixir
@callback resolve!(String.t()) :: String.t()
```

Resolve a model name, raising on error.

# `validate`

```elixir
@callback validate(String.t()) :: :ok | {:error, String.t()}
```

Validate a model string format.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
