@langwatch/scenario
    Preparing search index...

    Interface ScenarioConfigFinalInternal

    Final, normalized scenario configuration. All optional fields are filled with default values.

    interface ScenarioConfigFinal {
        agents: AgentAdapter[];
        description: string;
        id: string;
        langwatch?: LangwatchConfig;
        maxTurns: number;
        metadata?: Record<string, unknown>;
        minTurns?: number;
        name: string;
        onAudioChunk?: (chunk: AudioChunk) => void;
        onVoiceEvent?: (event: VoiceEvent) => void;
        script: ScriptStep[];
        setId?: string;
        threadId: string;
        verbose: boolean;
        voice?: VoiceConfig;
    }

    Hierarchy

    • Omit<ScenarioConfig, "id" | "script" | "threadId" | "verbose" | "maxTurns">
      • ScenarioConfigFinal
    Index
    agents: AgentAdapter[]

    The agents participating in the scenario.

    description: string

    A description of what the scenario tests.

    id: string
    langwatch?: LangwatchConfig

    LangWatch 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.

    await run({
    name: 'My scenario',
    langwatch: {
    apiKey: project.apiKey,
    endpoint: 'https://app.langwatch.ai',
    },
    agents: [...],
    });
    maxTurns: number
    metadata?: Record<string, unknown>

    Optional 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.

    minTurns?: number

    The 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.

    name: string

    The name of the scenario.

    onAudioChunk?: (chunk: AudioChunk) => void

    Optional 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.

    onVoiceEvent?: (event: VoiceEvent) => void

    Optional 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.

    script: ScriptStep[]
    setId?: string

    Optional 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.

    threadId: string
    verbose: boolean
    voice?: VoiceConfig

    Per-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.