Skip to content
Resources

Models and pricing

The approved roster, capability flags, and reservation estimates for each model.

Trace exposes a small, reviewed roster. A model that is not on it cannot be called, whatever id you pass.

Reading the roster#

from trace_sdk import Trace

client = Trace()

for model in client.models.list():
    print(f"{model.id:<40} {model.operation:<10} {model.credits_per_1k_tokens}")
trace models

The gateway is the authority. This page can go stale; client.models.list() cannot.

The roster#

Model idOperationToolsStreamingEstimated credits per 1K tokens
deepseek/deepseek-v4-flash-0731:nitrochatyesyes0.15 — default
openai/gpt-5.6-lunachatyesyes0.20
xiaomi/mimo-v2.5chatyesyes0.25
openai/text-embedding-3-smallembeddingnono0.02 — default

The chat models are exactly the roster the Trace agent builder offers, so a workflow you prototype visually uses the same models your code does. openai/text-embedding-3-small is reachable only through the SDK and never appears in a chat block.

The default model#

A call that names no model gets the roster's default:

client.chat.completions.create(messages=messages)                                 # the default
client.chat.completions.create(messages=messages, model="openai/gpt-5.6-luna")    # this request
client = Trace(model="openai/gpt-5.6-luna")                                       # every request

The default is the cheapest chat model on the roster: the first thing a student writes should also be the cheapest thing they can run. It is published rather than hidden — model.is_default marks it, and every completion reports the model that actually answered on completion.model.

default = next(model for model in client.models.list() if model.is_default)
print(default.id)

If the default is ever switched off, the gateway falls back to the first model still standing rather than failing.

Fields on a model#

model.id                      # "deepseek/deepseek-v4-flash-0731:nitro"
model.name                    # "DeepSeek V4 Flash"
model.operation               # "chat" or "embedding"
model.supports_tools          # bool
model.supports_streaming      # bool
model.credits_per_1k_tokens   # float reservation estimate
model.is_default              # bool
model.dimensions              # int, embedding models only

client.models.retrieve("deepseek/deepseek-v4-flash-0731:nitro") returns one model, and raises ModelNotFoundError listing the valid ids if there is no such model.

How billing works#

One credit is $0.001 of upstream cost.

estimated credits per 1K tokens = estimated dollars per 1K tokens × multiplier ÷ 0.001

The multiplier is a single deployment-wide number, published alongside the roster as credit_multiplier on GET /models. It is 1.0 on the hosted app, which means Trace charges the provider's reported cost. The per-token number is only a reservation estimate because providers price input, output, caching and reasoning differently. The final ledger settlement uses authoritative cost.

Estimating a call before you make it#

rate = client.models.retrieve("deepseek/deepseek-v4-flash-0731:nitro").credits_per_1k_tokens
estimated_tokens = 800
print(f"about {estimated_tokens / 1000 * rate:.4f} credits")

Roughly four characters per token is useful for a quick estimate. Trace reserves conservatively and settles the difference after the response.

Choosing a model#

  • deepseek/deepseek-v4-flash-0731:nitro — the default, and the cheapest. Use it for anything where you are learning the mechanics rather than probing what a model can do. The :nitro suffix routes to a throughput-optimised provider, so it is also the quickest to answer.
  • openai/gpt-5.6-luna, xiaomi/mimo-v2.5 — reach for these when a task is genuinely harder and the cheap model is visibly failing, not before.

Comparing models on the same prompt is a legitimate exercise, and each completion tells you what it cost. Just be aware that you pay for every comparison.

Availability#

Every model here is on Trace's reviewed child-safe roster; nothing else is reachable, whatever id you send. See Authentication.

A model can be switched off temporarily for the whole deployment. It disappears from client.models.list() while it is off, and calling it raises ModelNotFoundError with the current roster attached — so the recovery is always visible in the error itself.