The agents participating in the scenario.
A description of what the scenario tests.
OptionalfetchWhether the judge fetches the remote traces produced by the agent under test from the LangWatch trace API and merges them into its evaluation.
Enable this when the agent runs behind an HTTP endpoint that returns final text only: the adapter forwards AgentInput.propagationHeaders to the remote agent, the agent's own spans land in the same trace, and the judge reads the real tool calls, writes, and retrievals instead of claims in the transcript.
Can also be set project-wide in scenario.config.js; this per-run value
wins.
OptionalidOptional unique identifier for the scenario. If not provided, a UUID will be generated.
OptionallangwatchLangWatch reporting configuration. Takes precedence over LANGWATCH_API_KEY and LANGWATCH_ENDPOINT environment variables.
Use this when running multiple scenarios concurrently for different projects to avoid race conditions from mutating process.env.
OptionalmaxThe maximum number of turns to execute.
If no value is provided, this defaults to DEFAULT_MAX_TURNS.
OptionalmetadataOptional metadata to attach to the scenario run.
Accepts arbitrary key-value pairs (e.g. prompt IDs, environments, versions).
The langwatch key is reserved for platform-internal use.
OptionalminThe minimum number of turns that must run before the judge may
volunteer a verdict. With minTurns: 4, turns 1–4 always run and the
judge can first end the test on turn 5 — its finish_test tool is
withheld on earlier turns (ADR-005).
Forced judgments always win over the floor: an explicit
scenario.judge() step and the final maxTurns turn still deliver a
terminal verdict even below the floor. The floor governs the judge
only — red-team early exit and explicit succeed()/fail() script
steps are unaffected.
Must be a non-negative integer and must not exceed maxTurns; invalid
values throw at startup. Zero is valid and behaves like an unset floor.
When unset, behavior is identical to previous releases.
The name of the scenario.
OptionalonOptional callback invoked for every audio chunk that flows through a voice adapter (both user-side and agent-side).
Mirrors Python scenario.run(on_audio_chunk=...). Best-effort — if
the hook throws, the scenario continues uninterrupted.
OptionalonOptional callback invoked for every VoiceEvent appended to
the timeline (user_start_speaking, agent_stop_speaking, etc.).
Mirrors Python scenario.run(on_voice_event=...). Best-effort — if
the hook throws, the scenario continues uninterrupted.
OptionalscriptThe script of steps to execute for the scenario.
OptionalsetOptional identifier to group this scenario into a set ("Simulation Set"). This is useful for organizing related scenarios in the UI and for reporting. If not provided, the scenario will not be grouped into a set.
OptionalthreadOptional thread ID to use for the conversation. If not provided, a new thread will be created.
OptionaltraceBudget in milliseconds for the judge's one extra wait. When the traces
are still incomplete after the settle-wait, the verdict call offers the
judge a wait_for_traces tool: calling it waits this budget once more,
then the tool is withdrawn and the judge must decide. Only used when
fetchRemoteTraces is enabled.
Can also be set project-wide in scenario.config.js; this per-run value
wins.
OptionaltraceTotal time budget in milliseconds the judge waits at verdict time for remote traces to arrive and stabilize. Only used when fetchRemoteTraces is enabled. Mid-conversation judge calls never wait; the budget applies once, when a verdict is required.
Can also be set project-wide in scenario.config.js; this per-run value
wins.
OptionalverboseWhether to output verbose logging.
If no value is provided, this defaults to DEFAULT_VERBOSE.
OptionalvoicePer-run voice configuration (ADR-002). This is the carrier that reaches
every call() via AgentInput.scenarioConfig — the STT/TTS
providers the judge's transcription pass and the user-simulator's TTS
pass read live here, NOT in a module global. An optional
RunOptions.voice override seeds this at the run() boundary
(options?.voice ?? cfg.voice ?? default); the resolved provider is
always read off cfg.voice. See voice/config.ts#resolveVoiceConfig.
Configuration for a scenario.