> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zeroruntime.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent & Session

> Python API reference for Agent & Session.

The core classes that define an agent and drive a live call: the `Agent` you
subclass to give it instructions and tools, and the `AgentSession` that runs it,
speaking, listening, and managing the call lifecycle. `serve` and `invoke` register
an agent and start sessions against it.

## Agent

A voice agent: instructions, tools, and lifecycle behavior.

Subclass to add behavior: define `@function_tool` methods for tools and override
`on_enter`/`on_exit` for lifecycle hooks. The agent carries its
`Pipeline` and is registered for incoming sessions by `zrt.serve`.

### Constructor

```python theme={null}
Agent(instructions: 'str', name: 'Optional[str]' = None, pipeline: 'Any' = None, tools: 'List[FunctionTool]' = None, agent_id: 'str' = None, mcp_servers: 'list' = None, inherit_context: 'bool' = False, greeting: 'Optional[str]' = None, greeting_non_interruptible: 'bool' = False, voice_suffix: 'Optional[str]' = None, append_voice_suffix: 'bool' = True, agents: "Optional[List['Agent']]" = None, max_session_duration_seconds: 'Optional[int]' = None) -> 'None'
```

<ParamField path="instructions" type="str" required>
  System prompt defining the agent's behavior and persona.
</ParamField>

<ParamField path="name" type="Optional[str]">
  Display name. Defaults to `agent_id`.
</ParamField>

<ParamField path="pipeline" type="Any">
  The `Pipeline` (STT/LLM/TTS + VAD/turn detection) to run on.
</ParamField>

<ParamField path="tools" type="List[FunctionTool]">
  Extra `@function_tool` callables. Tools defined as methods on the agent are auto-registered, so use this only for tools defined elsewhere.
</ParamField>

<ParamField path="agent_id" type="str">
  Stable id the agent is registered and routed under. Required.
</ParamField>

<ParamField path="mcp_servers" type="list">
  MCP servers whose tools are exposed to the agent.
</ParamField>

<ParamField path="inherit_context" type="bool" default="False">
  Carry chat history over when handed off from another agent.
</ParamField>

<ParamField path="greeting" type="Optional[str]">
  Optional line spoken automatically when the agent starts.
</ParamField>

<ParamField path="greeting_non_interruptible" type="bool" default="False">
  Disallow barge-in during the greeting.
</ParamField>

<ParamField path="voice_suffix" type="Optional[str]">
  Text appended to the agent's voice id (provider-specific).
</ParamField>

<ParamField path="append_voice_suffix" type="bool" default="True">
  Whether to apply `voice_suffix`. Default True.
</ParamField>

<ParamField path="agents" type="Optional[List['Agent']]">
  Alternate agents this one can hand off to.
</ParamField>

<ParamField path="max_session_duration_seconds" type="Optional[int]">
  Hard cap on session length for this agent.
</ParamField>

### add\_server

```python theme={null}
def add_server(self, mcp_server: 'Any') -> 'None'
```

Register an additional MCP server with the agent.

Extension hook for attaching an MCP server at runtime. The base
implementation does nothing.

<ParamField path="mcp_server" type="Any" required>
  The MCP server to add.
</ParamField>

### capture\_frames

```python theme={null}
def capture_frames(self, num_of_frames: 'int' = 1) -> 'list'
```

Return the most recent captured camera frames (vision).

<ParamField path="num_of_frames" type="int" default="1">
  How many recent frames to return. Default 1.
</ParamField>

<ResponseField name="returns" type="list">
  A list of frames, empty when vision is not active.
</ResponseField>

### cleanup

```python theme={null}
def cleanup(self) -> 'None'
```

Release the agent's resources.

Extension hook for cleaning up after a session. The base implementation
does nothing.

### emit

```python theme={null}
def emit(self, event: 'T', *args: 'Any') -> 'None'
```

Emit an event, invoking all registered handlers with the given arguments.

Handlers are called in registration order. Coroutine handlers are
scheduled on the running event loop. If the emitter is closed, the call
is a no-op.

<ParamField path="event" type="T" required>
  The event to emit.
</ParamField>

### hangup

```python theme={null}
def hangup(self) -> 'None'
```

End the active call/session immediately.

### initialize\_mcp

```python theme={null}
def initialize_mcp(self) -> 'None'
```

Initialize the agent's MCP servers.

Extension hook for setting up configured MCP servers. The base
implementation does nothing.

### off

```python theme={null}
def off(self, event: 'T', callback: 'Callable[..., Any]') -> 'None'
```

Remove a previously registered handler for an event.

If the handler is not registered for the event, the call is a no-op.

<ParamField path="event" type="T" required>
  The event the handler was registered for.
</ParamField>

<ParamField path="callback" type="Callable[..., Any]" required>
  The handler to remove.
</ParamField>

### on

```python theme={null}
def on(self, event: 'T', callback: 'Callable[..., Any] | None' = None) -> 'Callable[..., Any]'
```

Register a handler for an event.

Can be used directly by passing a callback, or as a decorator when
`callback` is omitted.

<ParamField path="event" type="T" required>
  The event to listen for.
</ParamField>

<ParamField path="callback" type="Callable[..., Any] | None">
  The handler to invoke when the event is emitted. If `None`, a decorator is returned that registers the decorated function.
</ParamField>

<ResponseField name="returns" type="Callable[..., Any]">
  The registered callback when `callback` is provided, otherwise a decorator that registers and returns the function it wraps.
</ResponseField>

### on\_enter

```python theme={null}
def on_enter(self) -> 'None'
```

Lifecycle hook fired when the agent starts handling a session.

Override to greet the caller or run setup, e.g. `await self.session.say(...)`.

### on\_exit

```python theme={null}
def on_exit(self) -> 'None'
```

Lifecycle hook fired when the session is ending.

Override to say a closing line or release resources before the session closes.

### play\_background\_audio

```python theme={null}
def play_background_audio(self, file: 'str' = None, volume: 'float' = 1.0, looping: 'bool' = False, override_thinking: 'bool' = True) -> 'None'
```

Play a background-audio clip under the conversation.

<ParamField path="file" type="str">
  Audio file URL/path.
</ParamField>

<ParamField path="volume" type="float" default="1.0">
  Playback volume. Default 1.0.
</ParamField>

<ParamField path="looping" type="bool" default="False">
  Loop the clip. Default False.
</ParamField>

<ParamField path="override_thinking" type="bool" default="True">
  Replace any thinking-audio while this plays. Default True.
</ParamField>

### preload\_background\_audio

```python theme={null}
def preload_background_audio(self, file: 'str' = None, volume: 'float' = 1.0) -> 'None'
```

Preload a background-audio clip so later playback starts instantly.

<ParamField path="file" type="str">
  Audio file URL/path.
</ParamField>

<ParamField path="volume" type="float" default="1.0">
  Playback volume. Default 1.0.
</ParamField>

### register\_a2a

```python theme={null}
def register_a2a(self, card: 'Any') -> 'None'
```

Register the agent for agent-to-agent communication.

Extension hook for publishing the agent's A2A card. The base
implementation does nothing.

<ParamField path="card" type="Any" required>
  The agent card describing this agent for A2A.
</ParamField>

### register\_tools

```python theme={null}
def register_tools(self) -> 'None'
```

Discover and register tools defined as methods on the agent.

Scans the agent's public attributes and appends any that are
`@function_tool` callables to the agent's tool set, skipping tools
already registered. Called automatically during initialization.

### set\_thinking\_audio

```python theme={null}
def set_thinking_audio(self, file: 'str' = None, volume: 'float' = 0.3) -> 'None'
```

Set an audio clip looped while the agent is thinking.

<ParamField path="file" type="str">
  Audio file URL/path. Pass a falsy value to clear it.
</ParamField>

<ParamField path="volume" type="float" default="0.3">
  Playback volume, 0.0–1.0. Default 0.3.
</ParamField>

### stop\_background\_audio

```python theme={null}
def stop_background_audio(self) -> 'None'
```

Stop any background audio currently playing.

### unregister\_a2a

```python theme={null}
def unregister_a2a(self) -> 'None'
```

Unregister the agent from agent-to-agent communication.

Extension hook for tearing down A2A registration. The base
implementation does nothing.

### update\_tools

```python theme={null}
def update_tools(self, tools: 'List[FunctionTool]') -> 'None'
```

Replace the agent's tool set.

<ParamField path="tools" type="List[FunctionTool]" required>
  The new list of `@function_tool` callables.
</ParamField>

***

## AgentSession

A running agent session, your handle to interact with the live conversation.

Available as `self.session` inside an agent. Use it to speak (`say`,
`reply`), steer the turn (`interrupt`, `generate`), read or edit the
conversation (`get_context_history`, `update_instructions`,
`update_tools`), hot-swap components (`update_provider`), play audio, and
end the call (`hangup`, `leave`).

### Constructor

```python theme={null}
AgentSession(agent: 'Any', pipeline: 'Any', wake_up: 'Optional[int]' = None, wake_up_max_attempts: 'Optional[int]' = None, background_audio: 'Any' = None, dtmf_handler: 'Any' = None, voice_mail_detector: 'Any' = None, recording: 'Any' = None) -> 'None'
```

<ParamField path="agent" type="Any" required>
  The agent whose instructions, tools and callbacks drive the session.
</ParamField>

<ParamField path="pipeline" type="Any" required>
  The media pipeline (STT/LLM/TTS and hooks) for the session.
</ParamField>

<ParamField path="wake_up" type="Optional[int]">
  Idle timeout in seconds after which the wake-up callback fires.
</ParamField>

<ParamField path="wake_up_max_attempts" type="Optional[int]">
  Maximum number of wake-up callbacks before the session is closed; `None` means unlimited.
</ParamField>

<ParamField path="background_audio" type="Any">
  Background audio configuration for the session.
</ParamField>

<ParamField path="dtmf_handler" type="Any">
  Handler dispatched when DTMF digits are received.
</ParamField>

<ParamField path="voice_mail_detector" type="Any">
  Detector invoked when voicemail is detected.
</ParamField>

<ParamField path="recording" type="Any">
  Recording configuration applied to the session.
</ParamField>

### active\_agent

```python theme={null}
def active_agent(self) -> 'Any'
```

Return the agent currently driving the session.

<ResponseField name="returns" type="Any" />

### add\_shutdown\_callback

```python theme={null}
def add_shutdown_callback(self, callback: 'Callable[[], Any]') -> 'None'
```

Register a callback to run when the session is closing.

Callbacks are invoked during `close`; coroutine callbacks are awaited.

<ParamField path="callback" type="Callable[[], Any]" required>
  A callable taking no arguments; may be sync or async.
</ParamField>

### call\_transfer

```python theme={null}
def call_transfer(self, token: 'str', transfer_to: 'str') -> 'None'
```

Transfer the active phone call to another destination.

<ParamField path="token" type="str" required>
  Auth token for the transfer.
</ParamField>

<ParamField path="transfer_to" type="str" required>
  Destination number/address to transfer to.
</ParamField>

### cancel\_generation

```python theme={null}
def cancel_generation(self) -> 'None'
```

Cancel the in-flight LLM generation, if any.

### close

```python theme={null}
def close(self, reason: 'str' = 'sdk_close') -> 'None'
```

Close the session and release its resources.

<ParamField path="reason" type="str" default="sdk_close">
  Optional reason recorded for the close.
</ParamField>

### emit

```python theme={null}
def emit(self, event: 'T', *args: 'Any') -> 'None'
```

Emit an event, invoking all registered handlers with the given arguments.

Handlers are called in registration order. Coroutine handlers are
scheduled on the running event loop. If the emitter is closed, the call
is a no-op.

<ParamField path="event" type="T" required>
  The event to emit.
</ParamField>

### fetch\_context\_history

```python theme={null}
def fetch_context_history(self, *, last_n: 'int' = 0, include_function_calls: 'bool' = False, include_system_messages: 'bool' = False) -> 'list[dict]'
```

Fetch a fresh copy of the conversation history.

The async form of `get_context_history`: always retrieves the latest
messages for the live session.

<ParamField path="last_n" type="int" default="0">
  Return only the most recent `last_n` messages (0 = all).
</ParamField>

<ParamField path="include_function_calls" type="bool" default="False">
  Include tool-call/tool-result messages. Default False.
</ParamField>

<ParamField path="include_system_messages" type="bool" default="False">
  Include system messages. Default False.
</ParamField>

<ResponseField name="returns" type="list[dict]">
  A list of message dicts.
</ResponseField>

### generate

```python theme={null}
def generate(self, text: 'str') -> 'None'
```

Feed text to the agent as if the caller had said it, triggering a response.

<ParamField path="text" type="str" required>
  The user-turn text to inject and generate a reply for.
</ParamField>

### get\_context\_history

```python theme={null}
def get_context_history(self, *, last_n: 'int' = 0, include_function_calls: 'bool' = False, include_system_messages: 'bool' = False) -> "'_HistoryAwaitable'"
```

Read the conversation history.

Returns immediately with a cached snapshot, and is also awaitable: `await` the
result to fetch a fresh copy of the live conversation. Each item is a dict with
`role`, `content`, `message_id` and related fields.

<ParamField path="last_n" type="int" default="0">
  Return only the most recent `last_n` messages (0 = all).
</ParamField>

<ParamField path="include_function_calls" type="bool" default="False">
  Include tool-call/tool-result messages. Default False.
</ParamField>

<ParamField path="include_system_messages" type="bool" default="False">
  Include system messages. Default False.
</ParamField>

<ResponseField name="returns" type="'_HistoryAwaitable'">
  An awaitable list of message dicts.
</ResponseField>

### handoffs

```python theme={null}
def handoffs(self) -> 'list'
```

Return the list of handoffs that have occurred this session.

<ResponseField name="returns" type="list">
  A copy of the handoff records, each a dict with `from`, `to` and `reason` fields.
</ResponseField>

### hangup

```python theme={null}
def hangup(self, reason: 'str' = 'manual_hangup') -> 'None'
```

End the call and close the session.

<ParamField path="reason" type="str" default="manual_hangup">
  Reason recorded on the close (defaults to "manual\_hangup").
</ParamField>

### inject\_context

```python theme={null}
def inject_context(self, ctx: 'Any') -> 'bool'
```

Inject multiple messages into the conversation context.

<ParamField path="ctx" type="Any" required>
  An object exposing `messages()` or an iterable of messages, each injected via `inject_message`.
</ParamField>

<ResponseField name="returns" type="bool">
  `True` if every message was injected successfully, `False` otherwise.
</ResponseField>

### inject\_message

```python theme={null}
def inject_message(self, message: 'Any', position: 'str' = '') -> 'bool'
```

Insert a message into the conversation context without triggering a reply.

Accepts either a message object or a dict with fields such as `role`,
`content`, `message_id`, `images`, `tool_calls` and `tool_call_id`.

<ParamField path="message" type="Any" required>
  The message to inject.
</ParamField>

<ParamField path="position" type="str" default="">
  Optional placement hint for where to insert the message.
</ParamField>

<ResponseField name="returns" type="bool">
  `True` if the message was accepted, `False` otherwise (e.g. no active session or transport).
</ResponseField>

### interrupt

```python theme={null}
def interrupt(self, *, force: 'bool' = False) -> 'None'
```

Stop the agent's current utterance and cancel any in-flight generation.

<ParamField path="force" type="bool" default="False">
  Interrupt even when the current utterance is non-interruptible.
</ParamField>

### last\_handoff\_reason

```python theme={null}
def last_handoff_reason(self) -> 'str'
```

Return the reason recorded for the most recent handoff, or an empty string.

<ResponseField name="returns" type="str" />

### leave

```python theme={null}
def leave(self) -> 'None'
```

Leave the session gracefully (the agent disconnects).

### off

```python theme={null}
def off(self, event: 'T', callback: 'Callable[..., Any]') -> 'None'
```

Remove a previously registered handler for an event.

If the handler is not registered for the event, the call is a no-op.

<ParamField path="event" type="T" required>
  The event the handler was registered for.
</ParamField>

<ParamField path="callback" type="Callable[..., Any]" required>
  The handler to remove.
</ParamField>

### on

```python theme={null}
def on(self, event: 'T', callback: 'Callable[..., Any] | None' = None) -> 'Callable[..., Any]'
```

Register a handler for an event.

Can be used directly by passing a callback, or as a decorator when
`callback` is omitted.

<ParamField path="event" type="T" required>
  The event to listen for.
</ParamField>

<ParamField path="callback" type="Callable[..., Any] | None">
  The handler to invoke when the event is emitted. If `None`, a decorator is returned that registers the decorated function.
</ParamField>

<ResponseField name="returns" type="Callable[..., Any]">
  The registered callback when `callback` is provided, otherwise a decorator that registers and returns the function it wraps.
</ResponseField>

### play\_background\_audio

```python theme={null}
def play_background_audio(self, config: 'Any' = None, override_thinking: 'bool' = True) -> 'None'
```

Play background audio for the session.

The source may be a URL, a local file path, or a config object/dict with
`file_url` (or `file_path`/`url`), `volume`, `looping` and a playback
mode. Local files are read and sent inline. A config whose `enabled` flag is
`False` is ignored.

<ParamField path="config" type="Any">
  Audio source as a string path/URL, dict, or config object.
</ParamField>

<ParamField path="override_thinking" type="bool" default="True">
  Whether this playback may override active thinking audio.
</ParamField>

### preload\_background\_audio

```python theme={null}
def preload_background_audio(self, config: 'Any' = None) -> 'None'
```

Preload background audio so later playback starts without delay.

Accepts the same source forms as `play_background_audio`. A config whose
`enabled` flag is `False` is ignored.

<ParamField path="config" type="Any">
  Audio source as a string path/URL, dict, or config object.
</ParamField>

### publish\_message

```python theme={null}
def publish_message(self, config: 'Any') -> 'None'
```

Publish a message to a pub/sub topic.

<ParamField path="config" type="Any" required>
  An object with a `topic` and `message`, plus optional `options` and `payload`. Non-string messages, options and payloads are JSON-encoded.
</ParamField>

### push\_audio\_frame

```python theme={null}
def push_audio_frame(self, pcm: 'bytes', sample_rate: 'int' = 48000) -> 'None'
```

Push a raw PCM audio frame into the session.

<ParamField path="pcm" type="bytes" required>
  Raw PCM audio bytes; empty input is ignored.
</ParamField>

<ParamField path="sample_rate" type="int" default="48000">
  Sample rate of the PCM data in Hz. Default 48000.
</ParamField>

### register\_handoff\_agent

```python theme={null}
def register_handoff_agent(self, agent: 'Any') -> 'str'
```

Register an agent so it can be a handoff target during the session.

<ParamField path="agent" type="Any" required>
  The agent to register; indexed by its `agent_id` or `id`.
</ParamField>

<ResponseField name="returns" type="str">
  The registered agent's id, or an empty string if it has none.
</ResponseField>

### remove\_message

```python theme={null}
def remove_message(self, message_id: 'str') -> 'bool'
```

Remove a single message from the conversation history.

<ParamField path="message_id" type="str" required>
  Id of the message to remove (from `get_context_history`).
</ParamField>

<ResponseField name="returns" type="bool">
  `True` if the message was removed.
</ResponseField>

### reply

```python theme={null}
def reply(self, instructions: 'str', wait_for_playback: 'bool' = True, frames: 'list | None' = None, latest_frames: 'int' = 0, interruptible: 'bool' = True) -> 'UtteranceHandle'
```

Have the agent generate and speak a reply from a prompt.

Unlike `say` (which speaks fixed text), this asks the LLM to produce the
response from `instructions`.

<ParamField path="instructions" type="str" required>
  Prompt telling the agent what to say.
</ParamField>

<ParamField path="wait_for_playback" type="bool" default="True">
  Await until playback finishes before returning. Default True.
</ParamField>

<ParamField path="frames" type="list | None">
  Image frames to include with the prompt (vision).
</ParamField>

<ParamField path="latest_frames" type="int" default="0">
  Instead of `frames`, attach this many most-recent camera frames.
</ParamField>

<ParamField path="interruptible" type="bool" default="True">
  Allow the caller to barge in. Default True.
</ParamField>

<ResponseField name="returns" type="UtteranceHandle">
  An `UtteranceHandle` you can await for playback completion.
</ResponseField>

### say

```python theme={null}
def say(self, message: 'str', interruptible: 'bool' = True, voice: 'str' = '', audio_data: 'Any' = None, add_to_chat_context: 'bool' = True, **kwargs: 'Any') -> 'UtteranceHandle'
```

Speak a specific line of text (synthesized via TTS).

<ParamField path="message" type="str" required>
  The exact text to speak.
</ParamField>

<ParamField path="interruptible" type="bool" default="True">
  Allow the caller to barge in over it. Default True.
</ParamField>

<ParamField path="voice" type="str" default="">
  Optional one-off voice override for this utterance.
</ParamField>

<ParamField path="audio_data" type="Any">
  Reserved; pre-synthesized audio injection is not supported yet.
</ParamField>

<ParamField path="add_to_chat_context" type="bool" default="True">
  Reserved; transcript handling is automatic.
</ParamField>

<ResponseField name="returns" type="UtteranceHandle">
  An `UtteranceHandle` you can await for playback completion.
</ResponseField>

### send\_a2a

```python theme={null}
def send_a2a(self, target_agent_id: 'str', message_json: 'str', correlation_id: 'str' = '') -> 'None'
```

Send an agent-to-agent message to another agent over pub/sub.

The message is wrapped in an envelope carrying the sending agent's id and
published to the target agent's A2A topic.

<ParamField path="target_agent_id" type="str" required>
  Id of the agent to deliver the message to; required.
</ParamField>

<ParamField path="message_json" type="str" required>
  The message body to deliver.
</ParamField>

<ParamField path="correlation_id" type="str" default="">
  Optional id to correlate request and response messages.
</ParamField>

### send\_image

```python theme={null}
def send_image(self, data: 'Any', mime_type: 'str' = 'image/jpeg') -> 'None'
```

Send an image to the session.

Raw bytes are sent as-is with the given `mime_type`; other inputs are
coerced to JPEG bytes. Empty input is ignored.

<ParamField path="data" type="Any" required>
  Image data as bytes-like or any object coercible to JPEG.
</ParamField>

<ParamField path="mime_type" type="str" default="image/jpeg">
  MIME type to use when `data` is already bytes. Default `"image/jpeg"`.
</ParamField>

### send\_message\_with\_frames

```python theme={null}
def send_message_with_frames(self, message: 'Optional[str]', frames: 'list', *, default_mime_type: 'str' = 'image/jpeg', num_latest_frames: 'int' = 0) -> 'None'
```

Send a text message together with image frames (vision input).

Each frame may be a `(payload, mime_type)` tuple, a dict with `data` and an
optional `mime_type`, or a raw image payload; non-bytes payloads are coerced
to JPEG. The call is skipped when there is no message, no frames, and
`num_latest_frames` is not positive.

<ParamField path="message" type="Optional[str]" required>
  Text to send alongside the frames; may be `None`.
</ParamField>

<ParamField path="frames" type="list" required>
  The image frames to attach.
</ParamField>

<ParamField path="default_mime_type" type="str" default="image/jpeg">
  MIME type used when a frame does not specify one.
</ParamField>

<ParamField path="num_latest_frames" type="int" default="0">
  Number of most-recent camera frames to attach instead of (or in addition to) `frames`.
</ParamField>

### set\_user\_input\_enabled

```python theme={null}
def set_user_input_enabled(self, enabled: 'bool') -> 'None'
```

Enable or disable processing of the caller's audio input.

<ParamField path="enabled" type="bool" required>
  `False` to ignore the caller, `True` to resume.
</ParamField>

### start

```python theme={null}
def start(self, wait_for_participant: 'bool' = False, run_until_shutdown: 'bool' = False, sip_hangup_on_shutdown: 'bool' = False, wait_for_participant_timeout_ms: 'int' = 60000, wait_for_audio_stream: 'bool' = False, runtime_options: 'Optional[dict]' = None, session_id: 'Optional[str]' = None, **kwargs: 'Any') -> 'None'
```

Start the session: connect to the runtime and run the agent.

Establishes the session, emits the join events, and invokes the agent's
`on_enter`. Optionally holds startup until a participant (and audio stream)
is present and can block until shutdown.

<ParamField path="wait_for_participant" type="bool" default="False">
  Hold `on_enter` until a participant joins.
</ParamField>

<ParamField path="run_until_shutdown" type="bool" default="False">
  Block until the session is closed, then clean up.
</ParamField>

<ParamField path="sip_hangup_on_shutdown" type="bool" default="False">
  Hang up the SIP call when the session shuts down.
</ParamField>

<ParamField path="wait_for_participant_timeout_ms" type="int" default="60000">
  How long to wait for a participant, in ms.
</ParamField>

<ParamField path="wait_for_audio_stream" type="bool" default="False">
  Also wait for the participant's audio stream before proceeding; defaults to enabled for SIP calls.
</ParamField>

<ParamField path="runtime_options" type="Optional[dict]">
  Optional runtime configuration overrides.
</ParamField>

<ParamField path="session_id" type="Optional[str]">
  Caller-supplied session identifier to associate with the call.
</ParamField>

### start\_recording

```python theme={null}
def start_recording(self, config: 'Any' = None) -> 'None'
```

Start recording the session.

<ParamField path="config" type="Any">
  Recording configuration; falls back to the session-level `recording=` config if omitted. If neither is set, the call is ignored.
</ParamField>

### start\_thinking\_audio

```python theme={null}
def start_thinking_audio(self) -> 'None'
```

Play the agent's configured thinking audio.

Requires thinking audio to have been configured on the agent (via
`agent.set_thinking_audio(...)`); otherwise the call is ignored.

### stop\_background\_audio

```python theme={null}
def stop_background_audio(self) -> 'None'
```

Stop any background audio currently playing.

### stop\_recording

```python theme={null}
def stop_recording(self) -> 'None'
```

Stop the active session recording.

### stop\_thinking\_audio

```python theme={null}
def stop_thinking_audio(self) -> 'None'
```

Stop the agent's thinking audio.

### subscribe\_a2a

```python theme={null}
def subscribe_a2a(self) -> 'None'
```

Subscribe to incoming agent-to-agent messages for the active agent.

Subscribes to the active agent's A2A topic and emits an `a2a_message` event
for each well-formed envelope received. Re-subscribing to the same topic is a
no-op; switching agents resubscribes to the new agent's topic.

### subscribe\_pubsub

```python theme={null}
def subscribe_pubsub(self, topic: 'str', callback: 'Any' = None) -> 'Any'
```

Subscribe to a pub/sub topic, optionally invoking a callback per message.

<ParamField path="topic" type="str" required>
  The topic to subscribe to; must be non-empty.
</ParamField>

<ParamField path="callback" type="Any">
  Optional callable invoked with each message dict matching the topic.
</ParamField>

<ResponseField name="returns" type="Any">
  The internal handler registered for the callback, or `None` if no callback was supplied or the topic was empty.
</ResponseField>

### update\_instructions

```python theme={null}
def update_instructions(self, instructions: 'str') -> 'None'
```

Replace the agent's system prompt mid-session.

<ParamField path="instructions" type="str" required>
  The new system prompt.
</ParamField>

### update\_interrupt\_config

```python theme={null}
def update_interrupt_config(self, *, mode: 'Optional[str]' = None, interrupt_min_duration: 'Optional[float]' = None, interrupt_min_words: 'Optional[int]' = None, cooldown_ms: 'Optional[int]' = None, false_interrupt_pause_duration_ms: 'Optional[int]' = None, resume_on_false_interrupt: 'Optional[bool]' = None) -> 'None'
```

Tune barge-in / interruption behavior mid-session.

<ParamField path="mode" type="Optional[str]">
  Detection mode: `"VAD_ONLY"`, `"STT_ONLY"` or `"HYBRID"`.
</ParamField>

<ParamField path="interrupt_min_duration" type="Optional[float]">
  Minimum speech duration (seconds) to count as a barge-in.
</ParamField>

<ParamField path="interrupt_min_words" type="Optional[int]">
  Minimum words before an interruption is honored.
</ParamField>

<ParamField path="cooldown_ms" type="Optional[int]">
  Minimum gap between interruptions, in ms.
</ParamField>

<ParamField path="false_interrupt_pause_duration_ms" type="Optional[int]">
  Pause length treated as a false interrupt, in ms.
</ParamField>

<ParamField path="resume_on_false_interrupt" type="Optional[bool]">
  Resume the agent's turn after a false interrupt.
</ParamField>

### update\_provider

```python theme={null}
def update_provider(self, component: 'str', provider: 'str', params: 'dict | None' = None) -> 'None'
```

Hot-swap a pipeline component to a different provider mid-session.

<ParamField path="component" type="str" required>
  Which stage to change, e.g. `"stt"`, `"llm"`, `"tts"`.
</ParamField>

<ParamField path="provider" type="str" required>
  The provider to switch to.
</ParamField>

<ParamField path="params" type="dict | None">
  Optional provider-specific settings (model, voice, …).
</ParamField>

### update\_tools

```python theme={null}
def update_tools(self, tools: 'list') -> 'None'
```

Replace the agent's tool set mid-session.

<ParamField path="tools" type="list" required>
  The new list of `@function_tool` callables.
</ParamField>

### wait\_for\_synthesis\_done

```python theme={null}
def wait_for_synthesis_done(self, timeout: 'Optional[float]' = None) -> 'bool'
```

Wait until the current TTS synthesis finishes.

Returns immediately if no synthesis is in progress.

<ParamField path="timeout" type="Optional[float]">
  Maximum time to wait in seconds; `None` waits indefinitely.
</ParamField>

<ResponseField name="returns" type="bool">
  `True` if synthesis completed (or none was in progress), `False` if the wait timed out.
</ResponseField>

### warm\_transfer

```python theme={null}
def warm_transfer(self, *args, **kwargs)
```

Not implemented.

***

## Room

Per-session room configuration passed to `invoke`.

### Fields

<ParamField path="room_id" type="Optional[str]">
  Existing room to join. A new room is created when `None`.
</ParamField>

<ParamField path="auth_token" type="Optional[str]">
  Auth token for the room. Falls back to the ZRT auth env vars.
</ParamField>

<ParamField path="agent_name" type="Optional[str]">
  Display name to publish the agent under. Defaults to the agent id.
</ParamField>

<ParamField path="playground" type="bool" default="True">
  Return a `playground_url` for opening the session. Default True.
</ParamField>

<ParamField path="vision" type="bool" default="False">
  Enable camera-frame capture for the agent. Default False.
</ParamField>

<ParamField path="recording" type="bool" default="False">
  Record the session. Default False.
</ParamField>

<ParamField path="background_audio" type="bool" default="False">
  Enable background-audio playback. Default False.
</ParamField>

<ParamField path="audio_listener_enabled" type="bool" default="False">
  Deliver raw input audio to listeners. Default False.
</ParamField>

<ParamField path="auto_end_session" type="bool" default="True">
  End the session when the caller leaves. Default True.
</ParamField>

<ParamField path="session_timeout_seconds" type="Optional[int]">
  Hard cap on session duration, in seconds.
</ParamField>

<ParamField path="no_participant_timeout_seconds" type="Optional[int]">
  End the session if nobody joins in time.
</ParamField>

<ParamField path="agent_participant_id" type="Optional[str]">
  Fixed participant id for the agent.
</ParamField>

<ParamField path="signaling_base_url" type="Optional[str]">
  Override the signaling base URL.
</ParamField>

<ParamField path="send_logs_to_dashboard" type="bool" default="True">
  Stream session logs to the dashboard. Default True.
</ParamField>

<ParamField path="dashboard_log_level" type="str" default="INFO">
  Log level for dashboard logs. Default `"INFO"`.
</ParamField>

***

## Sip

Telephony (SIP) details for a phone-call session passed to `invoke`.

### Fields

<ParamField path="call_to" type="Optional[str]">
  Destination number/address for an outbound call.
</ParamField>

<ParamField path="call_from" type="Optional[str]">
  Caller id presented on the call.
</ParamField>

<ParamField path="call_type" type="Optional[str]">
  Call direction/type (e.g. inbound/outbound).
</ParamField>

<ParamField path="call_id" type="Optional[str]">
  Identifier correlating the call.
</ParamField>

<ParamField path="webhook_url" type="Optional[str]">
  URL to receive call-event callbacks.
</ParamField>

<ParamField path="extra" type="Dict[str, str]" default="…">
  Additional provider-specific key/values forwarded with the call.
</ParamField>
