Model config
The model object stored with a version, an open JSON block carrying provider, model id and whatever generation params you use, and how you read it back to call your provider yourself.
The model object stores which model to call and how, versioned atomically with the content, so a model swap or a temperature change ships as a new version, no code deploy. In the dashboard it's edited on the model panel, either through the form or as raw JSON.
The shape is yours
Trodo does not enforce a model schema, and never calls a model with this object. compile() hands it back and you decide, field by field, what to send, so it's reference data you wrote, not a request we're about to make.
That's also why we don't judge it. New models ship params that didn't exist last month (reasoning_effort, thinking.budget_tokens); our model catalog is a weekly third-party sync and goes stale; openai_compat points at gateways whose accepted params we can't see; and the model id is whatever your code calls it.
The only rules are the ones that stop a value breaking downstream: model must be an object. What's in it is up to you, and it's stored and returned byte-for-byte.
Common fields
The form covers these because they're the ones most calls use. Every one is optional, and the list is not exhaustive, anything else you write is kept:
{
"provider": "anthropic",
"model": "claude-opus-4-8",
"temperature": 0.2,
"max_tokens": 1024,
"top_p": 1,
"top_k": 40,
"stop": ["\n\nHuman:"],
"base_url": "https://my-gateway.example.com/v1",
"credential_id": "cred_abc123"
}| Field | Notes |
|---|---|
provider | Which provider you intend to call. |
model | The model id, e.g. gpt-4o or claude-opus-4-8. |
temperature | Sampling temperature. |
max_tokens | Max output tokens. |
top_p | Nucleus sampling. |
top_k | Top-k sampling. |
stop | Stop sequences. |
base_url | Custom endpoint. |
credential_id | A stored credential, if you want the version to name one. |
Providers
The picker offers openai, anthropic, gemini, mistral, groq, deepseek, xai, fireworks, openai_compat, azure_openai, vertex_ai, bedrock, but the field is a plain string and any value is stored.
Things your provider will care about
None of these are enforced. They're listed because they're the ones that most often turn into a provider 400, and the version is where you'd notice too late:
anthropicandbedrockreject a call withoutmax_tokens.- The OpenAI-schema providers have no
top_k. openai_compathas no default endpoint, so abase_urlhas to come from somewhere: the version, or your code.- Some models reject
temperatureoutright (reasoning models, and newer Anthropic models).
Reading it back
compile() passes model through unchanged: it never calls a model. Read the fields off prompt.model (or compiled.model) and pass them to your provider client yourself.
const { messages, model } = prompt.compile({ question: 'refund status?' });
const answer = await openai.chat.completions.create({
model: model.model ?? 'gpt-4o',
temperature: model.temperature ?? 0.2,
max_tokens: model.max_tokens,
messages,
});compiled = prompt.compile(question="refund status?")
answer = openai.chat.completions.create(
model=compiled.model.get("model", "gpt-4o"),
temperature=compiled.model.get("temperature", 0.2),
max_tokens=compiled.model.get("max_tokens"),
messages=compiled.messages,
)Variables & templating
Declared variables with optional defaults, message-list placeholders, and the strict Mustache-subset syntax that fills them. A missing value falls back to its default, or renders empty, it never fails.
Model config
The model object stored with a version, an open JSON block carrying provider, model id and whatever generation params you use, and how you read it back to call your provider yourself.