@langwatch/scenario
    Preparing search index...

    Interface UserSimulatorAgent

    Abstract base class for user simulator agents. User simulator agents are responsible for generating user messages to drive the conversation.

    interface UserSimulatorAgent {
        _audioEffectsOverride: ((audio: Uint8Array) => Uint8Array)[] | null;
        _synthesize: (text: string, voice: string) => Promise<AudioChunk>;
        _voiceStyleOverride: string | null;
        invokeLLM: (
            params: CallSettings & (
                Prompt & { model: LanguageModel; tools?: ToolSet | undefined; toolChoice?: ToolChoice<NoInfer<ToolSet>> | undefined; ... 19 more ...; _internal?: { ...; } | undefined; }
            ),
        ) => Promise<InvokeLLMResult>;
        name: string;
        role: AgentRole;
        get interruptProbability(): number;
        get voice(): string | undefined;
        call(input: AgentInput): Promise<ModelMessage>;
        setOneShotOverride(
            opts: {
                audioEffects?: ((audio: Uint8Array) => Uint8Array)[];
                voiceStyle?: string;
            },
        ): () => void;
        voiceifyText(
            text: string,
            runVoiceConfig?: { tts?: { voice?: string } },
        ): Promise<ModelMessage>;
    }

    Hierarchy (View Summary)

    Index

    Properties

    _audioEffectsOverride: ((audio: Uint8Array) => Uint8Array)[] | null = null
    _synthesize: (text: string, voice: string) => Promise<AudioChunk> = ...

    Synthesize TTS audio. Exposed as a property so tests can replace it with a stub without subclassing.

    Signature mirrors python/scenario/voice/tts.py:synthesize(text, voice). Returns an AudioChunk with the synthesized PCM16 data.

    Default: routes through the per-run TTS module (voice/tts#synthesize), whose "provider/voice" router resolves the backend and whose LRU cache is keyed on (sha256(text), voice) — effects apply AFTER the cache read (in voiceify), never baked into the key. Per-run, not a module global. Tests inject a stub via _synthesize.

    _voiceStyleOverride: string | null = null
    invokeLLM: (
        params: CallSettings & (
            Prompt & { model: LanguageModel; tools?: ToolSet | undefined; toolChoice?: ToolChoice<NoInfer<ToolSet>> | undefined; ... 19 more ...; _internal?: { ...; } | undefined; }
        ),
    ) => Promise<InvokeLLMResult> = ...

    LLM invocation function. Can be overridden to customize LLM behavior.

    name: string = "UserSimulatorAgent"
    role: AgentRole = AgentRole.USER

    Accessors

    • get voice(): string | undefined

      The simulator's own configured TTS voice (PRD §4.2, userSimulatorAgent({ voice })), or undefined when none was set.

      Exposed (mirrors Python's UserSimulatorAgent.voice attribute) so the executor can decide whether a scripted user("text") step should be voiceified for a voice agent under test — see scenario_executor.py:_find_user_sim + the getattr(sim, "voice", None) guard.

      Returns string | undefined

    Methods

    • Set a per-step override for voice_style and/or audio_effects. Returns a cleanup function that restores the previous overrides.

      Usage:

      const restore = sim.setOneShotOverride({ voiceStyle: "angry" });
      try { await sim.call(input); } finally { restore(); }

      Parameters

      • opts: { audioEffects?: ((audio: Uint8Array) => Uint8Array)[]; voiceStyle?: string }

      Returns () => void

    • Voiceify an explicit, scripted user line (scenario.user("text")) into an audio ModelMessage — TTS via the effective voice + any active per-step effects/overrides. Returns the original text message unchanged when no voice resolves or the content is empty.

      Port of the explicit-content branch of python/scenario/scenario_executor.py:user (sim._voiceify({...})). The auto-generated-turn path uses the private voiceify (which also reads the per-run cfg.voice.tts.voice off AgentInput); this entry point is for the executor's scripted-content path, where the simulator's OWN voice is authoritative and the per-run config is supplied directly.

      Parameters

      • text: string
      • OptionalrunVoiceConfig: { tts?: { voice?: string } }

      Returns Promise<ModelMessage>