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

# Python Quickstart

> Install the Anam Python SDK, create a session token, and stream your first interactive avatar from a Python application.

Build this Python quickstart with a coding agent

Paste this prompt into Cursor, Claude Code, Codex, or another coding agent.

Copy prompt

This quickstart shows you how to connect to an Anam persona and receive audio and video frames.

## Prerequisites

* An Anam API key ([get one here](https://anam.ai/docs/api-key.md))
* A persona ID from [Anam Lab](https://lab.anam.ai)
* The `anam` package installed (`pip install anam`)

## Connect and stream

```python theme={"system"}
import asyncio
from anam import AnamClient

async def main():
    client = AnamClient(
        api_key="your-api-key",
        persona_id="your-persona-id",
    )

    async with client.connect() as session:
        async def consume_video():
            async for frame in session.video_frames():
                img = frame.to_ndarray(format="rgb24")
                print(f"Video: {frame.width}x{frame.height}")

        async def consume_audio():
            async for frame in session.audio_frames():
                samples = frame.to_ndarray()
                print(f"Audio: {samples.size} samples")

        await asyncio.gather(consume_video(), consume_audio())

asyncio.run(main())
```

This connects to the persona and prints frame metadata as it arrives. Replace the `print` calls with your own rendering logic.

> [!NOTE]
>
> When you save SDK video frames to a file, set the output writer or muxer to 25 fps. This is an output encoding hint; `session.video_frames()` yields frames as they arrive. Encoding saved output at 30 fps can make audio and video drift out of sync.

> [!WARNING]
>
> Never expose your API key in client-side code. The Python SDK is designed for server-side use. See [Usage in Production](https://anam.ai/docs/production.md) for session token patterns.

## Send a message

You can send text to the persona during a session:

```python theme={"system"}
async with client.connect() as session:
    await session.talk("Hello, tell me about yourself.")
```

## Use the event-driven API

If you prefer callbacks over async iterators:

```python theme={"system"}
from anam import AnamClient, AnamEvent

client = AnamClient(
    api_key="your-api-key",
    persona_id="your-persona-id",
)

@client.on(AnamEvent.CONNECTION_ESTABLISHED)
async def on_connected():
    print("Connected to persona")

@client.on(AnamEvent.MESSAGE_STREAM_EVENT_RECEIVED)
async def on_message(event):
    print(f"{event.role}: {event.content}")

await client.connect()
```

## Multi-utterance persona turns

In a tool-driven response, a persona can speak before a tool call and continue after the tool returns. With `anam` version 0.11.0 or later, completed persona messages expose those spoken parts through the optional `utterances` field:

```python theme={"system"}
from anam import AnamEvent, Message, MessageRole

@client.on(AnamEvent.MESSAGE_HISTORY_UPDATED)
async def on_message_history(messages: list[Message]):
    message = messages[-1]

    if message.role != MessageRole.ASSISTANT:
        return

    if message.utterances:
        for utterance in message.utterances:
            print(f"[{utterance.id}] {utterance.content}")
    else:
        print(message.content)
```

`message.content` remains the complete concatenated turn. `message.utterances` is `None` for user messages and whenever the engine does not provide utterance IDs, so continue to handle `content` as the fallback.

For live captions, persona `MESSAGE_STREAM_EVENT_RECEIVED` payloads include an optional `utterance_id`. Consecutive chunks with the same ID belong to the same utterance; append their `content` in arrival order.

> [!NOTE]
>
> Multi-utterance turns require an LLM that supports interleaved tool calling: text before and after a tool call in one turn. Anam-provided LLMs hosted by OpenAI or Azure support this behavior; LLMs hosted by Groq do not.

## Next steps

> [card] [GitHub Repository](https://github.com/anam-org/python-sdk)
>
> Source code, full API reference, and examples

> [card] [Cookbook: Python BYO LLM](https://anam.ai/cookbook/python-byo-llm)
>
> Bring your own LLM with the Python SDK


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