Skip to main content
What you learn: backend objects, configure once, the four ways to hand simulate() an agent, and how traces aim the run. Needs: WHILEAI_API_KEY or wai login for the hosted model, or the provider’s key; simulator=False with a callable needs nothing. Takes: ten minutes. simulate() needs to know what the agent can do (its tools and system prompt) and how to run it. TOOLS on this page is a list of @wai.tool functions, as on the quickstart; schema dicts work in the same list. This page is the second part: which model, behind which endpoint, on which key. Every block below reaches a model, so each one needs a key: WHILEAI_API_KEY in the environment (or wai login) for the hosted model, and OPENAI_API_KEY or ANTHROPIC_API_KEY for a block that names that provider. Adding simulator=False and your own callable agent runs the same call offline.

Which model, on which key

A backend object names a provider, a model and a key. Print it and it says where the call goes.
A key given on a backend is kept for that provider, so every call to that provider in the process finds it. The spec strings the objects stand for (openai:<model>, anthropic:<model>, fireworks:<model>, bedrock:<model-id>[@<region>], vllm:<model>@<url>, ollama:<model>) still work anywhere a backend does.

Set it once, override per call

Three roles: the agent under test, the judge, and the simulator that writes the user’s messages. configure sets them for the process. A keyword on the call wins over configure; a context block wins inside the block; the environment is read only when none of those say.

Four ways to hand simulate() the agent

A backend object

No wrapper at all. The SDK builds the agent from the tools and system prompt you pass and plays it multi-turn: it sends the system prompt and tools, answers each tool call from the mock world, and lets a separate model play the customer.
agent= takes the same backend object configure(agent=) takes, and a key given on it (wai.OpenAI("gpt-4.1-mini", api_key="sk-...")) reaches that provider the same way. Leave agent= out and the run uses what configure set, else the model While hosts on the key from wai login. Useful for a policy that does not have an agent yet: pass only system_prompt= and tools= and see how a capable open model behaves under it. The judge is never the model it is judging: the hosted judge is a different family from the hosted agent.

A callable

Any function that takes the user’s message and returns the tool calls it made and what it finally said.
A callable is played single-turn: one message in, one trajectory out. It is the right shape for an agent you already run behind an HTTP handler or a queue worker. Wrap the handler, return what it did.
wai.simulations.world(tools) gives a callable agent the same mock world the engine uses, so a real tool call in your code can be answered by the sandbox (faults included) instead of by production.

An endpoint with knobs

wai.Endpoint covers a served model. When you need the engine’s per-agent knobs (a reasoning base that should reply without its trace, pinned tool results, scheduled faults), build the agent with local_model and pass the callable.
result_shapes= pins what a tool returns so a policy branch is actually reached; fault_plans= schedules which tool fails on which ask. Both are on the parameters page.

A spec string

The string form of a backend object, for configs and command lines.
typesafe:<model> is TypeSafe’s Jev, on TYPESAFE_API_KEY. It is a judge only: spec= on grade, never agent=.

Aim the run with traces

Without traces, the coverage grid comes from the tools and policy alone (a cold start). With them, it aims at the situations the agent actually met: the tools called, the faults seen, the world states. Any generated row that near-copies a source trace is dropped, so held-out traces stay out of training.
traces= takes rows or a JSONL path. wai.simulations.load_traces normalizes the common shapes (OpenAI messages, tool_trace, final/output) to the one the engine reads, and wai.simulations.rows_from_otel reads an OpenTelemetry batch. Traces reproduce situations, not wording failures: an unsupported claim or an estimate not labelled as one has no world-visible trigger, so put a grader in the loop for those (grader=, on the what to run page).

Seeds

seeds= is a list of opening asks the writer keeps and varies. Every seed is run. With a callable agent whose world has real ids (order numbers, account names), put those ids in the seeds or in the tool descriptions, or the writer invents ids and every rollout is “not found”.
Last modified on September 21, 2026