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

# Client events

> Let the agent act on your page during the call: open a page, show a product, fill in a form.

A client event is a tool that runs on **your page** instead of your server. When the agent calls it, the event and its
arguments go straight to the page your [widget or iframe](https://docs.talking-avatar.dev/voice-agents/share-and-embed.md#embed-on-your-website) is on,
and your code reacts: open the pricing page, show a product, fill in a form, highlight a slot in a calendar.

| | Tool on **Your server** | Client event (**Your page**) |
| - | - | - |
| Goes to | Your HTTPS endpoint | The page your widget or iframe is on |
| The agent | Waits for your reply (up to 10 seconds) and uses it | Carries on right away |
| Use it to | Look things up, take actions: an order's status, a booking, your CRM | Change what the caller sees |

## Set one up

1. Open the agent's **Tools** tab and click **Add tool**.
2. Set **Runs on** to **Your page**.
3. Fill in the **Function name** (such as `show_pricing`), **When to use it** (the agent reads it to decide when to call
   it) and its **Parameters**.
4. Click **Save changes**.

Parameters work like a [tool's](https://docs.talking-avatar.dev/voice-agents/tools.md#add-a-custom-tool): one row each in **Simple** (a name, a type, a
description, required or not), or a JSON Schema object in **JSON Schema**, for choices, lists and nested objects. For
example, `show_pricing` with a choice of plan:

```json theme={null}
{
  "type": "object",
  "properties": {
    "plan": {
      "type": "string",
      "enum": ["starter", "pro", "enterprise"],
      "description": "The plan the caller asked about"
    }
  },
  "required": ["plan"]
}
```

> [!TIP]
>
> Mention it in the agent's [prompt](https://docs.talking-avatar.dev/voice-agents/prompting.md) too, such as *When the caller asks about pricing, show the
> plan with show\_pricing while you explain it*.

## Listen on your page

Add one listener to the page your widget or iframe is on. It works the same for both.

```js JavaScript theme={null}
window.addEventListener("message", (event) => {
  if (event.origin !== "https://app.talking-avatar.dev") return;
  if (event.data?.type !== "talking-avatar:client-event") return;

  const { tool, arguments: args } = event.data;
  if (tool === "show_pricing") showPricing(args.plan); // { plan: "pro" }
});
```

```jsx React theme={null}
import { useEffect } from "react";

export function useClientEvents(handlers) {
  useEffect(() => {
    const onMessage = (event) => {
      if (event.origin !== "https://app.talking-avatar.dev") return;
      if (event.data?.type !== "talking-avatar:client-event") return;
      handlers[event.data.tool]?.(event.data.arguments);
    };
    window.addEventListener("message", onMessage);
    return () => window.removeEventListener("message", onMessage);
  }, [handlers]);
}

// useClientEvents({ show_pricing: ({ plan }) => setPlan(plan) });
```

## What your page receives

```json theme={null}
{
  "type": "talking-avatar:client-event",
  "tool": "show_pricing",
  "arguments": { "plan": "pro" }
}
```

| Field | Description |
| - | - |
| `type` | Always `talking-avatar:client-event` |
| `tool` | The function name |
| `arguments` | The arguments the agent collected, matching the parameters |

## How it behaves

* **Fire-and-forget.** The agent learns `Done.` as soon as the event is sent, and the conversation carries on. Your
  page's reply doesn't reach the agent: to give it an answer, use a [tool on your server](https://docs.talking-avatar.dev/voice-agents/tools.md).
* **Only around a call.** Events are sent while a call is live, once per tool call. The agent may call the same tool
  more than once.
* **Only in an embed.** The widget and the iframe send them to your page. The share link (no page around it) and test
  calls in the dashboard don't.

> [!WARNING]
>
> Check `event.origin`, so only the agent's call page can send you events. Your page gets the arguments as the agent
> wrote them, from the conversation: treat them like user input, and check them before you act on them.


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