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

# Events

> Listen to widget events for analytics and custom behavior

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](/personas/tools/overview), 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](/personas/tools/client-tools) 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`](/personas/tools/client-tools#using-registertoolcallhandler-recommended) instead of the embed widget.
</Note>

## Common patterns

<AccordionGroup>
  <Accordion title="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>

  <Accordion title="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>

  <Accordion title="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.");
      }
    });
    ```
  </Accordion>
</AccordionGroup>
