Skip to main content
18 public names. import whileai.simulations as wai, then wai.name.

adapters

Framework adapters. Every runner returns {steps, final_text}.

AgentProfile

Defined in whileai/simulations/generate/adapters.py.

claude_code

Defined in whileai/simulations/generate/adapters.py.

connect

Defined in whileai/simulations/generate/adapters.py.

inspect

Defined in whileai/simulations/generate/adapters.py. Read tools and system prompt off the agent; caller extras are merged in.

agents

OpenAI-compatible chat loop for hosted and local simulation backends.

hosted_model

Defined in whileai/simulations/generate/agents.py. The default simulation brain: hosted Qwen wearing these tools.

local_model

Defined in whileai/simulations/generate/agents.py. Build an agent that talks to any OpenAI-compatible endpoint for simulate(agent=...). Reach for it when the policy under test is a served model: a trained adapter behind vLLM, a local server, any chat endpoint. It returns a callable that plays the multi-turn agent (tool calls, the simulated user, faults) against model at base_url with tools and the system prompt, and every rollout comes back as a row.
  • base_url, model, api_key: where the model is served and what to call it.
  • thinking: for reasoning bases such as Qwen3. False sends chat_template_kwargs={"enable_thinking": False} so the reply is the answer, not the reasoning, the way the hosted Qwen path already does; True asks for it; None (the default) sends nothing and leaves the server’s default. The same field goes to the simulated user when the agent’s own model plays it (the default) or user_model sits on the same endpoint, so the customer is asked not to reason either; a user_model on another endpoint keeps that server’s default. Either way <think> markup never reaches step["text"], final_text, or a user turn (step["user"] and the messages history): what the user model still emits as reasoning is stripped before it becomes speech, and a turn that was reasoning with no spoken line is retried, then dropped. The run reports those under search["user_think"]: user_turns, stripped and unclosed as counts, stripped_share and unclosed_share as shares of the user turns, zeros when none.
  • result_shapes: pins what a tool returns, as {tool_name: example result dict}. The sandbox fills the example on every call instead of inventing a record, so a policy branch that only exists for some tool results (a credit over $200 must be escalated) is reached on purpose rather than by luck. Field names and free text stay as written; ids, dates and people are re-drawn per call, and a number moves by up to about a third of itself (900.0 lands in roughly 600 to 1200, 90.0 in 60 to 120), so pick a template value whose whole range sits on the side of the threshold you want. An argument that shares a key with the template is echoed back (invoice_id in, same invoice_id out). To measure a branch, run the same pinned tasks under two shapes, one per side of the rule. Without it the situation writer drafts an example per tool (write_result_shapes) and the branch is exercised at random.
  • fault_plans: schedules faults per ask, as {message: {tool_name: {"mode": "timeout", "rate": 1.0}}}, keyed by the exact user message, with mode one of timeout, malformed, stale or permission_denied and rate the chance the fault fires on a call. The plan may also carry world_state, stance, tone and texture, which are popped off and shape the world and the simulated user for that ask. simulate() writes these itself from fault_rate=; pass your own only to replay a known plan (tasks= does this for you).
  • timeout: seconds per completion, LOCAL_MODEL_TIMEOUT (300) by default: a served model that scaled to zero takes two to three minutes to answer its first request, and a timeout under that drops every rollout of the first pass. When a call still times out the run says so in data.warnings with the fix (raise timeout=, or send one throwaway request first so the endpoint is warm).
  • patience: a level name (PATIENCE_LEVELS, "normal" by default) or a table {"second": p, "later": q}: the chance the person leaves at the agent’s second question and at every later one, fitted from your own traces (see PATIENCE_HAZARDS).
  • user_model and user_temperature: the simulated person’s model (the agent’s own by default) and the sampling temperature of every simulated-user line, follow-ups (USER_TURN_TEMPERATURE) and human-tool answers (HUMAN_TOOL_TEMPERATURE) alike; None keeps those two defaults.
  • world_options: the mock world’s dials (a WorldOptions or the same fields as a dict: fault modes, hit counts, name pools, …); simulate(advanced={"world": {...}}) lands here. None is the defaults in defaults.py.
  • execute: your own world (tool, arguments) -> result in place of the mock one. max_turns / avg_turns (12.0) cap and shape the conversation length; avg_turns=1 is one user line and one reply, and the follow-up branch never runs; temperature (0.8), max_tokens and logprobs are the agent’s own sampling, recorded on every row.

diversity

Sparse generic writer knobs and annealing helpers.

adaptive_allocator

Defined in whileai/simulations/generate/diversity.py. Adaptive mix. Short remaining clock is messier; saturation walks more cards. Shares are explore / expand / verify. n_req and k are caps so expand and verify can actually run. Not a pinned n=1 k=1 policy.

allocator_slot_counts

Defined in whileai/simulations/generate/diversity.py. Integer explore/expand/verify slots from mix shares.

generator

Model-driven scenario generation. Templates are bootstrap and offline fallback.

ModelSimulator

Defined in whileai/simulations/generate/generator.py. Invent what a person might send, ask, or discuss; it never grades.

write_scene_brief

Defined in whileai/simulations/generate/generator.py. One cheap LLM pass per simulate(). Private writer context. Empty on failure.

offline_agent

The free path, with something to catch.

World

Defined in whileai/simulations/generate/offline_agent.py. The mock world for a callable agent, faults first. Built once; call reads the rollout being answered from current_rollout (thread-local, set by simulate before each rollout) so the row’s own faults and world_state apply. Outside a run it answers with no faults and no world state.

World.call

The world’s answer to one tool call. Scheduled faults apply first.

seeded_agent

Defined in whileai/simulations/generate/offline_agent.py. Build a demo agent whose mistakes are on purpose and recorded on the row. Reach for it to try the whole loop offline, with no key and no model: it gives a run something to catch, and each row says what was planted, so a grader or a marker can be checked against the truth. It returns a callable message -> trajectory for simulate(agent=...). Honest by default: it picks the tool the ask names, calls it through world() (faults fire), and reports what came back. On rate of rollouts, drawn deterministically from seed, the prompt and the rollout index, it does one thing from behaviors: hedging, sycophancy, apology and boilerplate add the phrase style_report looks for; ignore_fault claims success although the tool faulted; leak quotes the row’s privileged context. Each row it answers carries seeded: what it did on purpose, [] when it behaved.
  • tools: the tool schemas the agent may call.
  • rate (SEEDED_RATE, 0.35): the share of rollouts with one planted mistake, high enough that a 20-row demo run catches every behavior kind at least once; a convention, not a real failure rate.
  • seed (0): fixes which rollouts misbehave and how.
  • behaviors (SEEDED_BEHAVIORS): the subset of mistakes to draw from.

world

Defined in whileai/simulations/generate/offline_agent.py. A World for a callable agent: world.call(tool, arguments). Pass the same tools you pass simulate. Inside a run the row’s scheduled faults fire on it; a callable that answers its tool calls through this sees them, and the row’s faults stop being a label with no effect.

scenarios

Coverage cells from the agent’s tools and policy, plus offline fallback wording.

build_dimensions

Defined in whileai/simulations/generate/scenarios.py. Coverage axes from this agent. Length and vagueness are writer-only. rule_cap is the most policy clauses on the rule axis: the grid’s RULE_CAP by default, None for every clause (what a report over an existing suite passes, RULE_AXIS_CAP_REPORT).

novelty

Defined in whileai/simulations/generate/scenarios.py. Min cosine distance from a candidate embedding to every tested row.

open_ended_probes

Defined in whileai/simulations/generate/scenarios.py. Taxonomy-free probes. Wording rotates with seed.

policy_sections

Defined in whileai/simulations/generate/scenarios.py. Split policy text into short rule clauses used as coverage cells. Identity / system-prompt preambles are not clauses. A long unsplit paragraph is dropped rather than truncated mid-word into rule. cap is the most clauses returned, in document order; None is every clause. rule_axis says how many a cap left out.

scenario_regions

Defined in whileai/simulations/generate/scenarios.py. Weighted target regions over a pairwise covering set of the dimensions. prefer_success defaults off in mode="rl" so fault cells survive for covering-grid RL data. Explicit True/False always wins.
Last modified on September 22, 2026