> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Multi Turn Conversations with the Claude SDK

> Explains using ClaudeSDKClient to maintain multi-turn conversation state for iterative code and config editing, discusses memory costs, safety controls, and interactive builder patterns.

Make your Claude-based agents remember previous turns so they can build and refine things across a conversation.

Short-lived calls to `query` work well for one-off tasks: you ask, Claude answers, the session ends, and the model forgets everything. But many workflows—like iteratively crafting infrastructure templates or incrementally editing code—need memory. That’s where the stateful client comes in: it preserves the conversation so each new turn can reference everything that came before.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/_CTwEK7wfhlq4R-D/images/Learn-By-Doing-Building-AI-Agents-with-Claude-Agent-SDK/Foundations/Multi-Turn-Conversations-with-the-Claude-SDK/from-forgetful-to-stateful-s3-aes256.jpg?fit=max&auto=format&n=_CTwEK7wfhlq4R-D&q=85&s=ffe015ac56cc87a6172906ca17d08bc4" alt="A split infographic titled &#x22;From Forgetful to Stateful&#x22; comparing a single-turn query (left) that forgets context and returns &#x22;What bucket? I have no memory of that.&#x22; with a multi-turn client (right) that retains context and successfully adds &#x22;AES256 to your bucket.&#x22; The panels show example conversation bubbles about creating an S3 bucket and adding encryption, highlighting &#x22;Memory wiped between calls&#x22; versus &#x22;Context kept across every turn.&#x22;" width="1920" height="1080" data-path="images/Learn-By-Doing-Building-AI-Agents-with-Claude-Agent-SDK/Foundations/Multi-Turn-Conversations-with-the-Claude-SDK/from-forgetful-to-stateful-s3-aes256.jpg" />
</Frame>

## Stateful client: ClaudeSDKClient

Use `ClaudeSDKClient` when you need cross-turn memory. Open the client with an async context manager:

* Enter the session with `async with ClaudeSDKClient(...)` to start a stateful connection.
* Exit the context to shut the session down cleanly.

Within that context the pattern intentionally splits into two steps:

1. Send user instructions with `client.query(...)`.
2. Read the assistant’s replies using `client.receive_response()`.

This split (send, then receive) lets the session remain open across many turns. The fused `query` helper performs both steps at once for short-lived interactions; the stateful client separates them so the conversation can accumulate.

### Minimal send/receive example

```python theme={null}
# example_send_receive.py
from claude_agent_sdk import ClaudeSDKClient
from claude_agent_sdk.messages import AssistantMessage
from claude_agent_sdk.blocks import TextBlock
import asyncio

async def main(options):
    async with ClaudeSDKClient(options=options) as client:
        # Turn 1: send an instruction
        await client.query("Create an S3 bucket template")

        # Read assistant responses as they arrive for this and subsequent turns
        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        print(block.text)

# To run:
# asyncio.run(main(options))
```

## How the memory works — and its cost

Every time you call `client.query`, the SDK includes the full conversation history in the request payload. That means:

* Turn 1 sends one message.
* Turn 2 sends turn 1 + new message.
* Turn N sends all N messages.

Because the full history is sent on every call, Claude can recall previous facts (e.g., “Alex”, favorite color, or earlier template details) without you repeating them. That makes iterative workflows natural: the model edits what it created earlier rather than starting from scratch.

But there’s a tradeoff: the request payload grows every turn, which increases token usage, latency, and cost—and eventually risks hitting the model’s context window.

<Callout icon="warning" color="#FF6B6B">
  Preserving full conversation history improves continuity but increases token usage and latency. Monitor the size of your history and consider summarizing, pruning, or checkpointing older turns to control costs and avoid context limits.
</Callout>

## Safety controls: permission mode and allowed tools

Before Claude can modify files or run commands, decide what it’s allowed to do. The SDK exposes two complementary controls:

* Permission mode (how freely Claude may act), e.g., `acceptEdits` to auto-approve file edits or `default` for a more cautious, confirmation-first posture.
* Allowed tools (a whitelist of actions Claude may take), e.g., `Write`, `Bash`, etc. An empty list means the agent can only provide guidance.

Together they enable safe, production-ready agents.

| Control | Purpose | Example |
| -: | - | - |
| Permission mode | How the agent handles action requests | `acceptEdits`, `default` |
| Allowed tools | Which system-level capabilities the agent may use | `["Write"]`, `["Bash", "Write"]`, `[]` (none) |

Use stricter modes and minimal tool sets for sensitive environments; relax them in trusted automation pipelines.

## Iterative infrastructure building (practical payoff)

With a stateful client you can grow a single template across multiple turns. For example:

* Turn 1: “Create a starter S3 bucket and save it as `s3template.yaml`.”
* Turn 2: “Enable versioning and AES-256 encryption.”
* Turn 3: “Add lifecycle rules, public access block, and tags.”

Because the agent keeps the earlier file in its conversation history, it edits that same file rather than re-creating or duplicating it.

Here’s a representative CloudFormation snippet Claude might produce and refine across turns:

```yaml theme={null}
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      LifecycleConfiguration:
        Rules:
          - Status: Enabled
            Transitions:
              - TransitionInDays: 30
                StorageClass: STANDARD_IA
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
      Tags:
        - Key: Environment
          Value: Production
```

This single-file, multi-turn workflow is far more ergonomic than copying and pasting YAML into each prompt for one-off `query` calls.

## Interactive builder pattern

Wrap the stateful loop in a user input loop and you get an interactive builder: open the client once, then repeatedly accept user instructions until the session ends.

```python theme={null}
# interactive_builder.py
from claude_agent_sdk import ClaudeSDKClient
from claude_agent_sdk.messages import AssistantMessage
from claude_agent_sdk.blocks import TextBlock
import asyncio

async def interactive_builder(options, initial_prompt):
    async with ClaudeSDKClient(options=options) as client:
        # Seed the conversation
        await client.query(initial_prompt)

        while True:
            user_input = input("You: ").strip()
            if user_input.lower() == "done":
                print("Exiting interactive builder.")
                break

            # Send the user's instruction as the next turn
            await client.query(user_input)

            # Read and print the assistant's reply for this turn
            async for message in client.receive_response():
                if isinstance(message, AssistantMessage):
                    for block in message.content:
                        if isinstance(block, TextBlock):
                            print("Claude:", block.text)
                            # Assume one assistant reply per turn; break out to accept new input
                            break
                # Stop reading responses for this turn
                break

# To run:
# asyncio.run(interactive_builder(options, "Create a starter S3 bucket template."))
```

Swap the initial prompt, output paths, and allowed tools and this skeleton becomes a code generator, config wizard, or documentation authoring assistant.

## Summary and next steps

Use `ClaudeSDKClient` when conversation continuity matters: it preserves history so the agent can iteratively build, edit, and refine artifacts across multiple turns. Balance that convenience against token growth and latency by pruning or summarizing history where appropriate, and apply permission modes plus a minimal allowed tools list to keep agents safe in production.

Next, you’ll learn how to package common capabilities into reusable components so agents can load and run them on demand.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/learn-by-doing-building-ai-agents-with-claude-agent-sdk/module/c7046700-56e6-42f1-9530-3e70b2e24350/lesson/8eda6bf8-8d1e-4d08-baf6-ffbcd7f889cc" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/learn-by-doing-building-ai-agents-with-claude-agent-sdk/module/c7046700-56e6-42f1-9530-3e70b2e24350/lesson/bf86b91b-3124-4580-a05f-761119fb87fd" />
</CardGroup>


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