# Multi-turn conversations

> Carry context across turns with conversation_id.

Source: https://maincode.com/docs/python-client-sdk-multi-turn
Section: Client SDK · Matilda documentation

---

The client SDK does not have a `Session` class. Multi-turn conversations are managed by passing a `conversation_id` to each chat call. The server reconstructs the full conversation history server-side from the session store.

## Pattern

1. Generate a conversation ID (any unique string, e.g. a UUID).
2. Pass it to every `chat.create()` or `chat.stream()` call.
3. The server maintains the conversation history — you only send the latest message.

> **Caution** — **Important:** Omitting `conversation_id` auto-creates a new conversation per call, and the response never returns that auto-created ID. Mint your own ID (e.g. `uuid.uuid4()`) and thread it through — it's the only way to continue a conversation.

```python title="conversation.py"
import asyncio
from uuid import uuid4

from matilda_client import MatildaClient


async def main():
    async with MatildaClient() as client:
        # Authenticate with device flow — token refresh is handled automatically
        if not await client.auth.get_tokens():
            await client.auth.login_with_device_flow(client_id="matilda-code")

        conversation_id = str(uuid4())

        # Turn 1
        r1 = await client.chat.create(
            input="What is the capital of France?", conversation_id=conversation_id
        )
        print(r1.output_text)  # "Paris"

        # Turn 2 — server remembers the previous turn
        r2 = await client.chat.create(
            input="What about Germany?", conversation_id=conversation_id
        )
        print(r2.output_text)  # "Berlin"

        # Turn 3
        r3 = await client.chat.create(
            input="And Italy?", conversation_id=conversation_id
        )
        print(r3.output_text)  # "Rome"


asyncio.run(main())
```

## Contrasting with the agent SDK

The Matilda [agent SDK](https://maincode.com/docs/python-agent-sdk-overview) provides a `Session` class that wraps an `Agent` with auto-managed `conversation_id`, a `turns` list, and session-level defaults. If you need client-side tool execution, approval loops, or session state management, consider the agent SDK. For simple chatbot integrations, the client SDK's `conversation_id` pattern is sufficient.

## Retrieving conversation history

```python
# List all conversations
result = await client.conversations.list(limit=50)

# Retrieve a specific conversation with full message history
conv = await client.conversations.retrieve(conversation_id)
for msg in conv["messages"]:
    print(f"[{msg['role']}] {msg['content']}")
```
