model field on LuaAgent, or leave the field unset and get the platform default, alibaba/qwen3.8-flash. Lua holds the provider accounts; you don’t configure a provider key.
How a model is chosen
A model is named by a model code,provider/model, for example openai/gpt-5.4-mini or anthropic/claude-sonnet-5. model accepts that string, or a model resolver: a function that receives the request and returns a code. The resolver runs on every request with the same platform objects a tool has, so it can read request.channel, the current end user, or an environment variable and pick accordingly.
src/index.ts
lua models set --model <code> writes a code into src/index.ts and updates the agent on the server; lua models unset removes it and returns the agent to the platform default. Both validate the code against the catalog, as does lua init --model. Pushing the agent with lua push agent sends the whole agent configuration, so an agent whose code has no model clears any model set in the admin dashboard; lua sync --check reports that difference before you push. A model or modelSettings change takes effect for end users as soon as the push lands, before any agent version is created. The model code is also recorded in each agent version, so promoting an older version restores the model it was created with.
The catalog is served by the platform and changes without a CLI release, so read it from the CLI rather than from a page. The --json form adds each model’s reasoning tiers, accepted media, and web-search support.
Output
actionMultiplier is the model’s cost relative to the platform’s baseline model, the same multiplier billing applies to a turn: 0.5 means a turn on this model spends half as much as one on the baseline, 10 means ten times as much. A costWarning: true field appears when the multiplier is at or above the platform’s warning threshold. description is free text from the catalog; the 0.15/0.47 in the default model’s line is not defined by the CLI.
The CLI has no per-turn readout of the model: lua logs --type agent_response records the reply, the channel, and the end user, not the model that produced it. lua models list prints Current model: as the server has it (or (platform default)), and lua version show <n> prints the Model: a version pins. With a resolver, the model that answered a given turn is not exposed.
modelSettings tunes how the chosen model answers and applies to every turn. temperature (0–2) or topP (0–1) control randomness; set one, not both. maxOutputTokens caps the reply. reasoning.effort sets how much the model thinks before answering, on one scale for every provider: off, minimal, low, medium, high, max. Lua translates it to the provider’s own setting and clamps it to the nearest tier that model offers (a model without off gets its lowest tier), so any of the six values is safe to send. Left unset, the model’s reasoning.platformDefault from the catalog applies: low on the platform default, adaptive on models that decide for themselves. reasoning.show controls whether the reasoning trace is returned. topK, presencePenalty, frequencyPenalty, stopSequences, and seed pass through to providers that support them.
Lua’s runtime also contains a fallback chain that can retry a turn on other approved models when the primary’s provider fails. It is switched off unless enabled on the server; a model pinned to another provider never inherits the platform-wide chain; and a model served through an organization’s own provider key is never re-routed.
Model classes
A workflow step can ask for a class of model rather than name a code. There are three, and they describe what a model is good at, not which company makes it:
A step written as
model: 'class/balanced' is resolved to one approved model at the moment it runs, so the step keeps working when a model is retired or a better one joins the catalog. A step also names its work with a task class — classify, extract, transform, draft, research, reason, code or judge — which maps to a model class. On a workflow you push, write both: the map is applied while the agent composes a workflow from chat, not when the step runs. See Author a workflow.
Model classes apply to workflow steps only. An agent’s own model takes a catalog code, auto, or a model resolver; lua models set and lua init --model validate against the catalog, which has no class/… entry, so a class is refused there.
lua models list --workflows (lua-cli 3.36.0 or later) prints the catalog the way a workflow step sees it — each model’s class, what it is best for, its speed, its cost, the effort levels it offers, and why a class may not resolve to it:
Output
own key is a model served through your organization’s own provider key, shown at that provider’s relative rate because you pay the provider directly, and its cost cell reads <n>× (own key). awaiting confirmation is a model new to the catalog: it can be pinned by code, but no class resolves to it until a curator has reviewed it. rate not calibrated means the cost shown is a conservative placeholder, and the cost cell reads <n>× (estimate). Any of the three makes a row pin only, as does a row nothing has rated, which shows — for its class. The effort footnote appears whenever a listed model offers a single effort level or no reasoning control. With --json the same flag prints { "view": "workflows", "models": [...] } with the server’s own rows.
Your organization decides how much of this a workflow may use. lua workflows policy models get prints the ceiling on the classes a step may ask for, the class map in force, and whether composed steps may pin concrete codes; lua workflows policy models set --compose off turns assignment off, leaving every composed step on the agent’s own model.
One vocabulary
Five words in this area sound alike and mean different things. Support, the documentation and the run card use these and no others:
On a seat plan, what a priced call costs is its price band multiplied by that model’s
actionMultiplier, on a chat turn and on a workflow step alike; on the legacy plan a chat turn is one flat credit whatever the band and whatever the model. The band is read from the size of the call, and a cached prompt token counts toward that size at the fraction of a fresh token the provider charges Lua for it — a cache write at its own fraction — rather than at full weight. Where Lua has no published fraction for a provider, nothing changes for that provider: its calls are sized exactly as they were before. Cached tokens move which band a call lands in; they are never a charge of their own, so a call whose weighted size stays inside the same band costs exactly what it cost before. Two calls of the same shape land in the same band whether they came from a chat turn or a workflow step.
Some providers charge more for a long prompt: once a single request’s prompt passes a set size, every token in that request costs more. Claude Haiku 5.5 is one, above 100,000 prompt tokens. On these models a call whose largest request is over that size is priced at the model’s higher multiplier (×1.67 instead of ×0.33 for Claude Haiku 5.5), and the band is read exactly as before. Every prompt token counts toward the size, cached or not, because that is how the provider measures it. The multiplier lua models list --workflows shows is the price below the size.
An agent’s own modelSettings.reasoning.effort is a separate, six-value scale (off through max) that applies to every chat turn and does reach the model. A workflow step’s effort is the three-value one in the table, it is per step, and a plain push records and estimates it without sending it; lua push workflow --apply-effort changes that from the version it pushes, see Author a workflow.
A pinned model and a model resolver
A pinned model is one code for every conversation: predictable cost, predictable behavior, one thing to test. A resolver trades that for a decision per request. Use it when the difference is structural (a cheaper model on a high-volume channel, a stronger one for end users on a paid plan) and keep the decision cheap, because it runs before every turn. A resolver that returns a code outside the catalog doesn’t fail the turn: Lua substitutes the platform default for that turn, so an unexpected model in the logs usually means a typo in the resolver.When to change the model
- The default answers well and cost matters: leave
modelunset. - Answers need deeper multi-step reasoning or tool use than the default manages: pin a stronger model and keep
reasoning.effortatlowuntil you see the need. - Some channels or end users justify a different cost profile: a resolver keyed on
request.channelorUser.get(). - The model must read images or documents: check the catalog’s
mediaflags before pinning. - Replies run long or vary too much: set
maxOutputTokensand a lowertemperaturebefore changing model.
Limits
temperature0–2,topP0–1,maxOutputTokensat least 1,stopSequencesan array of strings; out-of-range values throw at construction, for exampleAgent modelSettings.temperature must be between 0 and 2.reasoning.effortmust be one ofoff,minimal,low,medium,high,max; the model’sreasoning.effortslist in the catalog says which tiers it offers.lua models setandlua init --modelrefuse a code that isn’t in the catalog.- A provider refusal (unknown model, quota) surfaces in the CLI as exit code 12.
Next steps
lua models
List the catalog, set, and unset.
LuaAgent reference
model, modelSettings, and their types.Execution contexts
What a model resolver can read.
Channels
The
request.channel values a resolver sees.Author a workflow
Task classes, model classes, and effort on a workflow step.

