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


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.