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

# Implementing Conversational AI Part 3

> Shows using DynamoDB to persist chat session history and supply context to stateless Bedrock model calls, including trimming history and example Python code

In this lesson we show a complete, practical example that uses DynamoDB to persist conversational state for a chat application while calling a stateless model via the Bedrock Runtime SDK for inference.

At the top of the Python file the example creates two AWS SDK clients:

* A Bedrock Runtime client to perform inference requests.
* A DynamoDB resource client to read and write conversation history.

This sample assumes a DynamoDB table called `ChatSessions` already exists and uses `sessionId` as its partition key.

<Callout icon="lightbulb" color="#1CB2FE">
  Make sure the [DynamoDB](https://aws.amazon.com/dynamodb) table named `ChatSessions` exists and its partition key is `sessionId`. This code does not create the table; it only reads from and writes to it.
</Callout>

Overview

* Purpose: Persist and retrieve chat history per session so a stateless model can be given conversational context on each inference call.
* Key idea: Store messages as an ordered list per `sessionId`, trim history to a bounded size to control model context usage, and overwrite the session item when saving updated history.

Complete example (Python)

* The code below demonstrates loading and saving message history from DynamoDB, trimming history to the most recent messages before sending it to the model, and includes minimal error handling.

```python theme={null}
import boto3
from botocore.exceptions import ClientError
from typing import List, Dict

# AWS clients
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
dynamodb = boto3.resource("dynamodb", region_name="us-east-1")

# DynamoDB table that stores conversation history per session
table = dynamodb.Table("ChatSessions")

MAX_MESSAGES = 10  # Keep only the most recent messages for context control

def load_messages(session_id: str) -> List[Dict]:
    """Load conversation history for a session from DynamoDB."""
    try:
        response = table.get_item(Key={"sessionId": session_id})
        item = response.get("Item")
        if item and "messages" in item:
            return item["messages"]
        return []
    except ClientError as e:
        print(f"Error loading session {session_id}: {e}")
        return []

def save_messages(session_id: str, messages: List[Dict]) -> None:
    """Save conversation history for a session to DynamoDB (overwrites existing history)."""
    try:
        table.put_item(
            Item={
                "sessionId": session_id,
                "messages": messages
            }
        )
    except ClientError as e:
        print(f"Error saving session {session_id}: {e}")
        raise

def trim_messages(messages: List[Dict], max_messages: int = MAX_MESSAGES) -> List[Dict]:
    """Keep only the most recent messages to avoid context window bloat."""
    return messages[-max_messages:]

# Example usage
if __name__ == "__main__":
    # Example flow: load, append a new user message, trim, save
    session_id = "user123"
    history = load_messages(session_id)
    history.append({"role": "user", "content": "Hello"})
    history = trim_messages(history)
    save_messages(session_id, history)

    # A different session uses a different session_id
    other_session = "user456"
    other_history = [{"role": "user", "content": "Hi there"}]
    save_messages(other_session, other_history)
```

Notes on the example

* `load_messages` calls `table.get_item` with `Key={"sessionId": session_id}` to fetch the DynamoDB item that contains the message list. If the item or `messages` attribute is missing, it returns an empty list.
* `save_messages` uses `table.put_item` to write the entire item (partition key plus messages). DynamoDB writes are unconditional by default, so this call overwrites any previous item for that `sessionId`. Conditional writes are possible but are unnecessary for this simple conversation-history use case.
* `trim_messages` keeps only the most recent N messages (controlled by `MAX_MESSAGES`) so you don't exceed the model context window or send unnecessary history.

<Callout icon="warning" color="#FF6B6B">
  `table.put_item` overwrites the item for `sessionId` unconditionally. If you require concurrency control (to avoid lost updates), consider using conditional writes or version attributes (`IfNotExists`, `ConditionExpression`, or atomic counters).
</Callout>

Usage patterns and session semantics

* Using session IDs lets the same user (or conversation) keep state across multiple requests:
  * `chat("user123", "hello")` → persists the conversation under session `user123`.
  * `chat("user123", "what did I just say?")` → loads and continues the same conversation.
  * `chat("user456", "hi there")` → starts a separate conversation stored under `user456`.
* Session IDs can be user IDs, conversation IDs, or any identifier that correlates messages to a specific conversational context.

What to expect when persisting conversational context

* Persisted context enables more natural multi-turn interactions, personalization, and fewer repeated prompts for the same information.

| Benefit | Why it matters |
| - | - |
| Natural, intuitive interactions | The assistant can reference prior exchanges to respond coherently across turns. |
| Personalized customer experiences | Stored history captures user preferences and past inputs that shape responses. |
| Scalable support | An assistant with context can handle a larger workload without linear staffing increases. |
| Easier enterprise integration | Retained knowledge of past tool usage and data simplifies workflow continuity. |
| Faster, more accurate responses | Reusing previously provided user data avoids re-asking and reduces latency in obtaining facts. |

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/BVCvDn4rl3j0TCQq/images/Introduction-to-Amazon-Bedrock/Advanced-Topics-Optional/Implementing-Conversational-AI-Part-3/results-ai-customer-support-benefits.jpg?fit=max&auto=format&n=BVCvDn4rl3j0TCQq&q=85&s=0b4a3224345b1fe8346a5b79958b0da7" alt="A slide titled &#x22;Results&#x22; with five numbered dark-blue panels. Each panel lists a benefit—natural/intuitive user interaction; personalized customer experiences; scalable support without linear staffing growth; integration of AI assistants with enterprise workflows; and improved response times and service availability." width="1920" height="1080" data-path="images/Introduction-to-Amazon-Bedrock/Advanced-Topics-Optional/Implementing-Conversational-AI-Part-3/results-ai-customer-support-benefits.jpg" />
</Frame>

Key points to keep in mind

* Engineering the user experience is as important as model selection. Users expect continuity across turns.
* Models are stateless by default. Your application must provide conversation history on each request to achieve multi-turn continuity.
* Using a `sessionId` as the datastore key is a straightforward, effective pattern. Choose the datastore that matches your scale and latency needs — [DynamoDB](https://aws.amazon.com/dynamodb), [Redis](https://redis.io/), [Aurora](https://aws.amazon.com/rds/aurora), etc.
* Structure stored messages clearly (e.g., `role: user` / `assistant` / `system`), include timestamps when helpful, keep messages ordered chronologically, and always append new messages so the prompt built for the model reflects the proper sequence.
* Bedrock's chat-style runtime APIs (sometimes referenced as "Converse" in docs and examples) support a unified message format that simplifies supplying history and adding guardrails or system instructions.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/BVCvDn4rl3j0TCQq/images/Introduction-to-Amazon-Bedrock/Advanced-Topics-Optional/Implementing-Conversational-AI-Part-3/chatbot-key-takeaways-conversation-state.jpg?fit=max&auto=format&n=BVCvDn4rl3j0TCQq&q=85&s=6130b5f39f3063790e50c30980db23bf" alt="A presentation slide titled &#x22;Key Takeaways&#x22; listing four numbered points about chatbot development. The points note that chatbots aren't just complex AI, conversation state management and correct request structuring are essential, and message history/Converse API support effective conversational apps." width="1920" height="1080" data-path="images/Introduction-to-Amazon-Bedrock/Advanced-Topics-Optional/Implementing-Conversational-AI-Part-3/chatbot-key-takeaways-conversation-state.jpg" />
</Frame>

Best practices and extensions

* Trim history to a bounded length or use summarization to control token usage and cost.
* Consider storing metadata (timestamps, message source, embeddings, or flags) alongside messages to support search, retrieval, or tool routing.
* For complex multi-step workflows or tool access, evaluate Bedrock Agents to orchestrate steps, call external APIs, and manage permissions—at the cost of additional design considerations.
* Monitor and audit stored conversations for privacy and compliance; consider encryption at rest and access controls for your datastore.

This lesson wraps up managing conversational state and supplying that history as context when calling stateless models. Properly storing and supplying history is essential to delivering engaging, personalized conversational experiences.

Coming up next: release management and a feature called shadow release.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/BVCvDn4rl3j0TCQq/images/Introduction-to-Amazon-Bedrock/Advanced-Topics-Optional/Implementing-Conversational-AI-Part-3/whats-next-shadow-release-slide.jpg?fit=max&auto=format&n=BVCvDn4rl3j0TCQq&q=85&s=541bbaf9db7877e8bd855595b537e14d" alt="A presentation slide titled &#x22;What's Next? Release management with Shadow Release&#x22; with a teal circuit/brain icon on a dark curved background and a small &#x22;© Copyright KodeKloud&#x22; note in the corner." width="1920" height="1080" data-path="images/Introduction-to-Amazon-Bedrock/Advanced-Topics-Optional/Implementing-Conversational-AI-Part-3/whats-next-shadow-release-slide.jpg" />
</Frame>

Links and references

* [Amazon DynamoDB](https://aws.amazon.com/dynamodb)
* [Amazon Bedrock (what is Bedrock)](https://docs.aws.amazon.com/bedrock/latest/devguide/what-is-bedrock.html)
* Bedrock Agents — for multi-step workflows, tool access, and orchestration

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/introduction-to-amazon-bedrock/module/7af9f623-7d4e-447a-8b21-6e635dfaccfa/lesson/34d5389b-9834-42ac-9881-1893b7b61cec" />
</CardGroup>


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