The model registry
What is actually on chain#
Very little, on purpose. A Model account holds four fields plus a bump:
| Field | Type | Notes |
|---|---|---|
id | u16 | the PDA seed is ["model", id] |
name | String | at most 32 bytes |
provider | String | at most 24 bytes |
enabled | bool | whether it can be picked at launch right now |
There is no price on chain, no context window, no capability flags and no ranking. Pricing changes and the chain is a poor place to keep something that changes, so what is recorded is only the fact a buyer needs to check: which model, which provider, and whether it is currently allowed to be picked. Prices live off chain and are documented on compute costs.
The registry, live#
21 models across 9 providers, all currently enabled, written on mainnet and read back through /models. The registry was written on 2026-09-23 alongside the six origins.
| Id | Model | Provider |
|---|---|---|
| 1 | GPT-5.5 | OpenAI |
| 2 | GPT-5.1 | OpenAI |
| 3 | GPT-5 mini | OpenAI |
| 4 | GPT-4.1 | OpenAI |
| 5 | Claude Opus 5 | Anthropic |
| 6 | Claude Sonnet 5 | Anthropic |
| 7 | Claude Haiku 4.5 | Anthropic |
| 8 | Claude Fable 5.1 | Anthropic |
| 9 | Llama | Meta |
| 10 | deepseek-flash | DeepSeek |
| 11 | qwen3.8-max | Alibaba |
| 12 | kimi-k3 | Moonshot |
| 13 | GLM-5.3 | Zhipu |
| 14 | MiniMax-M3 | MiniMax |
| 15 | Gemini 3.5 Flash | |
| 16 | Gemini 3.5 Flash-Lite | |
| 17 | deepseek-v4-pro | DeepSeek |
| 18 | qwen3.8-flash | Alibaba |
| 19 | kimi-k2.6 | Moonshot |
| 20 | GLM-5.3-Flash | Zhipu |
| 21 | MiniMax-M2.7 | MiniMax |
Ids are not grouped by provider because the registry is append-ordered: ids 1 to 16 were written first, and 17 to 21 added later.
{
"source": "chain:Model accounts",
"items": [
{ "id": 1, "name": "GPT-5.5", "provider": "OpenAI", "enabled": true, "registeredAt": "2026-09-23T00:08:28.000Z" },
{ "id": 5, "name": "Claude Opus 5", "provider": "Anthropic", "enabled": true, "registeredAt": "2026-09-23T00:08:30.000Z" },
{ "id": 9, "name": "Llama", "provider": "Meta", "enabled": true, "registeredAt": "2026-09-23T00:08:32.000Z" }
]
}registeredAt is the block time of the transaction that wrote the entry, taken from the indexer, not a field on the account.
How a choice is validated#
When a policy's mode is Agent, init_policy and set_policy both run the same three checks against the supplied Model account:
- the account key must equal the PDA derived from
["model", model_id], elseModelNotFound; - its
idfield must equalmodel_id, elseModelNotFound; - it must be
enabled, elseModelDisabled.
In Passive mode none of this runs: the validator returns immediately and the model account is never read. The accounts struct types it as an Option, so a client signals "none" the standard Anchor way, by passing the program's own id in place of a real account.
Curated, and what that costs#
register_model is admin-only. There is no permissionless path to add a model, which means the registry is a curated list and not an open one. The benefit is that a buyer reading model_id on a policy is reading something an admin vouched for. The cost is that a model nobody has registered cannot be picked, however good it is.
The instruction uses init_if_needed, so calling it again with the same id overwrites the entry in place. Name, provider and enabled flag are all replaced. There is no separate update or delete instruction, and no history on chain: the indexer's registeredAt is the only record of when an entry last changed.
It already drifts behind the vendors#
This matters for how a policy should be read. model_id = 5 means "the entry an admin wrote at id 5", which is currently Claude Opus 5. It does not mean "Anthropic's current flagship", and if the entry is later overwritten, the policy's model_id silently points at the new contents.
Disabling a model#
There is no disable_model instruction. A model is disabled by calling register_model again with the same id and enabled: false.
What disabling does and does not do#
| Effect | |
|---|---|
| New launches | blocked. init_policy fails with ModelDisabled. |
| Existing policies changing their model | blocked. set_policy runs the same check. |
| Existing policies already pointing at it | unaffected. They keep running, and no money path re-reads the model account. |
| The agent key | unaffected. Disabling a registry entry does not revoke anything; only set_agent and set_paused do that. |
So disabling is a gate on new choices, not a kill switch. Stopping a running policy is the guardian's job, described on the safety model.