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:

model
{
  "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"
}
FieldNotes
providerWhich provider you intend to call.
modelThe model id, e.g. gpt-4o or claude-opus-4-8.
temperatureSampling temperature.
max_tokensMax output tokens.
top_pNucleus sampling.
top_kTop-k sampling.
stopStop sequences.
base_urlCustom endpoint.
credential_idA 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:

  • anthropic and bedrock reject a call without max_tokens.
  • The OpenAI-schema providers have no top_k.
  • openai_compat has no default endpoint, so a base_url has to come from somewhere: the version, or your code.
  • Some models reject temperature outright (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,
)

On this page