- A Bedrock Runtime client to perform inference requests.
- A DynamoDB resource client to read and write conversation history.
ChatSessions already exists and uses sessionId as its partition key.
Make sure the 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.- 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.
- 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.
load_messagescallstable.get_itemwithKey={"sessionId": session_id}to fetch the DynamoDB item that contains the message list. If the item ormessagesattribute is missing, it returns an empty list.save_messagesusestable.put_itemto write the entire item (partition key plus messages). DynamoDB writes are unconditional by default, so this call overwrites any previous item for thatsessionId. Conditional writes are possible but are unnecessary for this simple conversation-history use case.trim_messageskeeps only the most recent N messages (controlled byMAX_MESSAGES) so you don’t exceed the model context window or send unnecessary history.
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).- Using session IDs lets the same user (or conversation) keep state across multiple requests:
chat("user123", "hello")→ persists the conversation under sessionuser123.chat("user123", "what did I just say?")→ loads and continues the same conversation.chat("user456", "hi there")→ starts a separate conversation stored underuser456.
- Session IDs can be user IDs, conversation IDs, or any identifier that correlates messages to a specific conversational context.
- Persisted context enables more natural multi-turn interactions, personalization, and fewer repeated prompts for the same information.

- 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
sessionIdas the datastore key is a straightforward, effective pattern. Choose the datastore that matches your scale and latency needs — DynamoDB, Redis, 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.

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

- Amazon DynamoDB
- Amazon Bedrock (what is Bedrock)
- Bedrock Agents — for multi-step workflows, tool access, and orchestration