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

# Events Reference

Reference of every event the agent emits, with fields and import paths.

<Note>
  For an overview of how events are dispatched and patterns for using them, see the [Event System Guide](/guides/event-system).
</Note>

For most app logic, prefer `agent.simple_response(..., interrupt=...)`, `agent.say(..., interrupt=...)`, and `agent.metrics` over wiring up low-level events.

## Base Event Structure

All events inherit from `BaseEvent`:

| Field           | Type                  | Description                                            |
| --------------- | --------------------- | ------------------------------------------------------ |
| `type`          | `str`                 | Event type identifier (e.g. `"agent.user_transcript"`) |
| `event_id`      | `str`                 | Unique UUID for this event instance                    |
| `timestamp`     | `datetime`            | When the event was created (UTC)                       |
| `session_id`    | `str \| None`         | Current session identifier                             |
| `participant`   | `Participant \| None` | Participant the event relates to, when applicable      |
| `user_metadata` | `Any \| None`         | Optional caller-supplied metadata                      |

Plugin-emitted events extend `PluginBaseEvent`, which adds two fields:

| Field            | Type          | Description                               |
| ---------------- | ------------- | ----------------------------------------- |
| `plugin_name`    | `str \| None` | Name of the plugin that emitted the event |
| `plugin_version` | `str \| None` | Version of the plugin                     |

***

## Agent Lifecycle Events

High-level events emitted by the agent itself as a call progresses through user and agent turns.

**Import:** `from vision_agents.core.agents.events import ...`

### UserTranscriptEvent

Emitted with the final user transcript that triggers an LLM turn. This is the event most apps should listen to for "what did the user say" — it fires in both classic STT and realtime modes.

```python theme={null}
from vision_agents.core.agents.events import UserTranscriptEvent

@agent.events.subscribe
async def on_user_transcript(event: UserTranscriptEvent):
    print(f"User said: {event.text}")
```

| Field         | Type                  | Description                 |
| ------------- | --------------------- | --------------------------- |
| `text`        | `str`                 | Final transcribed user text |
| `participant` | `Participant \| None` | Who spoke                   |

### UserTurnStartedEvent

Emitted when the user starts speaking.

| Field         | Type                  | Description          |
| ------------- | --------------------- | -------------------- |
| `participant` | `Participant \| None` | Who started speaking |

### UserTurnEndedEvent

Emitted when the user stops speaking.

| Field         | Type                  | Description          |
| ------------- | --------------------- | -------------------- |
| `participant` | `Participant \| None` | Who stopped speaking |

### AgentTurnStartedEvent

Emitted when the agent starts speaking (first audio chunk leaving the pipeline). Carries only the `BaseEvent` fields.

### AgentTurnEndedEvent

Emitted when the agent stops speaking. Use `interrupted` to tell barge-in from natural completion.

```python theme={null}
from vision_agents.core.agents.events import AgentTurnEndedEvent

@agent.events.subscribe
async def on_agent_turn_ended(event: AgentTurnEndedEvent):
    if event.interrupted:
        print("User barged in")
```

| Field         | Type   | Description                                             |
| ------------- | ------ | ------------------------------------------------------- |
| `interrupted` | `bool` | `True` if the turn was cut short by a user interruption |

### AgentJoinedCallEvent

Emitted after the agent has joined a call.

| Field  | Type   | Description              |
| ------ | ------ | ------------------------ |
| `call` | `Call` | The call that was joined |

### AgentLeftCallEvent

Emitted when the agent leaves a call.

| Field  | Type   | Description            |
| ------ | ------ | ---------------------- |
| `call` | `Call` | The call that was left |

### AgentFinishEvent

Emitted when `agent.finish()` has completed. Carries only the `BaseEvent` fields.

***

## Edge / Call Events

Events emitted by the edge transport for participant and track activity on the call.

**Import:** `from vision_agents.core.edge.events import ...`

### ParticipantJoinedEvent

Emitted when a participant (other than the agent) joins the call.

```python theme={null}
from vision_agents.core.edge.events import ParticipantJoinedEvent

@agent.events.subscribe
async def on_join(event: ParticipantJoinedEvent):
    print(f"{event.participant.user_id} joined")
```

| Field         | Type          | Description        |
| ------------- | ------------- | ------------------ |
| `participant` | `Participant` | Joined participant |
| `call`        | `Call`        | The call           |

### ParticipantLeftEvent

Emitted when a participant (other than the agent) leaves the call.

| Field         | Type          | Description           |
| ------------- | ------------- | --------------------- |
| `participant` | `Participant` | Participant that left |
| `call`        | `Call`        | The call              |

### CallEndedEvent

Emitted when a call ends.

| Field  | Type   | Description         |
| ------ | ------ | ------------------- |
| `call` | `Call` | The call that ended |

### TrackAddedEvent

Emitted when a track is added to the call.

| Field        | Type                | Description              |
| ------------ | ------------------- | ------------------------ |
| `track_id`   | `str \| None`       | Track identifier         |
| `track_type` | `TrackType \| None` | Track type (audio/video) |

### TrackRemovedEvent

Emitted when a track is removed from the call.

| Field        | Type                | Description              |
| ------------ | ------------------- | ------------------------ |
| `track_id`   | `str \| None`       | Track identifier         |
| `track_type` | `TrackType \| None` | Track type (audio/video) |

### AudioReceivedEvent

Emitted when audio is received from a participant. High-volume — silence it with `agent.events.silent(AudioReceivedEvent)` if you don't need it.

| Field      | Type              | Description |
| ---------- | ----------------- | ----------- |
| `pcm_data` | `PcmData \| None` | Audio data  |

***

## LLM Events

Events from non-realtime LLM interactions.

**Import:** `from vision_agents.core.llm.events import ...`

### LLMResponseFinalEvent

Emitted when a final LLM response is received.

```python theme={null}
from vision_agents.core.llm.events import LLMResponseFinalEvent

@agent.events.subscribe
async def on_response(event: LLMResponseFinalEvent):
    print(f"Response: {event.text}")
    print(f"Model: {event.model}")
```

| Field   | Type          | Description            |
| ------- | ------------- | ---------------------- |
| `text`  | `str`         | Full LLM response text |
| `model` | `str \| None` | Model identifier       |

<Note>
  `LLMResponseCompletedEvent` and `LLMResponseChunkEvent` were removed in v0.6.2 along with the `heygen` plugin that was their only consumer. Subscribe to `LLMResponseFinalEvent` instead for completion notifications.
</Note>

### LLMErrorEvent

Emitted when a non-realtime LLM error occurs.

| Field            | Type                | Description                            |
| ---------------- | ------------------- | -------------------------------------- |
| `error`          | `Exception \| None` | The exception                          |
| `error_code`     | `str \| None`       | Error code                             |
| `context`        | `str \| None`       | Additional context                     |
| `request_id`     | `str \| None`       | Request identifier                     |
| `is_recoverable` | `bool`              | Whether the error is recoverable       |
| `error_message`  | `str`               | Property: human-readable error message |

***

## Realtime LLM Events

Events specific to realtime LLM connections (e.g. OpenAI Realtime, Gemini Live).

**Import:** `from vision_agents.core.llm.events import ...`

### RealtimeConnectedEvent

Emitted when a realtime connection is established.

| Field            | Type                     | Description            |
| ---------------- | ------------------------ | ---------------------- |
| `session_id`     | `str \| None`            | Session identifier     |
| `session_config` | `dict[str, Any] \| None` | Session configuration  |
| `capabilities`   | `list[str] \| None`      | Available capabilities |

### RealtimeDisconnectedEvent

Emitted when the realtime connection closes.

| Field        | Type          | Description                  |
| ------------ | ------------- | ---------------------------- |
| `session_id` | `str \| None` | Session identifier           |
| `reason`     | `str \| None` | Disconnection reason         |
| `clean`      | `bool`        | Whether disconnect was clean |

<Note>
  For conversation content in a realtime session, subscribe to `UserTranscriptEvent` (see [Agent Lifecycle Events](#agent-lifecycle-events)) — it fires for both realtime and classic STT modes.
</Note>

***

## Tool Events

Events for function calling / tool use.

**Import:** `from vision_agents.core.llm.events import ...`

### ToolStartEvent

Emitted when tool execution begins.

```python theme={null}
from vision_agents.core.llm.events import ToolStartEvent

@agent.events.subscribe
async def on_tool_start(event: ToolStartEvent):
    print(f"Calling {event.tool_name}")
    print(f"Args: {event.arguments}")
```

| Field          | Type           | Description                   |
| -------------- | -------------- | ----------------------------- |
| `tool_name`    | `str`          | Name of the tool being called |
| `arguments`    | `dict \| None` | Arguments passed to the tool  |
| `tool_call_id` | `str \| None`  | Unique call identifier        |

### ToolEndEvent

Emitted when tool execution completes.

```python theme={null}
from vision_agents.core.llm.events import ToolEndEvent

@agent.events.subscribe
async def on_tool_end(event: ToolEndEvent):
    if event.success:
        print(f"{event.tool_name} returned: {event.result}")
        print(f"Took {event.execution_time_ms}ms")
    else:
        print(f"{event.tool_name} failed: {event.error}")
```

| Field               | Type            | Description                 |
| ------------------- | --------------- | --------------------------- |
| `tool_name`         | `str`           | Name of the tool            |
| `success`           | `bool`          | Whether execution succeeded |
| `result`            | `Any`           | Return value (if success)   |
| `error`             | `str \| None`   | Error message (if failed)   |
| `tool_call_id`      | `str \| None`   | Unique call identifier      |
| `execution_time_ms` | `float \| None` | Execution duration          |

***

## STT Events

Connection-state and error events from the speech-to-text plugin. Transcripts themselves surface as `UserTranscriptEvent` (see [Agent Lifecycle Events](#agent-lifecycle-events)).

**Import:** `from vision_agents.core.stt.events import ...`

### STTConnectedEvent

Emitted when an STT connection is established. Carries only the `PluginBaseEvent` fields.

### STTDisconnectedEvent

Emitted when an STT connection is closed.

| Field    | Type          | Description                  |
| -------- | ------------- | ---------------------------- |
| `reason` | `str \| None` | Disconnection reason         |
| `clean`  | `bool`        | Whether disconnect was clean |

### STTErrorEvent

Emitted when STT encounters an error.

| Field           | Type                | Description                            |
| --------------- | ------------------- | -------------------------------------- |
| `error`         | `Exception \| None` | The exception that occurred            |
| `error_code`    | `str \| None`       | Error code identifier                  |
| `context`       | `str \| None`       | Additional context                     |
| `error_message` | `str`               | Property: human-readable error message |

***

## TTS Events

Events from speech synthesis.

**Import:** `from vision_agents.core.tts.events import ...`

### TTSSynthesisStartEvent

Emitted when TTS synthesis begins.

| Field                   | Type            | Description                  |
| ----------------------- | --------------- | ---------------------------- |
| `text`                  | `str \| None`   | Text being synthesized       |
| `synthesis_id`          | `str`           | Unique ID for this synthesis |
| `model_name`            | `str \| None`   | TTS model name               |
| `voice_id`              | `str \| None`   | Voice identifier             |
| `estimated_duration_ms` | `float \| None` | Estimated audio duration     |

### TTSSynthesisCompleteEvent

Emitted when TTS synthesis finishes.

```python theme={null}
from vision_agents.core.tts.events import TTSSynthesisCompleteEvent

@agent.events.subscribe
async def on_complete(event: TTSSynthesisCompleteEvent):
    print(f"Synthesis took {event.synthesis_time_ms}ms")
    print(f"Audio duration: {event.audio_duration_ms}ms")
```

| Field               | Type            | Description                  |
| ------------------- | --------------- | ---------------------------- |
| `synthesis_id`      | `str \| None`   | Unique ID for this synthesis |
| `text`              | `str \| None`   | Text that was synthesized    |
| `total_audio_bytes` | `int`           | Total bytes of audio         |
| `synthesis_time_ms` | `float`         | Processing time              |
| `audio_duration_ms` | `float \| None` | Resulting audio duration     |
| `chunk_count`       | `int`           | Number of chunks produced    |
| `real_time_factor`  | `float \| None` | Synthesis speed vs real-time |

### TTSConnectedEvent

Emitted when a TTS connection is established. Carries only the `PluginBaseEvent` fields.

### TTSDisconnectedEvent

Emitted when a TTS connection is closed.

| Field    | Type          | Description                  |
| -------- | ------------- | ---------------------------- |
| `reason` | `str \| None` | Disconnection reason         |
| `clean`  | `bool`        | Whether disconnect was clean |

### TTSErrorEvent

Emitted when TTS encounters an error.

| Field           | Type                | Description                            |
| --------------- | ------------------- | -------------------------------------- |
| `error`         | `Exception \| None` | The exception                          |
| `error_code`    | `str \| None`       | Error code                             |
| `context`       | `str \| None`       | Additional context                     |
| `error_message` | `str`               | Property: human-readable error message |

***

## Video Processor Events

Vision plugins (Roboflow, Ultralytics, Huggingface, etc.) emit subclasses of `VideoProcessorDetectionEvent` whenever they finish processing a frame.

**Import:** `from vision_agents.core.events import VideoProcessorDetectionEvent`

### VideoProcessorDetectionEvent

Base class for detection events from any video processor plugin. Plugins extend it with their own fields (detected objects, bounding boxes, raw provider output).

| Field               | Type            | Description                  |
| ------------------- | --------------- | ---------------------------- |
| `model_id`          | `str \| None`   | Identifier of the model used |
| `inference_time_ms` | `float \| None` | Time taken for inference     |
| `detection_count`   | `int`           | Number of objects detected   |

To subscribe, import the plugin-specific subclass (for example `roboflow.DetectionCompletedEvent`). See [Create your own plugin](/integrations/create-your-own-plugin) for the conventions plugin events follow.

<Note>
  This event is used by `MetricsCollector` to record video processing metrics. See [Telemetry](/core/telemetry) for details.
</Note>

***

## ExceptionEvent

Wraps any unhandled exception raised by a subscriber. The event system catches handler failures and re-emits them as `ExceptionEvent` so that other handlers and the agent itself keep running. Subscribe if you want a single place to log handler errors.

| Field     | Type        | Description                      |
| --------- | ----------- | -------------------------------- |
| `exc`     | `Exception` | The exception that was raised    |
| `handler` | `Callable`  | The handler function that failed |

***

## Subscribing to Events

All events can be subscribed to using the `@agent.events.subscribe` decorator:

```python theme={null}
@agent.events.subscribe
async def my_handler(event: EventType):
    # Handle event
    pass
```

Subscribe to multiple event types using union types:

```python theme={null}
@agent.events.subscribe
async def my_handler(event: UserTranscriptEvent | LLMResponseFinalEvent):
    print(event)
```

<Warning>
  Event handlers must be async functions. Non-async handlers raise `RuntimeError` at subscribe time.
</Warning>

See the [Event System Guide](/guides/event-system) for the dispatch model (fire-and-forget, fanout, error isolation) and the patterns that go with it.
