# `Agentic.LLM.Canonical`

Canonical model identity. The (provider, model_id) → canonical_id mapping
used to group pathways for the same underlying model weights across
providers (e.g. Anthropic direct, Claude Code CLI, OpenRouter all serve
`claude-sonnet-4`).

Resolution order for `for_model/2`:

  1. Static overrides (Codex aliases, Claude Code short aliases, z.ai GLM
     family — anything models.dev doesn't list)
  2. The cached models.dev catalog (~50 providers, refreshed every 24h)
  3. Pattern rules (e.g. strip OpenRouter org prefix)
  4. Fallback `"<provider>:<model_id>"` so the model is never canonical-less

## Persistence

The fetched models.dev snapshot is written to `~/.agentic/models_dev.json`
on every successful refresh so first boot is fast and we degrade cleanly
when models.dev is unreachable.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `for_model`

```elixir
@spec for_model(atom(), String.t()) :: String.t()
```

Resolve the canonical id for `(provider, model_id)`. Always returns a
non-nil binary; falls back to `"<provider>:<model_id>"` for unknowns.

# `info`

Inspect cache state — debugging/Mix-task use.

# `metadata_for`

```elixir
@spec metadata_for(atom(), String.t()) :: map() | nil
```

Return the rich models.dev metadata row for `(provider, model_id)` if
one is cached. `nil` otherwise.

# `refresh`

Force a refresh from models.dev.

# `start_link`

---

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