# Realtime Avatar API

> Put a live character in your product, on a voice or video call, with your own tools wired into the conversation.

- Canonical: https://realtimeavatar.ai/docs
- Updated: 2026-09-14

## Voice or video, on one meter

**TypeScript**

```tsx
<AvatarCall client={client} avatarId={avatarId} />                 // she is on screen
<AvatarCall client={client} avatarId={avatarId} mode="voice" />   // audio only
```

**Python**

```python
body = {"avatar_id": avatar_id, "mode": "avatar"}   # she is on screen
body = {"avatar_id": avatar_id, "mode": "voice"}    # audio only
```

**It is priced to leave on.** Live-call self-serve overage meters at **about $5 an hour** — $4.80–$5.70 depending on plan — with a free tier to build against. That is the difference between a demo you show and a feature you ship: a companion app can afford to let someone talk.

How she is rendered is in [Creating an avatar](https://realtimeavatar.ai/docs/video).

## She listens while she talks

Most voice AI takes turns like a walkie-talkie: you talk, you stop, it answers. This one is full-duplex — she is hearing you the whole time she is speaking — and in practice that shows up as four things you do not have to build:

- **Interrupt her and she stops**, mid-sentence, and can acknowledge it in character rather than snapping to silence.
- **A cough or an "mm-hm" does not derail her.** A backchannel is not an interruption, and being cut off by one is what makes a system feel brittle.
- **A pause is not the end of your turn.** Whether you are finished is judged by what you said, not by how long you have been quiet — so she neither talks over you nor leaves a gap.
- **Silence and language switches are handled.** Going quiet is a signal she can act on, and she follows a language change inside a single sentence.

Nothing to configure — it is how every call behaves. The one limit worth knowing: she will not talk over you with a new sentence while you are speaking. That is a deliberate trade for the voice and model choices this platform is built on.

## Your tools, wired into the conversation

A character that can only talk is a demo. The useful version books the appointment, checks the order, writes the code and keeps talking while it runs.

You declare a tool the same way you would brief a colleague: what it is called, and *when to reach for it*. The description is the whole teaching signal — she reads it and decides.

**TypeScript**

```ts
import type { AvatarTool } from "realtime-avatar/tools";

export const checkOrder: AvatarTool<{ order_id: string }> = {
  description:
    "Look up the status of a customer's order. Call this whenever they ask " +
    "where something is, or when it will arrive.",
  parameters: {
    type: "object",
    properties: { order_id: { type: "string" } },
    required: ["order_id"],
  },
  execute: async ({ order_id }, { signal }) => {
    const order = await api.order(order_id, { signal });
    return `${order.status}, arriving ${order.eta}.`;
  },
};
```

**Python**

```python
# Tools run in the page that renders the call — there is no hosted execution,
# so there is nothing to declare in Python. Your backend's part is the GRANT:
body["capabilities"] = ["client_tools"]

# The mint schema is strict: a tools[] field on the request itself is a 422.
# The page registers the manifest over RPC once the room is connected.
```

Then your server grants the tool plane at mint, and the page registers the tools once the room is connected. Omitting `execute` is a compile error rather than a timeout you find in production — and a tool has **2.5 seconds** to answer, so anything slow acknowledges fast and delivers the real result out of band:

**TypeScript**

```ts
// server — the session policy grants the client tool plane for this call
session: async ({ avatarId }) => ({ instructions, clientTools: true })

// client — register over RPC after connect; the record key is the tool's name
import { attachAvatarTools } from "realtime-avatar/tools";

const { accepted, rejected } = await attachAvatarTools(room, {
  check_order: checkOrder,
});
```

**Python**

```python
# server — grant the capability on the mint. That is the whole backend part:
body["capabilities"] = ["client_tools"]

# The worker only exposes tool registration to a session minted with the
# capability. If the page reports the registration method is missing, the fix
# is HERE, not in the page.
```

Full pattern: [Tool calling](https://realtimeavatar.ai/docs/tool-calling).

> These examples target `realtime-avatar@0.16.0`. On an older install the exports differ and the compiler will say so — update the package rather than working around it.

## Where to go next

- [Quickstart](https://realtimeavatar.ai/docs/quickstart) — key to live call in three steps.
- [Calls](https://realtimeavatar.ai/docs/sessions) — the policy your server decides, the five states, ending gracefully.
- [Creating an avatar](https://realtimeavatar.ai/docs/video) — one image in; the platform generates the loop and a map of states it switches between, or synthesizes the video live.
- [Tool calling](https://realtimeavatar.ai/docs/tool-calling) — running your own agent loop against a live character.
- [API reference](https://realtimeavatar.ai/docs/api-reference) — every endpoint, scope, and error.

---

Realtime Avatar — realtime AI avatar API & SDK. Docs: https://realtimeavatar.ai/docs · Agent guide: https://realtimeavatar.ai/llms.txt
