provider + model,
what features does it support? Tool calling? Vision input? Audio output?
JSON schema mode? Thinking budgets? Prompt caching?
The answer is a ModelCapabilities struct, computed at runtime by applying
rules (in file order) on top of a defaults block.
Zero regex, zero allocation, zero runtime deps.
Canonical source:
crates/nika-catalog/data/model-capabilities.toml.
Schema: nika/model-capabilities@1.0. Build-time FK checks against
llm-providers.toml (unknown provider = build failure, catches typos).Resolution algorithm
1
Start from `[defaults]`
Mirrors
ModelCapabilities::default(). Current defaults:2
Scan `[[rules]]` in file order
Every rule has a
match clause and a caps clause. If the rule’s
scope.providers list is non-empty and the canonical provider id
isn’t in it → skip. Same for scope.api_dialect.3
Apply the rule's `caps` fields
Fields set by a rule overwrite earlier values. Fields absent from
the rule preserve the accumulated state. No merging of lists:
assignment is wholesale.
4
Return the accumulated `ModelCapabilities`
Zero allocation (every string is
&'static str or Cow<'static, str>).
Resolved at runtime in O(N) rules for a single lookup.The 4 match kinds
`any`: matches every model
`any`: matches every model
`exact`: matches one model id
`exact`: matches one model id
`exact_any`: matches a set of model ids
`exact_any`: matches a set of model ids
`prefix_any`: matches models whose id starts with any prefix
`prefix_any`: matches models whose id starts with any prefix
Capability fields
What a rule can set:Supported parameter vocabulary (13)
The vocabulary is closed: adding a new parameter is a
nika-catalog schema change.Modality vocabulary (8)
text · image · audio · video · pdf · embedding · speech · image-gen
Example resolution trace
Why not regex
L0 crates ship zero runtime dependencies beyond
std + alloc. Regex
would pull in regex-automata (~50k LOC) and force a runtime
initialization cost. prefix_any covers 95% of actual model-family
matching needs; the remaining 5% is handled by exact_any.How to query capabilities
Two shipped subcommands project the embedded catalogs —nika catalog
(providers · models · capabilities · env vars) and nika catalog --tools (the
nika:* builtin schemas), each with a versioned --json machine form:
Drift protection
Build-time FK check: every
scope.providers[i] must be a canonical
provider id in llm-providers.toml. Typos fail the build.Build-time enum check: every supported_parameters entry must be in
the 13-value vocabulary. New additions require a schema bump.Build-time ordering check: tags arrays in llm-providers.toml must
be sorted + deduplicated. Same applies to caps.* arrays by convention.See also
Providers catalog
The canonical providers these rules target.
Concepts · Providers
Runtime routing: how infer verb picks a provider.
Schema
.nika.yaml envelope + workflow schema reference.L0 decisions
Q1-Q13: why no regex, why manual impl, why prefix-only matching.