# Models and harnesses
When you set a codon's `model` field in hank.json, that one spelling decides several things at once: which model actually runs, which in-process runner (the *harness*) sends the work, which credential pays for it, and what it costs. This page is the lookup surface for those decisions. It lists the 29 spellings verified against hankweave 0.10.0 with their routes, prices, and capabilities, explains the two harnesses and the dispatch rule that picks between them, walks through each spelling form you can write, and shows how to check a model locally before a run spends money. The grammar and failure formats behind all of this live on the linked reference pages; this page stays with the verified data and the practical consequences.
## Model spellings and verification
A codon is one sealed agent task, and its `model` spelling determines the route shown in the table below. The 29 spellings come from the shipped registry and the Pi catalog, and they cover eight tiers: Frontier reasoning (5), Workhorse (4), Fast and cheap (7), Open-weight & third-party via Baseten (4), Open-weight & third-party via OpenRouter (4), Subscription-backed (2), Amazon Bedrock (2), and Code (1).
Two catalogs sit behind these rows. Hankweave's shipped registry contains 6,472 models across 188 providers; the embedded Pi coding agent's catalog contains 1,267 models across 39 providers. The registry supplies model and price data when it has the resolved provider/id; Pi's catalog supplies fallback data and the startup gate for Pi-routed models. A model in neither source cannot be selected. The curated table below selects the spellings, prices, context limits, and harness routes checked at 0.10.0 rather than listing every model in either catalog.
Every row was exercised by the validation campaign, and the summary line records the outcome:
```text
29 slugs · VALID 22 · VALID-UNAUTHENTICATED-HERE 7 · SELF-TEST-FAILED 0 · INVALID 0 · numbers from registry 26 / pi-catalog 3 / none 0
```
The report covers 29 spellings: 22 `VALID`, 7 `VALID-UNAUTHENTICATED-HERE`, 0 `SELF-TEST-FAILED`, and 0 `INVALID`. `VALID-UNAUTHENTICATED-HERE` means the runtime accepted the spelling but the validation environment lacked that provider's credential. In the table, plain `✓` means `VALID`; `✓ spelling (no key in the build env)` means `VALID-UNAUTHENTICATED-HERE`. The latter is a spelling check, not a full pass. A normal startup run with a missing key instead reports a failing self-test and `Server startup failed`; it does not produce that table label.
These verdicts establish local spelling, catalog, and harness checks, not a successful generation against every provider. Credential presence does not prove validity, current model access, quota, or live availability. `GOOD TO RUN!` is not evidence that a model has answered a request. Use an explicitly authorized live check when that assurance is needed; it can be billable.
The validation record also includes resolved identities such as `haiku` → `anthropic/claude-haiku-4-5` and `gpt-5.6-xhigh` → `openai/gpt-5.6-sol` with `xhigh`. The curated table has no bare `kimi-k3` row: its Kimi rows are `kimi-k2.7-code` in Code and `pi/baseten/moonshotai/Kimi-K3` in Baseten. Separately, bare `kimi-k3` resolves through preferred-provider inference to the shipped registry identity `moonshotai/kimi-k3`, the current identity and newer than `kimi-k2.7-code`; that route goes through OpenRouter. The dictionary-only shortcut `gpt-5.6` – documented by model resolution but not emitted as its own generated-table row – is accepted and expands to `gpt-5.6-sol`.
Record both the requested spelling and the resolved provider/model identity. Registry resolution can accept a fuzzy match, so a successful lookup need not name the exact model you intended; inspect the resolved identity before freezing the hank. A matching Hankweave version string alone does not prove that a development checkout, npm artifact, and this documentation bundle contain identical catalogs.
The full table follows. Read `harness` for the resolved runner and `verified` for the runtime verdict; the remaining columns are prices, capacities, and capabilities per route.
**Pricing provenance:** this table was generated on 2026-09-05 from the artifact's shipped `models-dev-data.json` snapshot dated 2026-08-17, with Pi-catalog fallback for models only Pi knows. The captured totals are 26 registry rows and 3 Pi-catalog rows. Prices are catalog estimates for the named routes, not provider invoices or live price quotes. A `$0` catalog entry does not establish free service; see [Prices and your budget](#prices-and-your-budget), including the separate `xhigh` multiplier.
| tier | model | spelling in hank.json | harness | provider | base in $/1M | base out $/1M | base cache-read $/1M | context | max out | reasoning | effort | inputs | knowledge | verified |
| ---------------------------------------- | ------------------------------ | ----------------------------------------------------- | ---------------- | -------------- | ------------ | ------------- | -------------------- | ------- | ------- | --------- | ------- | -------------------------- | ---------- | ------------------------------------ |
| Frontier reasoning | Claude Opus 5 | `opus` | claude-agent-sdk | anthropic | $5 | $25 | $0.5 | 1000k | 128k | yes | default | text+image+pdf | 2026-05 | ✓ |
| Frontier reasoning | Claude Fable 5 | `claude-fable-5` | claude-agent-sdk | anthropic | $10 | $50 | $1 | 1000k | 128k | yes | default | text+image+pdf | — | ✓ |
| Frontier reasoning | GPT-5.6 Sol | `gpt-5.6-sol` | pi | openai | $5 | $30 | $0.5 | 1050k | 128k | yes | default | text+image+pdf | 2026-02-16 | ✓ |
| Frontier reasoning | DeepSeek V4 Pro | `deepseek-v4-pro` | pi | deepseek | $0.435 | $0.87 | $0.003625 | 1000k | 384k | yes | default | text | — | ✓ |
| Frontier reasoning | GPT-5.6 Sol (xhigh) | `gpt-5.6-xhigh` | pi | openai | $5 | $30 | $0.5 | 1050k | 128k | yes | xhigh | text+image+pdf | 2026-02-16 | ✓ |
| Workhorse | Claude Sonnet 5 | `sonnet` | claude-agent-sdk | anthropic | $2 | $10 | $0.2 | 1000k | 128k | yes | default | text+image+pdf | 2026-01-31 | ✓ |
| Workhorse | GPT-5.6 Terra | `gpt-5.6-terra` | pi | openai | $2 | $12 | $0.2 | 1050k | 128k | yes | default | text+image+pdf | 2026-02-16 | ✓ |
| Workhorse | Gemini 3.7 Flash | `gemini-3.7-flash` | pi | google | $0.75 | $3.75 | $0.075 | 1049k | 66k | yes | default | text+image+video+audio+pdf | 2026-03 | ✓ |
| Workhorse | GLM-5.3 | `pi/zai/glm-5.3` | pi | zai | $0 | $0 | $0 | 1000k | 131k | yes | default | text | — | ✓ |
| Fast and cheap | Claude Haiku 4.5 (latest) | `haiku` | claude-agent-sdk | anthropic | $1 | $5 | $0.1 | 200k | 64k | yes | default | text+image+pdf | 2025-02-28 | ✓ |
| Fast and cheap | GPT-5.6 Luna | `gpt-5.6-luna` | pi | openai | $0.2 | $1.2 | $0.02 | 1050k | 128k | yes | default | text+image+pdf | 2026-02-16 | ✓ |
| Fast and cheap | GPT-5.4 mini | `gpt-5.4-mini` | pi | openai | $0.75 | $4.5 | $0.075 | 400k | 128k | yes | default | text+image | 2025-08-31 | ✓ |
| Fast and cheap | GPT-5.4 nano | `gpt-5.4-nano` | pi | openai | $0.2 | $1.25 | $0.02 | 400k | 128k | yes | default | text+image | 2025-08-31 | ✓ |
| Fast and cheap | Gemini 2.5 Flash | `gemini-2.5-flash` | pi | google | $0.3 | $2.5 | $0.03 | 1049k | 66k | yes | default | text+image+audio+video+pdf | 2025-01 | ✓ |
| Fast and cheap | Gemini 3.5 Flash Lite | `gemini-3.5-flash-lite` | pi | google | $0.3 | $2.5 | $0.03 | 1049k | 66k | yes | default | text+image+video+audio+pdf | 2026-03 | ✓ |
| Fast and cheap | DeepSeek V4 Flash | `deepseek-v4-flash` | pi | deepseek | $0.14 | $0.28 | $0.0028 | 1000k | 384k | yes | default | text | 2025-05 | ✓ |
| Open-weight & third-party via Baseten | Deepseek V4 Pro | `pi/baseten/deepseek-ai/DeepSeek-V4-Pro` | pi | baseten | $1.74 | $3.48 | $0.145 | 262k | 262k | yes | default | text | 2025-05 | ✓ |
| Open-weight & third-party via Baseten | Deepseek V4 Flash 0731 | `pi/baseten/deepseek-ai/DeepSeek-V4-Flash-0731` | pi | baseten | $0.13 | $0.26 | $0.028 | 1049k | 1049k | yes | default | text | 2025-05 | ✓ |
| Open-weight & third-party via Baseten | Kimi K3 | `pi/baseten/moonshotai/Kimi-K3` | pi | baseten | $3 | $15 | — | 1049k | 262k | yes | default | text+image | — | ✓ |
| Open-weight & third-party via Baseten | Nemotron Ultra | `pi/baseten/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B` | pi | baseten | $0.6 | $2.4 | $0.12 | 203k | 203k | yes | default | text | — | ✓ |
| Open-weight & third-party via OpenRouter | Qwen3.8 Max | `openrouter/qwen/qwen3.8-max` | pi | openrouter | $2 | $6 | $0.25 | 1000k | 131k | yes | default | text+image+video | — | ✓ spelling (no key in the build env) |
| Open-weight & third-party via OpenRouter | Muse Glimmer 30B | `openrouter/meta/muse-glimmer-30b` | pi | openrouter | $0.35 | $1.5 | $0.04 | 131k | 131k | yes | default | text+image | 2026-01-04 | ✓ spelling (no key in the build env) |
| Open-weight & third-party via OpenRouter | Nemotron 3.5 Lightning 30B A3B | `openrouter/nvidia/nemotron-3.5-lightning` | pi | openrouter | $0.08 | $0.2 | $0.04 | 1000k | 131k | yes | default | text | — | ✓ spelling (no key in the build env) |
| Open-weight & third-party via OpenRouter | Grok 4.6 | `openrouter/x-ai/grok-4.6` | pi | openrouter | $2 | $6 | $0.5 | 500k | 500k | yes | default | text+image+pdf | 2026-02-01 | ✓ spelling (no key in the build env) |
| Subscription-backed | GPT-5.6 Luna | `pi/openai-codex/gpt-5.6-luna` | pi | openai-codex | $0.2 | $1.2 | $0.02 | 272k | 128k | yes | default | text+image | — | ✓ |
| Subscription-backed | GPT-5.6 Terra | `pi/openai-codex/gpt-5.6-terra` | pi | openai-codex | $2 | $12 | $0.2 | 272k | 128k | yes | default | text+image | — | ✓ |
| Amazon Bedrock | Claude Opus 5 (US) | `pi/amazon-bedrock/us.anthropic.claude-opus-5` | pi | amazon-bedrock | $5 | $25 | $0.5 | 1000k | 128k | yes | default | text+image+pdf | 2026-05 | ✓ spelling (no key in the build env) |
| Amazon Bedrock | Claude Sonnet 5 | `pi/amazon-bedrock/anthropic.claude-sonnet-5` | pi | amazon-bedrock | $2 | $10 | $0.2 | 1000k | 128k | yes | default | text+image+pdf | 2026-01-31 | ✓ spelling (no key in the build env) |
| Code | Kimi K2.7 Code | `kimi-k2.7-code` | pi | moonshotai | $0.95 | $4 | $0.19 | 262k | 262k | yes | default | text+image+video | 2025-01 | ✓ spelling (no key in the build env) |
[Model resolution](/reference/model-resolution) owns the resolution grammar; [authentication and models](/operate/authentication-and-models) owns authentication; [environment variables](/reference/environment-variables) owns the complete key catalog.
> **Pitfall:** The registry and Pi's catalog can drift. `glm-5.3` is servable by Pi while absent from hankweave's registry, so its numbers come from Pi's catalog and show $0 per 1M tokens. Conversely, bare `grok-4.6` can resolve in the registry to `abacus` and then fail Pi's startup catalog check. Trust the preflight result rather than either catalog alone.
## Two harnesses, one dispatch rule
The `harness` column above names the runner each row resolves to. A harness is the in-process runner that sends a codon to its model, and hankweave has exactly two: the Claude Agent SDK harness (`claude-agent-sdk`) and the embedded Pi harness (`pi`).
`selectHarness` computes the route at dispatch time; the choice is late-bound and is not persisted. A model routes to `claude-agent-sdk` when its real identity is first-party `providerId === "anthropic"`, or when `providerId === "amazon-bedrock"` and its model id is an Anthropic-family id (`anthropic.claude-…` or `.anthropic.claude-…`). Everything else uses `pi`. In the table, the four Anthropic rows use the first harness; the other 25 use the embedded Pi harness.
The single routing rule and `harnessOverride` semantics belong to [model resolution](/reference/model-resolution#how-harness-routing-is-selected) and [authentication and models](/operate/authentication-and-models#from-a-model-string-to-a-running-codon). An explicit `pi/...` spelling forces `harnessOverride: "pi"`, so the `pi/amazon-bedrock/...` rows stay on Pi even though their target ids contain `anthropic`. The runtime derives Bedrock mode from that provider/model identity and sets `CLAUDE_CODE_USE_BEDROCK=1` plus its enumerated AWS variables for the SDK child; ambient `CLAUDE_CODE_*` variables still pass through, but a codon `env` block cannot set that Bedrock variable or the AWS list. `SUPPORTED_CODON_PROVIDER_IDS` and the unsupported-model error belong to [model resolution §6](/reference/model-resolution#where-model-validation-fails).
Here, Pi means the embedded coding agent, not a separate harness installation: it runs in-process inside hankweave. Its catalog is the static vendored snapshot bundled in the artifact plus the user's `~/.pi/agent/models.json`; the only per-user Pi state is `~/.pi/agent/`, including `auth.json` from `pi login`. Both harnesses emit Claude-compatible line-delimited JSON (JSONL), so one log format covers both. Log paths, names, and translation details belong to [observing and debugging](/operate/observe-and-debug), [the execution directory](/reference/execution-directory), and [runtime architecture](/contribute/runtime-architecture).
The table's `inputs` column describes catalog model capabilities, not a promise that either harness exposes every modality as a tool. Check the combination of model, harness, and host: the model must accept the input, the harness must deliver it in a supported form, and the host must provide the needed programs and access. Shell bytes from an image file are not native image content. Tool inventories are route-specific; an agent workspace is not a sandbox, and disabling harness permission prompts cannot override host restrictions. See [prompt capability and permission guidance](/author/prompts#explain-the-workspace-before-assigning-work).
The diagram below traces one spelling through the whole path: shortcut expansion, registry resolution, the harness split, the key plane, and the startup catalog gate.
*Harness dispatch from a spelling to a runner, key plane, and startup gate.*
```text
harness dispatch:
model: "" in hank.json
|
v
shortcut expansion
|
v
registry resolution
exact -> inferred provider -> fuzzy
|
v
selectHarness
/ \
providerId=anthropic everything else
or amazon-bedrock + -> embedded Pi harness
Anthropic-family model id
-> Claude Agent SDK
(runtime sets CLAUDE_CODE_USE_BEDROCK=1 for Bedrock)
explicit pi//
(harnessOverride: "pi")
-> embedded Pi harness
-> pi target /
aliases zhipuai/z-ai -> zai;
moonshot/moonshot-ai -> moonshotai;
moonshotai -> openrouter/moonshotai/
|
+--> model_catalog gate
(same lookupPiModel at startup)
prefix rewrites before resolution:
opencode// -> pi//
openrouter// -> pi/openrouter//
key plane:
ANTHROPIC_API_KEY · GEMINI_API_KEY · OPENAI_API_KEY ·
OPENROUTER_API_KEY · ZAI_API_KEY -> hankweave runtime keys
every other provider -> Pi's own config (env / ~/.pi/agent,
e.g. BASETEN_API_KEY, pi login)
effort suffix:
-high/-xhigh stripped before dispatch -> thinkingLevel
```
A table row's `claude-agent-sdk` or `pi` value is the resolved dispatch harness; the `opus` row and the `pi/zai/glm-5.3` row show the two values.
[Model resolution](/reference/model-resolution#how-harness-routing-is-selected) owns routing and `harnessOverride`; [authentication and models](/operate/authentication-and-models#from-a-model-string-to-a-running-codon) explains the route decision.
> **VersionNote:** Since 0.8.0, the subprocess shims are gone: exactly two in-process harnesses remain. Legacy `opencode/...` spellings are rewritten to `pi/...`; shim history belongs to [upgrading](/start/upgrading).
## How to spell a model
The `model` field accepts six forms, and the choice between them is a choice about behavior. Choose a shortcut when the latest family member should follow automatically; choose a bare id when preferred-provider inference is wanted; choose `pi/...` to force Pi, `openrouter/...` for an organization/model route, or an effort suffix to change reasoning effort. Each form below states its rule, shows a row from the table that exercises it, and points to the owning reference.
**Shortcut form**
A shortcut resolves to the latest non-dated model selected for its family; `gpt-5.6` expands to `gpt-5.6-sol`.
The table exercises `opus`, `sonnet`, and `haiku`. Their intermediate expansions are `opus` → `claude-opus`, `sonnet` → `claude-sonnet`, and `haiku` → `claude-haiku`; registry resolution then selects the current identity, such as `anthropic/claude-haiku-4-5` for the table's `haiku` row. `gpt-5.6` is a dictionary-only shortcut and has no generated table row.
Qualification does not bypass shortcut expansion, and an effort suffix is preserved while the base is expanded: `anthropic/sonnet` → `anthropic/claude-sonnet`, `openai/gpt-5.6` → `openai/gpt-5.6-sol`, and `openai/gpt-5.6-xhigh` → `openai/gpt-5.6-sol-xhigh`. After that application, the expanded result is not recursively expanded again. Shortcuts track the latest non-dated model. Dated or snapshot ids are the pinning choice; a pinned spelling should be checked again after an upgrade.
The generated table's `opus` row supplies a shortcut-form example. Its neighboring columns show the resolved identity, route, and price data for that row.
Shortcuts are expanded by [model resolution](/reference/model-resolution#shortcut-expansion); [upgrading](/start/upgrading) carries the re-check path.
**Bare registry id**
A bare id resolves through the shipped registry when its provider can be inferred.
Provider inference uses `claude` → anthropic, `gemini` → google, `deepseek` → deepseek, `glm-` → zhipuai, `kimi` → moonshotai, and `gpt-`, `o1-`, or `o3-` → openai.
The table exercises bare ids such as `deepseek-v4-pro` and `gemini-3.7-flash`. Resolution order and fuzzy behavior belong to [model resolution §3](/reference/model-resolution#how-a-model-string-resolves).
The generated table's `deepseek-v4-pro` row supplies a bare-id example.
Resolution order is defined by [model resolution](/reference/model-resolution#how-a-model-string-resolves).
**Provider-qualified form**
A provider-qualified id names the provider before the model id and is a dictionary-only spelling form on this page.
The supported shape is `provider/model`; provider-qualified Anthropic forms such as `anthropic/claude-…` do not appear as generated table rows. The separate `openrouter//` form has an organization segment and is listed below.
Qualification does not bypass shortcut expansion; `applyModelShortcuts` applies the shortcut to the segment after the first slash. The grammar is defined in [model resolution](/reference/model-resolution#the-codon-model-field).
**`pi//` passthrough**
An explicit `pi//` spelling selects the embedded Pi harness and passes the provider/model target to Pi.
Validation sets `harnessOverride: "pi"`; capability data is inherited from the resolved Pi model. Baseten, `zai`, and `openai-codex` rows exercise this form.
The written provider/model split in an explicit `pi//` spelling is trusted verbatim as the dispatched identity; registry lookup on the expanded form contributes capabilities and cost only. Provider aliases resolve `zhipuai` and `z-ai` to `zai`; `moonshot` and `moonshot-ai` resolve to `moonshotai`, and the Moonshot first-party route is sent through `openrouter/moonshotai/` because hankweave carries no Moonshot first-party API key. That route is distinct from the `pi/baseten/moonshotai/Kimi-K3` table row: the latter names Baseten as its provider and follows Pi's credential lookup. The `kimi-k2.7-code` row is the OpenRouter-routed Kimi spelling and requires `OPENROUTER_API_KEY`. The Zai alias dates from 0.7.4; the Kimi OpenRouter route dates from 0.7.5.
The generated table's `pi/zai/glm-5.3` row supplies a complete passthrough spelling.
Passthrough and aliases are defined by [model resolution](/reference/model-resolution#handling-aliases-and-special-cases).
**`openrouter//` form**
An `openrouter//` spelling names an OpenRouter route and is rewritten to the Pi provider path.
The rewrite is `openrouter//` → `pi/openrouter//`; the resulting route uses the embedded Pi harness.
This form requires the OpenRouter key plane below. The legacy `opencode//` rewrite to `pi//` dates from 0.8.0 and belongs to [model resolution §5](/reference/model-resolution#legacy-stored-identities).
The generated table's `openrouter/x-ai/grok-4.6` row supplies an organization/model spelling.
The rewrite and its aliases are defined by [model resolution](/reference/model-resolution#handling-aliases-and-special-cases).
**Effort-suffixed form**
An effort suffix changes reasoning effort sent to the target while preserving the underlying model identity.
`-high` and `-xhigh` are stripped before dispatch and become `thinkingLevel`; an unsuffixed OpenAI model defaults to `high`. These effort variants are registered for reasoning-capable OpenAI models. The effort pricing multipliers are high ×1 and xhigh ×2.
`gpt-5.6-xhigh` resolves to `openai/gpt-5.6-sol` with `xhigh`. The suffix grammar and pricing rule belong to [model resolution §5](/reference/model-resolution#reasoning-effort-in-pi).
The generated table's `gpt-5.6-xhigh` row supplies the effort-suffixed spelling. Its displayed price is the base price; the registry accounts the auto-generated variant at 2× – see Prices and your budget.
The suffix rule is defined by [model resolution](/reference/model-resolution#reasoning-effort-in-pi); budget behavior belongs to [budgets](/concepts/budgets).
## Which key your route needs
Once a spelling resolves to a route, the route determines where the credential comes from. A route uses either a hankweave runtime key or Pi's own credential lookup, depending on the provider.
**Credential planes**
Hankweave enforces five provider keys and injects them at runtime: `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, `OPENAI_API_KEY`, `OPENROUTER_API_KEY`, and `ZAI_API_KEY`. Other providers use Pi's own configuration, including environment variables and `~/.pi/agent`.
Runtime-key injection and the full key catalog belong to [authentication and models](/operate/authentication-and-models#which-key-does-each-provider-need) and [environment variables](/reference/environment-variables#provider-api-keys). Baseten is not key-enforced: Pi resolves its credentials and reads `BASETEN_API_KEY` from the environment. The `deepseek` rows likewise use Pi's own configuration. The explicit `pi/amazon-bedrock/*` rows resolve AWS credentials through Pi; the Claude Agent SDK Bedrock route is selected by the provider/model identity above, and the runtime sets `CLAUDE_CODE_USE_BEDROCK=1` for that SDK child. Credential behavior is owned by [AWS Bedrock](/reference/aws-bedrock). Full prefixes and masking rules stay on the linked pages.
`kimi-k2.7-code` is the OpenRouter-routed Kimi row and therefore uses `OPENROUTER_API_KEY`. The separate `pi/baseten/moonshotai/Kimi-K3` row is a Baseten route and uses Pi's credential lookup, as other Baseten rows do.
**Google key spelling (0.8.0+).** Google-routed models use `GEMINI_API_KEY`; `GOOGLE_API_KEY` is not used. The [environment-variable reference](/reference/environment-variables#provider-api-keys) and [authentication guide](/operate/authentication-and-models#which-key-does-each-provider-need) own the full key contract; the generated table's Google rows show where this spelling applies.
**Codex subscription door (0.8.0+)**
The `pi/openai-codex/` route uses Pi's subscription authentication door.
The door is opened with `pi login`; its credential is stored at `~/.pi/agent/auth.json`. The table's two `openai-codex` rows exercise this route.
The metered-versus-subscription catalog difference belongs to [authentication and models §6](/operate/authentication-and-models#how-do-you-use-a-chatgpt-subscription). The two subscription-backed rows therefore have route-specific catalog data distinct from the metered OpenAI rows; the init fixture preserves the route's authentication instructions. The shipped scaffold includes these instructions:
```text
- The `pi/openai-codex/gpt-5.6-terra` codon runs on a **ChatGPT subscription** (no `OPENAI_API_KEY`): the OAuth credential is read from Pi's store at `~/.pi/agent/auth.json`. Put it there with `pi login` (choose "OpenAI (ChatGPT Plus/Pro)"). No subscription? Delete that codon, or switch its model to a keyed spelling like `gpt-5.5` with `OPENAI_API_KEY` set.
```
[Authentication and models §6](/operate/authentication-and-models#how-do-you-use-a-chatgpt-subscription) and [first run §2](/start/first-run#inspect-what---init-scaffolds).
**Same model, multiple routes.** A family has separate rows when its route changes context, price, or other route data. Seven route families appear: DeepSeek V4 Pro and V4 Flash each have first-party and Baseten routes; the Luna and Terra models each have a Codex route; Claude Opus 5 and Claude Sonnet 5 each have a `pi/amazon-bedrock` route; and `gpt-5.6-sol` has its `-xhigh` effort variant. The curated table has no bare `kimi-k3` row, but bare `kimi-k3` resolves through `kimi` → `moonshotai` provider inference to the shipped registry identity `moonshotai/kimi-k3`, newer than `kimi-k2.7-code`, and routes through OpenRouter. The table's Kimi rows are the OpenRouter-routed `kimi-k2.7-code` and the Baseten `pi/baseten/moonshotai/Kimi-K3` route. Prices and context differ between the DeepSeek twins. The registry-backed Luna/Terra rows and the Pi-catalog Codex rows share prices ($0.2/$1.2 and $2/$12), but their table data differs: the registry rows show 1050k context, `text+image+pdf` inputs, and knowledge date `2026-02-16`, while the Pi-catalog rows show 272k context, `text+image` inputs, and no knowledge date. Those inputs and knowledge values are source columns, not a claim about verified capability differences. The Claude and Bedrock twins share numbers but differ in harness and key plane: AWS versus `ANTHROPIC_API_KEY`. The Sol/xhigh pair keeps the same base id, while the registry accounts for `-xhigh` at 2×. Choose the row whose spelling matches the route you will run, and use that row's context and price columns for planning. See [model resolution](/reference/model-resolution) and [budgets](/concepts/budgets) for the owning contracts.
## Checking a model before you spend
Two checks stand between a spelling and a paid run: the startup catalog gate, which runs on every launch, and the `--validate` command, which you can run yourself at any time. This section covers both, then shows what a failure looks like on the console.
**Startup catalog check (0.10.0+)**
The `model_catalog` preflight is the startup check that confirms a Pi-routed model can be found in Pi's catalog.
The check occurs at every startup against the fixed snapshot shipped with the artifact and `~/.pi/agent/models.json`; the startup gate uses the same catalog lookup. A catalog miss is deterministic: the same shipped inputs produce the same miss.
The table's `VALID`, `VALID-UNAUTHENTICATED-HERE`, `SELF-TEST-FAILED`, and `INVALID` results are the consumer-visible validation categories. Failure formats and the unsupported-model error belong to [model resolution](/reference/model-resolution#where-model-validation-fails) and [authentication and models](/operate/authentication-and-models#when-the-registry-knows-a-model-pi-cannot-serve). A bare `grok-4.6` probe resolves to the provider identity `abacus` and is rejected by Pi's catalog; `openrouter/x-ai/grok-4.6` is the valid re-spelling.
The generated validation output supplies the verdict examples; its `VALID` and `VALID-UNAUTHENTICATED-HERE` labels correspond to the table's verification column. See [model resolution](/reference/model-resolution#where-model-validation-fails) and [authentication and models](/operate/authentication-and-models#when-the-registry-knows-a-model-pi-cannot-serve) for failure formats.
**Local validation command**
`--validate` checks configuration without running the hank – the workflow file.
```sh
bunx hankweave@0.10.0 hank.json data/ --validate
```
At 0.10.0, `--validate` hashes its inputs, resolves and validates configuration, initializes the harness and credential/catalog checks, and does not execute codons or make a model-generation self-test. Provider health checks are disabled for this command. Validation can add `$schema` to the hank and writes a temporary log; Bedrock credential discovery can probe instance metadata, so do not treat it as a universal offline guarantee. Runtime startup separately performs provider health checks, which can call `generateText("Hi", maxOutputTokens:16)` for available registry providers and may be billable. The command reports its validation result on the console. A successful run ends with the configuration summary, codon summary, and `GOOD TO RUN!` box shown here:
```text
╭──────────────────────────────────────────────────────────────────────────────╮
│ Minimal single provider v1.0.0 │
│ 1 codon • 0 loops │
╰──────────────────────────────────────────────────────────────────────────────╯
└─ [1] summarize-notes (Summarize the notes)
model: haiku │ mode: fresh │ prompts: 1 (13 lines)
checkpointedGlobs: 1
╭─ GOOD TO RUN! ─────────────────────────────────────────────────────╮
│ 1 codons • 1 prompts • 0 system prompts • 0 rigs • 1 checkpoints │
╰────────────────────────────────────────────────────────────────────╯
```
The capture's `mode`, `checkpointedGlobs`, loops, rigs, checkpoints, and system prompts are defined by [hank.json](/reference/hank-json), [loops](/concepts/loops), [rigs](/concepts/rigs), and [checkpoints](/concepts/checkpoints).
[Runbook §2](/operate/runbook#catch-a-broken-hank-before-it-spends-money), [first run §4](/start/first-run#diagnose-failures-before-a-codon-runs), and [CLI](/reference/cli#-v---validate).
**Startup failure readings**
A failed model self-test stops startup and exposes the failing model and reason on the console.
The failure observable is the self-test aggregate followed by `Server startup failed`; the execution directory is created as part of the failed startup path. The capture below shows that sequence for a missing `ANTHROPIC_API_KEY`:
```text
[] [ERROR] Self-test completed: FAILED
[] [ERROR] Self-test FAILED: Some checks failed
[] [ERROR] - authentication: ✗ No authentication found (set ANTHROPIC_API_KEY)
[ERROR] Server startup failed!
Error message: Self-test failed for 1 model(s):
- Claude Haiku 4.5 (latest) (anthropic/claude-haiku-4-5): Some checks failed
• authentication: No authentication found (set ANTHROPIC_API_KEY)
```
Failure formats belong to the linked runbook, first-run, authentication, and model-resolution pages. There is no `models list` or `hankweave run` subcommand: use the curated table for discovery and `--validate` for checking. For execution selection, see [`--execution`](/reference/cli#-e---execution-path).
[Runbook §2](/operate/runbook#catch-a-broken-hank-before-it-spends-money), [first run §4](/start/first-run#diagnose-failures-before-a-codon-runs), and [model resolution §6](/reference/model-resolution#where-model-validation-fails).
## Prices and your budget
**Price and capacity columns**
The generated table reports dated price and capacity data for estimating a model route, not an undated promise about future provider prices.
`in`, `out`, and `cache-read` are USD per 1M tokens. `context` and `max out` are token counts. The table also records reasoning support, accepted inputs, knowledge date, harness, provider, and verification status.
Read each 0.10.0 price with its route and capacity. `maxDollars` is the total cost budget in USD and `maxTimeSeconds` is the wall-clock limit; both are set in hank.json's `budget` block. For shares, caps, `onExceeded`, and their operational behavior, see [Budgets](/concepts/budgets) and [hank.json](/reference/hank-json).
One row needs care here. The generated table renders `gpt-5.6-xhigh` at the same $5/$30 as `gpt-5.6-sol`, while the registry's `effortCostMultiplier` accounts for the auto-generated `-xhigh` variant at 2× ($10/$60). The table and registry therefore expose different price surfaces: the table is the published display, but the registry accounting is the 2× signal. For an `xhigh` budget, use the registry's $10/$60 accounting signal; do not treat the displayed table price as if the multiplier had already been applied.
The embedded table supplies the route-specific price and capacity examples. [Budgets](/concepts/budgets#who-sets-what--the-two-party-contract) and [hank.json](/reference/hank-json) own shares, caps, `onExceeded`, and the two-party budget contract.
**Zero-priced Pi catalog rows**
A Pi-catalog row with a zero cost can pass model selection while escaping a dollar cap.
The `pi/zai/*` rows show $0 for input, output, and cache-read prices because Pi's catalog carries zero costs for those fields.
For those rows, `maxDollars` does not bind; the operational guidance is to guard the run with `maxTimeSeconds`. The consequence belongs to [authentication and models §7](/operate/authentication-and-models#when-does-provider-quota-end-a-run-first) and [runbook §7](/operate/runbook#stop-a-run-without-losing-state).
The embedded table's `pi/zai/glm-5.3` row supplies the zero-priced route and its token capacities. See [budgets](/concepts/budgets) and [authentication and models](/operate/authentication-and-models#when-does-provider-quota-end-a-run-first).