Models
athena model is the CLI surface over the model registry. Today it covers
discovery (list, get, schema) and readiness — the mechanical
“is a PR needed” check on existing rows, with a brief generator a loop can
consume directly. It also supports source-backed registration, live
verification, source inspection, canaries and promotion. Later
releases add deprecation, retirement and migration, driven by the
same commands.
<ref> — used by readiness, verify --live, sources, migrate,
deprecate and retire — is one of:
- a raw registry UUID
model_registry:<uuid>provider/model(split at the first/; the provider is the part before it, the model is everything after, since some providers’ model ids contain slashes — e.g.fal/fal-ai/flux-pro/v1.1)
Commands
athena model list
| Flag | Meaning |
|---|---|
--input-type <TYPE> | Filter by input type (text, image, audio, …). Comma-separated values accepted. |
--output-type <TYPE> | Filter by output type. Comma-separated values accepted. |
--search <term> | Case-insensitive substring match on display_name and the provider model path. Empty provider groups are dropped. |
--supports-web-search | Keep only models that can run provider web search (registry web_search capability, a translator dialect, output_type: text). Combines with --search. |
--all | Accepted for symmetry with other list commands; /models always returns the full list. |
-o, --output json | Compatibility flag for scripts that pass -o json / --output json. |
--schema | Dump this leaf’s schema instead of running. |
athena model list --search "recraft v4 pro"{ "data": [ { "provider": "fal", "models": [ { "id": "model_registry:019f902b-db73-7ea4-8ef2-60a8ff5747cd", "display_name": "Recraft V4 Pro T2I", "model": "fal-ai/recraft/v4/pro/text-to-image" } ] } ]}athena model get <id>
| Flag | Meaning |
|---|---|
<id> | Raw model registry UUID (positional, required unless --schema). |
--schema | Dump this leaf’s schema instead of running. |
athena model get 019f902b-db73-7ea4-8ef2-60a8ff5747cd{ "id": "019f902b-db73-7ea4-8ef2-60a8ff5747cd", "provider": "fal", "model": "fal-ai/recraft/v4/pro/text-to-image", "display_name": "Recraft V4 Pro T2I", "status": "active", "input_schema": { "...": "the full parameter contract" }}athena model schema <id-or-search>
| Flag | Meaning |
|---|---|
<id-or-search> | A raw registry UUID, or a case-insensitive search phrase matched against display_name / model (errors on multiple matches). Required unless --schema. |
--json | Print the raw input_schema only, instead of the readable table. |
--schema | Dump this leaf’s schema instead of running. |
athena model schema "nano banana 2 edit"Default output is a readable table (required params, then each param’s
type / default / enum-or-range). --json prints the schema object
directly:
{ "prompt": { "type": "string", "required": true }, "image_size": { "type": "enum", "values": ["square_hd", "square", "portrait_4_3"], "affects_pricing": true }}athena model verify
| Flag | Meaning |
|---|---|
--from-spec <file|-> | Full agent spec (CreateAgentRequest or a bare workflow) to scan for referenced models. |
--workflow <json|@file|@-> | A workflow object to scan directly: literal JSON, @<path>, or @-. |
--probe-fal | Also probe Fal live for models missing from the registry. |
<ref> | Registry id or a case-insensitive search phrase naming one model. Required with --live; ignored by spec-scanning mode. |
--live | Re-read one registered model from its provider documents and print its diff against the stored row, rather than scan a spec. |
--update | With --live, confirm and write the resolved diff plus a fresh source snapshot. An empty diff still refreshes the snapshot after confirmation. |
--yes | Answer the --live --update confirmation non-interactively. It never accepts a low-confidence or unpriced resolution. |
--schema | Dump this leaf’s schema instead of running. |
Exactly one of --from-spec / --workflow is required (neither → exit 2).
athena model verify --from-spec ./agent.json{ "results": [ { "ref": { "registry_id": "model_registry:019f902b-db73-7ea4-8ef2-60a8ff5747cd" }, "ok": true }, { "ref": { "provider": "fal-ai", "model": "fal-ai/recraft/v4/pro/text-to-image" }, "ok": false } ], "all_ok": false}Exit 0 when all_ok; exit 1 when any referenced model is missing.
With --live, <ref> is required and the command re-resolves the stored
model from its provider documents. It prints the proposed diff; --update
writes only after confirmation (or --yes).
athena model register <url>
| Flag | Meaning |
|---|---|
<url> | Required provider documentation, API-reference or model-card URL. |
--also | Offer every other provider carrying the same model; each candidate is resolved from its own sources and confirmed separately. |
--production | Register against the prod profile and require a second confirmation naming the production API URL. |
--price-json <file|-> | ModelPricingEntry JSON for a price absent from the provider documents; - reads stdin. |
--no-canary | Skip the post-registration canary. |
--yes | Answer confirmations non-interactively. It still refuses a low-confidence or unpriced resolution. |
--schema | Dump this leaf’s schema instead of running. |
The command resolves official provider sources, prints identity, model type,
documents, parameters, pricing, provenance and readiness to stderr, then
writes the row, pricing and source snapshot only after confirmation. Its JSON
report goes to stdout. By default it runs a canary after registration; use
--no-canary only when that execution is intentionally deferred.
athena model sources <ref>
| Flag | Meaning |
|---|---|
<ref> | Registry id or a case-insensitive search phrase naming one model. |
--schema | Dump this leaf’s schema instead of running. |
Prints the latest source snapshot recorded by registration or live verification: source documents, capture times, content hashes and extracted pricing.
athena model canary <ref>
| Flag | Meaning |
|---|---|
<ref> | Registry id or a case-insensitive search phrase naming one model. |
--params <json|file|@file|-> | JSON object used for canary execution and cost prediction: a literal, file path, @<file>, or - for stdin. |
--timeout <seconds> | Terminal-result polling limit in seconds. |
--schema | Dump this leaf’s schema instead of running. |
Requires --workspace. It creates a temporary single-model agent, runs it,
checks output modality and recorded cost against the registered prediction,
then deletes the temporary agent and prints the full outcome.
athena model promote <ref> --to <profile>
| Flag | Meaning |
|---|---|
<ref> | Registry id or a case-insensitive search phrase resolved on the current profile. |
--to <profile> | Required target deployment profile. It must resolve to a different API URL with its own token. |
--no-canary | Promote directly without the required target-environment canary. |
--yes | Answer confirmations non-interactively; promotion to prod normally has a second confirmation. |
--schema | Dump this leaf’s schema instead of running. |
Promotion reads the source row and source snapshot, diffs the target’s matching
provider/model row, confirms the target API URL, then writes row and snapshot
together. If both row and provenance already match, it reports a no-op. Unless
--no-canary is supplied, it requires a target workspace and runs the canary
after the write.
athena model readiness
athena model readiness [<ref>] [--all] [--pr-brief <file>] [--schema]| Flag | Meaning |
|---|---|
<ref> | The model to check (positional). Exactly one of <ref> or --all is required — both or neither is exit 2. |
--all | Check every registry row instead of one. |
--pr-brief <file> | Render the PR brief and write it to <file> (parent directories created; overwrites an existing file). Valid only with <ref> — with --all it’s exit 2. Written whenever the flag is given, whether or not the verdict fails. |
--schema | Dump this leaf’s schema instead of running. |
Single <ref> — stdout gets the full ModelReadinessResponse, exit 0
when readiness.ok, exit 1 otherwise:
athena model readiness higgsfield/higgsfield-ai/soul/2.0The ref splits at the first / (see <ref> above): provider
higgsfield, model higgsfield-ai/soul/2.0.
{ "id": "019f902b-db73-7ea4-8ef2-60a8ff5747cd", "provider": "higgsfield", "model": "higgsfield-ai/soul/2.0", "display_name": "Higgsfield Soul 2.0", "status": "active", "readiness": { "ok": false, "checks": [ { "code": "provider_supported", "ok": false, "reason": "…" }, { "code": "key_present", "ok": true, "reason": "…" }, { "code": "pricing_unit_supported", "ok": true, "reason": "…" }, { "code": "executor_available", "ok": false, "reason": "…" }, { "code": "pricing_param_forwarded", "ok": true, "reason": "…" } ], "unknown_params": ["foo"] }}--all — one JSON object per failing row on stdout, one per line
(NDJSON), rows that pass print nothing, rows in server order:
{"id":"019f902b-db73-7ea4-8ef2-60a8ff5747cd","provider":"higgsfield","model":"higgsfield-ai/soul/2.0","display_name":"Higgsfield Soul 2.0","failing":[{"code":"provider_supported","reason":"…"}],"unknown_params":[]}A summary line goes to stderr:
readiness: 55 of 581 rows need a PR(or readiness: all 581 rows pass). A 2xx response whose data is not an
array — a version skew, an envelope regression — is an error with code
invalid_response and exit 1, never an all-clear on rows the CLI could not
read. Both counts come from the response, never from a fixed catalog size — 581
is simply what the seed catalog (scripts/models/models.json) holds today.
Of the 55 failing rows, 46 fail provider_supported — no client at all (22
higgsfield, 14 stability, 8 ideogram, 2 zhipu) — and 4 fail
executor_available on a provider that otherwise has a client: three
google/imagen-4.0-* ids (not a -image family the Gemini adapter routes)
and google/text-embedding-004 (EmbeddingService takes an OpenAI key only).
The remaining five — cohere/embed-english-v3.0,
cohere/embed-multilingual-v3.0, cohere/embed-v4.0,
openrouter/openai/text-embedding-3-large, and
openrouter/openai/text-embedding-3-small — are declared with
output_type: text but have a zero token-output rate. Their
pricing_unit_supported check fails: only rows declared as embeddings can
omit a completion-token price.
Exit 0 when nothing fails, exit 1 otherwise.
--pr-brief <file> — after printing the verdict, stderr gets
wrote PR brief to <file>. See PR brief below. The command’s
exit code is still driven by the verdict, not by the brief write.
Every command above supports --schema, like the rest of the CLI — see
Reference → Schema dumps.
athena model migrate --from <ref> --to <ref>
| Flag | Meaning |
|---|---|
--from <ref> | Required source model. |
--to <ref> | Required target model. It must have the source model’s output type and must not be retired. |
--scope all|workspace|group | Agent search scope; defaults to all. workspace uses the active workspace. |
--group <id> | Required with --scope group; ignored by other scopes. |
--fix | Apply the plan. Without it, the command only reports the dry-run plan. |
--force | Migrate agents even when wizard-exposed parameters are unsupported by the target, dropping those parameters. |
--yes | Skip confirmation; required for a fixing run from non-interactive stdin. |
--schema | Dump this leaf’s schema instead of running. |
Both references accept a registry id or a case-insensitive search phrase. The command prints the run report. A dry run changes nothing; a fixing run confirms the plan, applies it, then polls the run until it reaches a terminal status.
athena model deprecate <ref>
| Flag | Meaning |
|---|---|
<ref> | Required model to deprecate. |
--to <ref> | Replacement model. Required to move agents without an interactive replacement prompt. |
--fix | Apply the migration plan when agents still reference the source. |
--force | Drop wizard-exposed parameters unsupported by the replacement instead of skipping the agent. |
--yes | Skip confirmation; required for a fixing run from non-interactive stdin. |
--schema | Dump this leaf’s schema instead of running. |
When no agent references the model, the command confirms and marks it
deprecated. When agents still reference it, it first migrates them to the
replacement; only a completed --fix run marks the source deprecated. A dry
run leaves the status unchanged and reports the plan.
athena model retire <ref>
| Flag | Meaning |
|---|---|
<ref> | Required model to retire. |
--yes | Skip confirmation; required from non-interactive stdin. |
--schema | Dump this leaf’s schema instead of running. |
The command refuses while any agent still references the model and names the references in its error. Migrate those agents first, then confirm retirement.
athena model register does not accept --pr-brief — the brief generator is
a readiness flag; register reads readiness, it does not write briefs.
Plain-language phrases
A driving agent (Claude Code, Codex) maps plain language onto athena model
commands. These are the phrases the loop and the CLI’s own --schema
descriptions agree on:
| Phrase | Command | Availability |
|---|---|---|
| ”is a PR needed” / “is this model ready to run” | athena model readiness <ref> | this release |
| ”which models can’t run” / “check every model” | athena model readiness --all | this release |
| ”write the brief” / “hand it to the loop” | athena model readiness <ref> --pr-brief <file> | this release |
| ”what models are there” / “find the nano banana model” | athena model list --search <term> | shipped |
| ”show its parameters” | athena model schema <ref> | shipped |
| ”does every model in this agent exist” | athena model verify --from-spec <file> | shipped |
| ”register this model” | athena model register <url> | shipped |
| ”check it against the provider” | athena model verify <ref> --live | shipped |
| ”show where the prices came from” | athena model sources <ref> | shipped |
| ”run it once and check the bill” | athena model canary <ref> | shipped |
| ”move it to production” | athena model promote <ref> --to prod | shipped |
| ”swap every agent to the new model” | athena model migrate --from <ref> --to <ref> --fix | later release (03) |
| “deprecate it” / “retire it” | athena model deprecate <ref> --to <ref> / athena model retire <ref> | later release (03) |
Worked example: “move gpt-image-2.5 to production” →
athena model promote openai/gpt-image-2.5-sunburst --to prod.
Exit codes
| Code | Meaning here |
|---|---|
| 0 | Success — readiness passed, or verify found every referenced model |
| 1 | Readiness failed, or verify found a missing model |
| 2 | Usage — neither <ref> nor --all given (or both), --pr-brief combined with --all, or neither --from-spec nor --workflow |
| 3 | Auth — not logged in, or token expired and refresh failed |
| 4 | Not found — provider/model resolved to zero rows, or a raw id doesn’t exist |
| 13 | Forbidden — authenticated but not a super-admin |
See Reference → Exit codes for the full, CLI-wide table.
Provider strategies
The provider column is the stored AiProvider value; aliases in
parentheses.
| Provider | Model types in scope | Identity source | Parameter source | Pricing source | Examples source |
|---|---|---|---|---|---|
fal | text_to_image, image_to_image, text_to_video, image_to_video, video_to_video, text_to_speech, speech_to_text, text_to_music | endpoint id from the path | OpenAPI https://fal.ai/api/openapi/queue/openapi.json?endpoint_id=<id>; <page>/api; <page>/llms.txt | <page> pricing section (matrix or unit price) plus GET /v1/models/pricing?endpoint_id= (fal_platform.rs) when a key is present | <page>/examples |
openai | text_to_text, text_to_image, image_to_image, text_to_speech, speech_to_text, text_to_embedding | model id from the path; existence via GET /v1/models when a key is present | developers.openai.com/api/docs/models/<id> (endpoints, modalities, snapshots); family template row for the parameter schema | the same page’s pricing block; per-image prices when the page has them, else the token rates with a per-image estimate (see pricing rules) | developers.openai.com/api/docs/guides/* linked from the page |
openrouter | text_to_text, text_to_image | <owner>/<name> from the path | GET /api/v1/models/<owner>/<name>/endpoints (supported_parameters, architecture) | the same endpoints response (pricing per endpoint; the cheapest provider is the base, others reported) | openrouter.ai/docs model page |
anthropic | text_to_text | model id from the docs path | docs.anthropic.com models overview and the Messages API reference (llms.txt first) | models overview pricing table (input, output, cache read, cache write) | docs quickstart |
google (gemini) | text_to_text, text_to_image, text_to_video, text_to_speech, text_to_embedding | model id from ai.google.dev/gemini-api/docs/models anchors | the models page and generateContent reference | ai.google.dev/gemini-api/docs/pricing (context tiers recorded as modifiers on declared usage thresholds, see 02b) | cookbook links on the page |
xai (grok) | text_to_text, text_to_image | model id from docs.x.ai/docs/models | the models page and the REST reference | the models page pricing table | docs guides |
deepseek | text_to_text | model id from api-docs.deepseek.com | api-docs.deepseek.com quick start and reasoning pages | api-docs.deepseek.com/quick_start/pricing (standard tier; off-peak discount recorded as a note, not a price) | docs |
moonshot (kimi) | text_to_text | model id from platform.moonshot.ai/docs | the model list page and chat reference | the pricing page incl. cached input | docs |
zai (glm) | text_to_text, text_to_image | model id from docs.z.ai | model page and API reference | model page pricing | docs |
groq | text_to_text, speech_to_text, text_to_speech | model id from console.groq.com/docs/models | the models page and the API reference | groq.com/pricing | docs |
minimax | text_to_text, text_to_speech | model id from platform.minimax.io/docs | the model page | the page when it prices; otherwise benchmarked from OpenRouter and flagged | docs |
| Alibaba Qwen | text_to_text, text_to_image | resolved through OpenRouter (openrouter/qwen/<name>) | OpenRouter endpoints | OpenRouter endpoints | — |
Alibaba’s own DashScope endpoint is not an AiProvider text variant; a
DashScope URL resolves to a PR brief naming the missing text client, and the
CLI offers the OpenRouter route for the same model instead. Qwen media models
are unaffected — media_gen/qwen.rs is a direct DashScope client and passes
provider_supported for image output. Higgsfield stays a brief as well —
higgsfield is not an AiProvider variant either.
Model types and pricing structure
The registry’s model_type column: text_to_text, text_to_image,
image_to_image, text_to_video, image_to_video, video_to_video,
text_to_speech, speech_to_text, speech_to_speech, text_to_music,
text_to_embedding. Each type has one pricing structure the resolver
produces and the billing path reads:
| Model type | Unit | Base | Modifiers evaluated on | Output-dimension pricing |
|---|---|---|---|---|
| text_to_text, text_to_embedding | per 1M tokens | input, output, cached input, reasoning | usage tiers (context thresholds) declared by the page | — |
| text_to_image, image_to_image | per image | the price at the documented default parameters | pricing-affecting job parameters (quality, image_size, background, n, …) | yes: per-cell prices keyed by output width×height when the page prices by size |
| text_to_video, image_to_video, video_to_video | per second, or per video when the page prices whole clips | the price at the documented default resolution and duration | resolution, fps, audio on/off, duration tiers | yes: keyed by output resolution |
| text_to_speech, text_to_music | per 1M characters, per second, or per request as the page states | documented default voice/quality | voice tier, quality, format | — |
| speech_to_text, speech_to_speech | per second (audio in) | documented default | diarisation, timestamps, language options when priced | — |
Readiness checks
readiness.checks is exactly these five pass/fail codes, plus
unknown_params as a sixth, warning-only list. readiness.ok is true iff
every check in checks is ok — unknown_params never fails the verdict.
| Code | Proves | What fixes it |
|---|---|---|
provider_supported | The provider string either parses to an AiProvider variant (aliases included) or is a media-only provider id with its own key spec — google-vertex and qwen are media-only and are not AiProvider variants. | For a text provider, add the variant to AiProvider (core/crates/athena-intelligence/src/providers/mod.rs) and its key slot (key_resolution.rs); for a media-only provider, add it to media_provider_key_spec (media_gen/provider.rs) alongside its adapter — either way, a PR. |
key_present | A credential is configured for the provider. | Configure the provider credential — an operator task, not a PR. |
pricing_unit_supported | BaseCosts (core/crates/athena-common/src/types/cost.rs) can hold this row’s pricing unit. | Extend BaseCosts for the unit — a PR. |
executor_available | A runtime path exists for this provider × output type. | Add a runtime path (media: media_gen/provider.rs build_media_provider) — a PR. |
pricing_param_forwarded | Every pricing-affecting parameter is actually forwarded to the provider, so the platform can bill it. | Forward the parameter in the provider client so the pricing modifier can apply — a PR. |
unknown_params (warning) | Lists parameters the provider client does not forward. Never fails the verdict. | Forward the parameter in the provider client, or register/run without it. |
PR brief
athena model readiness <ref> --pr-brief <file> renders a loop-ready
Markdown brief and writes it to <file> (parent directories created; an
existing file is overwritten). Before the command exits, the CLI validates
that every required task-template heading is present, in order — a missing
or out-of-order heading is exit 1 with code brief_invalid, naming the
first missing heading.
The brief carries, in this order:
-
A title line naming the provider and model, and stating the verdict —
needs a PRwhen a check fails,passes — no PR neededwhen none does. The## Objectivefollows the same verdict, so a brief written for a passing row never asks for work nobody needs. -
The task-template headings (
## Objective,## Decision / current baseline,## Repository gap analysis,## Required scope,## Dependencies / related,## Acceptance criteria,## Out of scope,## Estimate) —## Decision / current baselineembeds the full registry entry as a fenced ```json block;## Repository gap analysislists every failing check (plus aPassing:sub-list) andunknown_paramsas a warning line;## Required scopeturns each failing check into a checkbox item pointing at the file it needs touched, from the Readiness checks table above. -
A
## Sourcessection: one bullet per source document (url, capture time, content hash) with its excerpt fenced as ```text, or a note that no source snapshot was recorded. -
A
## Runsection with the loop invocation as a fenced block, naming the file just written:/athena-loop deliver the brief at <file>followed by a note that the brief can instead be pasted into a ClickUp task and run through
.agents/loop/ADD.mdwith its id.
--pr-brief is written whenever the verdict fails or the flag is
given — the command’s own exit code still tracks the verdict, not the
brief write.