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

# Event Handling

> React to conversation events and user interactions with Anam personas

Anam personas communicate through an event system that lets you respond to connection changes, conversation updates, and user interactions. Understanding these events helps you build responsive, interactive applications.

## How Events Work

The Anam SDK uses an event-driven architecture where your application listens for specific events and reacts accordingly. This allows you to:

* Update your UI based on connection status
* Track conversation history in real-time
* Handle user interruptions
* Monitor stream quality and performance

## Available Events

### Connection Events

These events track the connection lifecycle between your client and Anam's streaming infrastructure:

#### `CONNECTION_ESTABLISHED`

Fired when the WebRTC connection is successfully established.

```javascript theme={"system"}
import { AnamEvent } from "@anam-ai/js-sdk";

anamClient.addListener(AnamEvent.CONNECTION_ESTABLISHED, () => {
  console.log("Connected to Anam streaming service");
  updateConnectionStatus("connected");
  hideLoadingSpinner();
});
```

#### `SESSION_READY`

Fired after the session initializes and all backend components are ready. Use this to remove loading indicators.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.SESSION_READY, (sessionId) => {
  console.log("Session ready:", sessionId);
  setIsLoading(false);
});
```

#### `CONNECTION_CLOSED`

Fired when the connection is terminated. Receives a reason code and optional details.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.CONNECTION_CLOSED, (reason, details) => {
  console.log("Connection closed:", reason, details);
  updateConnectionStatus("disconnected");
  showReconnectButton();
});
```

### Video Events

#### `VIDEO_STREAM_STARTED`

Fired when the video MediaStream becomes available.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.VIDEO_STREAM_STARTED, (videoStream) => {
  console.log("Video stream available");
  // You can attach this to a video element if using manual stream handling
});
```

#### `VIDEO_PLAY_STARTED`

Fired when the first video frames begin playing. Ideal for removing loading indicators.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.VIDEO_PLAY_STARTED, () => {
  console.log("Video stream started");
  hideVideoLoadingState();
  showPersonaInterface();
});
```

### Audio Events

#### `AUDIO_STREAM_STARTED`

Fired when the audio MediaStream from the persona becomes available.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.AUDIO_STREAM_STARTED, (audioStream) => {
  console.log("Audio stream available");
});
```

#### `INPUT_AUDIO_STREAM_STARTED`

Fired when microphone input is successfully initialized.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.INPUT_AUDIO_STREAM_STARTED, (stream) => {
  console.log("Microphone access granted");
  showMicrophoneIndicator();
  updateAudioInputStatus("active");
});
```

#### `INPUT_AUDIO_DEVICE_CHANGED`

Fired when the input audio device changes.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.INPUT_AUDIO_DEVICE_CHANGED, (deviceId) => {
  console.log("Audio input device changed to:", deviceId);
});
```

### Microphone Permission Events

These events track the state of microphone permission requests:

#### `MIC_PERMISSION_PENDING`

Fired when the browser is requesting microphone permission from the user.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.MIC_PERMISSION_PENDING, () => {
  showMicPermissionPrompt();
});
```

#### `MIC_PERMISSION_GRANTED`

Fired when the user grants microphone permission.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.MIC_PERMISSION_GRANTED, () => {
  hideMicPermissionPrompt();
});
```

#### `MIC_PERMISSION_DENIED`

Fired when the user denies microphone permission.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.MIC_PERMISSION_DENIED, (error) => {
  console.error("Microphone permission denied:", error);
  showMicPermissionError();
});
```

### Conversation Events

These events help you track and respond to conversation flow:

#### `MESSAGE_HISTORY_UPDATED`

Provides the complete conversation history each time a participant finishes speaking.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.MESSAGE_HISTORY_UPDATED, (messages) => {
  console.log("Conversation updated:", messages);
  updateChatHistory(messages);

  // Example message structure:
  // [
  //   { role: "user", content: "Hello" },
  //   { role: "assistant", content: "Hi there! How can I help?" }
  // ]
});
```

#### `MESSAGE_STREAM_EVENT_RECEIVED`

Provides real-time transcription updates as speech occurs.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.MESSAGE_STREAM_EVENT_RECEIVED, (event) => {
  if (event.role === "persona") {
    // Persona is speaking - show real-time transcription
    updatePersonaTranscript(event.content);
  } else if (event.role === "user") {
    // User finished speaking - complete transcription
    updateUserTranscript(event.content);
  }
});
```

### Reasoning Events

These events provide insight into the persona's reasoning process (when using models that support it):

#### `REASONING_HISTORY_UPDATED`

Provides the complete reasoning history.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.REASONING_HISTORY_UPDATED, (thoughts) => {
  console.log("Reasoning updated:", thoughts);
});
```

#### `REASONING_STREAM_EVENT_RECEIVED`

Provides real-time reasoning updates as the persona thinks.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.REASONING_STREAM_EVENT_RECEIVED, (event) => {
  updateReasoningDisplay(event);
});
```

### Talk Stream Events

#### `TALK_STREAM_INTERRUPTED`

Fired when a user interrupts a `TalkMessageStream` by speaking. Receives the correlation ID directly.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.TALK_STREAM_INTERRUPTED, (correlationId) => {
  console.log("Talk stream interrupted:", correlationId);
  handleStreamInterruption(correlationId);
  stopCurrentGeneration();
});
```

### Server Events

#### `SERVER_WARNING`

Fired when the server sends a warning message.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.SERVER_WARNING, (message) => {
  console.warn("Server warning:", message);
});
```

### Tool Call Events

All tool calls emit lifecycle events — `started`, `completed`, and `failed` — that you can use to trigger client-side actions or for monitoring.

For client tools, use `registerToolCallHandler` to define per-tool handlers, this will automatically emit `completed` or `failed` events when the handler completes.

#### Using `registerToolCallHandler` (Recommended)

Register handlers for specific tools by name. For client tools, the return value from `onStart` is sent back to the LLM as the tool result:

```javascript theme={"system"}
// Register a handler — returns a cancel function
const cancelNavHandler = anamClient.registerToolCallHandler("navigate_to_page", {
  onStart: async (payload) => {
    const { page, section } = payload.arguments;
    window.location.href = `/${page}`;
    return `Navigated to ${page}`;
  },
  onComplete: async (payload) => {
    console.log(`Completed in ${payload.executionTime}ms`);
  },
  onFail: async (payload) => {
    console.error(`Failed: ${payload.errorMessage}`);
  },
});

// Clean up when done
cancelNavHandler();
```

#### `TOOL_CALL_STARTED`

Fired when any tool call begins. Receives a `ToolCallStartedPayload` with the tool name, type, and arguments.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.TOOL_CALL_STARTED, (event) => {
  const { toolName, arguments: args } = event;
  console.log(`Tool started: ${toolName}`, args);
});
```

#### `TOOL_CALL_COMPLETED`

Fired when a tool call completes successfully. Includes the result and execution time.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.TOOL_CALL_COMPLETED, (event) => {
  const { toolName, result, executionTime } = event;
  console.log(`Tool ${toolName} completed in ${executionTime}ms:`, result);
});
```

#### `TOOL_CALL_FAILED`

Fired when a tool call fails. Includes the error message and execution time.

```javascript theme={"system"}
anamClient.addListener(AnamEvent.TOOL_CALL_FAILED, (event) => {
  const { toolName, errorMessage, executionTime } = event;
  console.error(`Tool ${toolName} failed after ${executionTime}ms: ${errorMessage}`);
});
```

#### `CLIENT_TOOL_EVENT_RECEIVED` (Deprecated)

A legacy event for client tools. Replaced by `TOOL_CALL_STARTED` and `registerToolCallHandler` as of SDK v4.9.0.

```javascript theme={"system"}
// Deprecated — use registerToolCallHandler instead
anamClient.addListener(AnamEvent.CLIENT_TOOL_EVENT_RECEIVED, (event) => {
  const { eventName, eventData } = event;

  switch (eventName) {
    case "navigate_to_page":
      window.location.href = `/${eventData.page}`;
      break;
    case "open_modal":
      openModal(eventData.modalType, eventData.data);
      break;
  }
});
```

<Note>Client tools enable voice-driven or chat-driven UI control. For a complete guide on creating and configuring client tools, see the [Client Tools Guide](/personas/tools/client-tools).</Note>

## Removing Event Listeners

Remove listeners when components unmount or sessions end to prevent memory leaks:

```javascript theme={"system"}
const handleMessage = (messages) => {
  updateChatHistory(messages);
};

// Add listener
anamClient.addListener(AnamEvent.MESSAGE_HISTORY_UPDATED, handleMessage);

// Remove listener when done
anamClient.removeListener(AnamEvent.MESSAGE_HISTORY_UPDATED, handleMessage);
```

## Learn More

<CardGroup cols={2}>
  <Card title="Events API Reference" icon="code" href="/javascript-sdk/reference/events">
    Complete event reference with callback signatures
  </Card>

  <Card title="Client Tools Guide" icon="browser" href="/personas/tools/client-tools">
    Guide for creating and handling client tools
  </Card>
</CardGroup>
