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

# Anam Widget Events

> Listen for Anam Widget lifecycle and conversation events so your site can record analytics, update its interface, and respond to sessions.

The `<anam-agent>` element dispatches standard [DOM Custom Events](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) that cross the Shadow DOM boundary, so you can listen to them with `addEventListener` on the element itself or any ancestor. Event data is available on `event.detail`.

## Listening to events

```javascript theme={"system"}
const widget = document.querySelector("anam-agent");

widget.addEventListener("anam-agent:session-started", (e) => {
  console.log("Session started:", e.detail.sessionId);
});

widget.addEventListener("anam-agent:message-received", (e) => {
  console.log(`${e.detail.role}: ${e.detail.content}`);
});

widget.addEventListener("anam-agent:error", (e) => {
  console.error(`Error [${e.detail.code}]: ${e.detail.message}`);
});
```

## Events reference

| Event Name | Payload | Description |
| - | - | - |
| `anam-agent:session-started` | `{ sessionId: string }` | A WebRTC session has been established. |
| `anam-agent:session-ended` | `{ sessionId: string, reason: string }` | The session has ended (user-initiated or server-side). |
| `anam-agent:message-received` | `{ role: "user" \| "agent", content: string }` | A transcript message was received from either party. |
| `anam-agent:message-sent` | `{ content: string }` | The user sent a text message via the input field. |
| `anam-agent:expanded` | `{}` | The widget was expanded (floating layout only). |
| `anam-agent:collapsed` | `{}` | The widget was collapsed (floating layout only). |
| `anam-agent:error` | `{ code: string, message: string }` | An error occurred (auth failure, network issue, etc.). |
| `anam-agent:mic-muted` | `{}` | The user muted their microphone. |
| `anam-agent:mic-unmuted` | `{}` | The user unmuted their microphone. |
| `anam-agent:tool-call-started` | `{ toolName: string, toolCallId: string, toolType: string, toolSubtype?: string, arguments: object }` | The persona invoked a tool. |
| `anam-agent:tool-call-completed` | `{ toolName: string, toolCallId: string, toolType: string, toolSubtype?: string, result: unknown, executionTime: number, documentsAccessed?: string[] }` | A tool call finished successfully. |
| `anam-agent:tool-call-failed` | `{ toolName: string, toolCallId: string, toolType: string, toolSubtype?: string, errorMessage: string, executionTime: number }` | A tool call failed. |

In the tool-call payloads, `toolType` is `"client"` for browser-side tools and `"server"` for tools that run on Anam's side. The optional `toolSubtype` further identifies the tool and is currently set for server tools, such as `"webhook"` or `"knowledge"`. `executionTime` is in milliseconds, and `documentsAccessed` is present only for knowledge (RAG) tools.

## Reacting to tool calls

When your persona invokes a [tool](https://anam.ai/docs/personas/tools/overview.md), the widget surfaces the tool-call lifecycle as DOM events, so your page can react to it without wiring up the JavaScript SDK directly.

Use the `toolType` field to act only on client-side tools (those meant to run in the browser, such as navigation or cart updates) and ignore server-side tools (webhook and knowledge tools that run on Anam's side):

```javascript theme={"system"}
const widget = document.querySelector("anam-agent");

widget.addEventListener("anam-agent:tool-call-started", (e) => {
  const { toolName, toolType, arguments: args } = e.detail;

  // Server-side tools (webhook, knowledge) run on Anam's side — ignore them here.
  if (toolType !== "client") return;

  if (toolName === "redirect") {
    window.location.href = args.url;
  }
});
```

The `tool-call-completed` and `tool-call-failed` events report the outcome of each call, which is useful for logging and analytics:

```javascript theme={"system"}
widget.addEventListener("anam-agent:tool-call-completed", (e) => {
  const { toolName, executionTime, documentsAccessed } = e.detail;
  console.log(`${toolName} finished in ${executionTime}ms`);
  if (documentsAccessed) {
    console.log("Documents used:", documentsAccessed);
  }
});

widget.addEventListener("anam-agent:tool-call-failed", (e) => {
  const { toolName, errorMessage } = e.detail;
  console.error(`${toolName} failed: ${errorMessage}`);
});
```

You still define and configure the tools on your persona in [Anam Lab](https://lab.anam.ai). See [Client Tools and Events](https://anam.ai/docs/personas/tools/client-tools.md) for how tools are created.

> [!NOTE]
>
> These are notification events — the widget reports tool calls but does not send a value back to the persona. Use client-side tools with the widget as fire-and-forget actions (`awaitResult: false`). If you need to return a result to the LLM, integrate with the JavaScript SDK's [`registerToolCallHandler`](https://anam.ai/docs/personas/tools/client-tools#using-registertoolcallhandler-recommended) instead of the embed widget.

## Common patterns

> [accordion] Analytics tracking
>
> Track session starts, message counts, and engagement duration:
>
> ```javascript theme={"system"}
> const widget = document.querySelector("anam-agent");
> let sessionStart;
>
> widget.addEventListener("anam-agent:session-started", (e) => {
>   sessionStart = Date.now();
>   analytics.track("avatar_session_started", {
>     sessionId: e.detail.sessionId,
>   });
> });
>
> widget.addEventListener("anam-agent:session-ended", (e) => {
>   const duration = Date.now() - sessionStart;
>   analytics.track("avatar_session_ended", {
>     sessionId: e.detail.sessionId,
>     reason: e.detail.reason,
>     durationMs: duration,
>   });
> });
>
> widget.addEventListener("anam-agent:message-received", (e) => {
>   if (e.detail.role === "agent") {
>     analytics.track("avatar_message", {
>       contentLength: e.detail.content.length,
>     });
>   }
> });
> ```

> [accordion] Show or hide page elements
>
> React to widget expand/collapse to adjust your page layout:
>
> ```javascript theme={"system"}
> const widget = document.querySelector("anam-agent");
> const sidebar = document.getElementById("sidebar");
>
> widget.addEventListener("anam-agent:expanded", () => {
>   sidebar.style.marginRight = "420px";
> });
>
> widget.addEventListener("anam-agent:collapsed", () => {
>   sidebar.style.marginRight = "0";
> });
> ```

> [accordion] Error handling
>
> Display user-facing messages or trigger fallback behavior:
>
> ```javascript theme={"system"}
> const widget = document.querySelector("anam-agent");
>
> widget.addEventListener("anam-agent:error", (e) => {
>   const { code, message } = e.detail;
>
>   if (message.includes("Origin not allowed")) {
>     showBanner("Widget configuration required. Contact your admin.");
>   } else if (message.includes("Too many requests")) {
>     showBanner("Please wait a moment before trying again.");
>   } else {
>     showBanner("Something went wrong. Please try again.");
>   }
> });
> ```


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