

# Store and retrieve conversation history and context with session management APIs
<a name="sessions"></a>

**Note**  
The session management APIs are in preview and are subject to change.

 The session management APIs enable you to save checkpoints for ongoing conversations in generative AI applications built with open-source frameworks, such as LangGraph and LlamaIndex. You can use the APIs to securely manage state and conversation context across multi-step generative AI workflows. You don’t have to build, maintain, or scale custom back-end solutions for state and context persistence. 

With the session management APIs, you can do the following:
+ Checkpoint workflow stages for iterative testing and human-in-the-loop workflows.
+  Resume conversations and tasks from the point of interruption. 
+ Review session logs to analyze workflow stages and debug failures.

Because sessions are a resource in Amazon Bedrock, you can control access to the session with AWS Identity and Access Management (IAM). By default, Amazon Bedrock uses AWS-managed keys for session encryption, including session metadata, or you can use your own AWS KMS key. For more information, see [Session encryption](sessions-encryption.md).

 You can create and manage Amazon Bedrock sessions with the Amazon Bedrock APIs, or AWS SDKs. For applications built on LangGraph, you can use the `BedrockSessionSaver` class from the `langgraph_checkpoint_aws.saver` library. This is a custom implementation of the LangGraph CheckpointSaver. For more information, see [langgraph-checkpoint-aws](https://github.com/langchain-ai/langchain-aws/tree/main/libs/langgraph-checkpoint-aws) in the [LangChain](https://github.com/langchain-ai) GitHub repository.

**Note**  
You use a session to store state and conversation history for generative AI applications built with open-source frameworks. For Amazon Bedrock Agents, the service automatically manages conversation context and associates them with the agent-specific sessionId you specify in the [InvokeAgent](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_InvokeAgent.html) API operation.

**Topics**
+ [Use case example](#sessions-use-case)
+ [Workflow](#sessions-workflow)
+ [Considerations](#sessions-considerations)
+ [Session encryption](sessions-encryption.md)
+ [Create a session to prepare to store conversation history and context](sessions-create.md)
+ [Store conversation history and context in a session](sessions-store-coversation.md)
+ [Retrieve conversation history and context from a session](sessions-retrieve-coversation.md)
+ [End a session when the user ends the conversation](sessions-end-session.md)
+ [Delete a session and all of its data](sessions-delete-session.md)
+ [Store and retrieve conversation history and context with the BedrockSessionSaver LangGraph library](sessions-opensource-library.md)

## Use case example
<a name="sessions-use-case"></a>

You might have an application that uses a LangGraph agent to help customers plan travel itineraries. A user can start a conversation with this agent to create the itinerary for an upcoming trip, adding destinations, preferred hotels, and flight details. 

With session management APIs, the agent can save intermediate states and persistent context across the extended multi-step interaction. The agent could use an Amazon Bedrock session to checkpoint its state after each destination is added, preserving details about the customer's preferences.

If the conversation is interrupted or fails, the agent can resume the session later with context intact, including text and images. This allows the agent continue without requiring the customer to repeat information. Also, in the case of failure, you can investigate the session details to debug the cause.

## Workflow
<a name="sessions-workflow"></a>

The workflow to use the Session Management APIs is as follows. For information about using the BedrockSessionSaver library, see [Manage sessions with BedrockSessionSaver LangGraph library](sessions-opensource-library.md). 
+ **Create a session** – When your end user first starts the conversation, you create a session with the [CreateSession](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_CreateSession.html) API operation and specify an ID for the session. You use this ID when you store and retrieve the conversation state.
+ **Store conversations and context** – As your end users interact with your generative AI assistant, use the [CreateInvocation](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_CreateInvocation.html) API to create a grouping of interactions within the session. For each invocation, use the [PutInvocationStep](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_PutInvocationStep.html) API operations to store fine-grained state checkpoints, including text and images, for each interaction.
+ **Retrieve conversation history and context** – Use the [GetSession](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_GetSession.html), [ListInvocations](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_ListInvocations.html), and [GetInvocationStep](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_GetInvocationStep.html) API operations to retrieve session metadata and interaction details.
+ **End the session** – When the session is complete, end the session with the [EndSession](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_EndSession.html) API operation. After you end a session, you can still access its content but you can’t add to it. To delete the session and it's content, you use the [DeleteSession](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_DeleteSession.html) API operation.

## Considerations
<a name="sessions-considerations"></a>

Before you create and manage sessions, note the following:
+ You can create and manage sessions with the Amazon Bedrock APIs and AWS SDKs. You can’t use the AWS Management Console to manage sessions.
+ For agent applications built on LangGraph, you can use the `BedrockSessionSaver` class from the `langchain-aws` library. This is a custom implementation of the LangGraph CheckpointSaver. For information about using the BedrockSessionSaver library, see [Manage sessions with BedrockSessionSaver LangGraph library](sessions-opensource-library.md). To view the code directly, see [langgraph-checkpoint-aws](https://github.com/langchain-ai/langchain-aws/tree/main/libs/langgraph-checkpoint-aws) in the [LangChain](https://github.com/langchain-ai) GitHub repository.
+ If you specify a customer managed AWS KMS key when you create a session, the user or role creating the session must have permission to use the key. For more information, [Session encryption](sessions-encryption.md).
+ The Session Management APIs have the following quotas:
  + Number of invocation steps in a session across all invocations – 1000
  + Maximum size of each invocation step – 50 MB
  + IdleSession Timeout – 1 hour
  + Retention period – Session data is automatically deleted after 30 days

# Session encryption
<a name="sessions-encryption"></a>

By default, Amazon Bedrock uses AWS-managed keys for session encryption. For more information about the default encryption Amazon Bedrock uses, see [Data encryption](https://docs.aws.amazon.com/bedrock/latest/userguide/data-encryption.html).

 For an additional layer of security, you can encrypt session data with a customer managed key. To use your own key, specify the Amazon Resource Name (ARN) of the key for the `KMSKeyArn` in the [CreateSession](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_CreateSession.html) API operation. The user or role creating the session must have permission to use the key. You can use the following IAM policy to grant the required permissions. 

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:GenerateDataKey"
            ],
            "Resource": "arn:aws:kms:us-east-1:123456789012:key/${key-id}",
            "Condition": {
                "StringLike": {
                    "kms:EncryptionContext:aws:bedrock:session:arn": "arn:aws:bedrock:us-east-1:123456789012:session/*"
                },
                "StringEquals": {
                    "kms:ViaService": "bedrock.us-east-1.amazonaws.com"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "kms:DescribeKey"
            ],
            "Resource": "arn:aws:kms:us-east-1:123456789012:key/${key-id}",
            "Condition": {
                "StringEquals": {
                    "kms:ViaService": "bedrock.us-east-1.amazonaws.com"
                }
            }
        }
    ]
}
```

------

# Create a session to prepare to store conversation history and context
<a name="sessions-create"></a>

To create a session, you use the [CreateSession](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_CreateSession.html) API operation. In the response, Amazon Bedrock returns a unique session ID and Amazon Resource Name (ARN) for the session. You use either the session ID or the ARN when you use the [CreateInvocation](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_CreateInvocation.html) and [PutInvocationStep](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_PutInvocationStep.html) API operations to record the session events. 

When you create a session, you can specify a AWS KMS key to encrypt conversations. For information about encryption, see [Session encryption](sessions-encryption.md).

```
def create_session():
try:
    session_id = client.create_session(
        encryptionKeyArn="arn:aws:kms:us-west-2:<123456789012>:key/keyId",
        tags={
            'Environment': 'Test',
            'Project': 'Demo'
        },
        sessionMetadata={
            "deviceType": "mobile"
        }
    )["sessionId"]
    print("Session created. Session ID: " + session_id)
    return session_id
except ClientError as e:
    print(f"Error: {e}")
```

# Store conversation history and context in a session
<a name="sessions-store-coversation"></a>

After you create a session, use the [CreateInvocation](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_CreateInvocation.html) API to create a grouping of interactions within the session. For each grouping, use the [PutInvocationStep](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_PutInvocationStep.html) API operations to store state checkpoints, including text and images, for each interaction.

How you organize invocation steps within invocations depends on your use case. For example, if you have an agent that agent that helps customers make travel reservations, your invocation and invocation steps might be as follows:
+ The invocation might serve as the grouping for the text from a conversation an agent has with a customer checking room availability at a specific hotel for different nights.
+ Each invocation step might be each message between the agent and the user, and each step the agent takes to retrieve the availability.

In your [PutInvocationStep](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_PutInvocationStep.html) API, you can import images associated with the conversation.
+ You can include up to 20 images. Each image's size, height, and width must be no more than 3.75 MB, 8000 px, and 8000 px, respectively.
+ You can import the following types of images:
  + PNG
  + JPEG
  + GIF
  + WEBP

**Topics**
+ [CreateInvocation example](#session-create-invocation)
+ [PutInvocationSteps example](#session-put-invocation-step)

## CreateInvocation example
<a name="session-create-invocation"></a>

The following code example shows how to add an invocation to an active session with the AWS SDK for Python (Boto3). For the `sessionIdentifier`, you can specify either the session's sessionId or its Amazon Resource Name (ARN). For more information about the API, see [CreateInvocation](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_CreateInvocation.html). 

```
def create_invocation(session_identifier):
try:
    invocationId = client.create_invocation(
        sessionIdentifier=session_identifier,
        description="User asking about weather in Seattle",
        invocationId="12345abc-1234-abcd-1234-abcdef123456"
    )["invocationId"]
    print("invocation created")
    return invocationId
except ClientError as e:
    print(f"Error: {e}")
```

## PutInvocationSteps example
<a name="session-put-invocation-step"></a>

The following code example shows how to add an invocation step to an active session with the AWS SDK for Python (Boto3). The code adds text and an image in from the working directory. For the `sessionIdentifier`, you can specify either the session's sessionId or its Amazon Resource Name (ARN). For the invocation identifier, specify the unique identifier (in UUID format) of the invocation to add the invocation step to. For more information about the API, see [PutInvocationStep](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_PutInvocationStep.html). 

```
def put_invocation_step(invocation_identifier, session_identifier):
with open('weather.png', 'rb') as image_file:
    weather_image = image_file.read()

try:
    client.put_invocation_step(
        sessionIdentifier=session_identifier,
        invocationIdentifier=invocation_identifier,
        invocationStepId="12345abc-1234-abcd-1234-abcdef123456",
        invocationStepTime="2023-08-08T12:00:00Z",
        payload={
            'contentBlocks': [
                {
                    'text': 'What\'s the weather in Seattle?',

                },
                {
                    'image': {
                        'format': 'png',
                        'source': {'bytes': weather_image}
                    }
                }

            ]
        }
    )
    print("invocation step created")
except ClientError as e:
    print(f"Error: {e}")
```

# Retrieve conversation history and context from a session
<a name="sessions-retrieve-coversation"></a>

Use the [GetSession](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_GetSession.html), [ListInvocations](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_ListInvocations.html), and [GetInvocationStep](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_GetInvocationStep.html) API operations to retrieve session details, details for the interaction state at different checkpoints, and summary information for all invocations.

The following example code shows how to get text and image data for a checkpoint with the AWS SDK for Python (Boto3) and the [GetInvocationStep](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_GetInvocationStep.html) API operation.

```
def get_invocation_step(invocation_identifier, session_identifier, invocation_step_identifier):
try:
    response = client.get_invocation_step(
        sessionIdentifier=session_identifier,
        invocationIdentifier=invocation_identifier,
        invocationStepId=invocation_step_identifier
    )  ["invocationStep"]["payload"]["contentBlocks"]
    print(response)
except ClientError as e:
    print(f"Error: {e}")
```

# End a session when the user ends the conversation
<a name="sessions-end-session"></a>

When the conversations are finished and any agent tasks are completed, end the session with the [EndSession](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_EndSession.html) API operation. After you end a session, you can still access its content but you can’t add to it or restart it. 

The following example code shows how to end a session with the AWS SDK for Python (Boto3).

```
def end_session(session_identifier):
try:
    client.end_session(
        sessionIdentifier=session_identifier
    )
    print("session ended")
except ClientError as e:
    print(f"Error: {e}")
```

# Delete a session and all of its data
<a name="sessions-delete-session"></a>

After you end a session, you can delete it with the [DeleteSession](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_DeleteSession.html) API operation. Deleting a session deletes all Invocations, and InvocationSteps and associated data. You can’t undo deleting a session.

The following example code shows how to delete a session with the AWS SDK for Python (Boto3).

```
def delete_session(session_identifier):
try:
    client.delete_session(
        sessionIdentifier=session_identifier
    )
    print("session deleted")
except ClientError as e:
    print(f"Error: {e}")
```

# Store and retrieve conversation history and context with the BedrockSessionSaver LangGraph library
<a name="sessions-opensource-library"></a>

Instead of directly using the Amazon Bedrock session management APIs, you can store and retrieve conversation history and context in LangGraph with the `BedrockSessionSaver` library. This is a custom implementation of the LangGraph CheckpointSaver. It uses the Amazon Bedrock APIs with a LangGraph-based interface. For more information, see [langgraph-checkpoint-aws](https://github.com/langchain-ai/langchain-aws/tree/main/libs/langgraph-checkpoint-aws) in the [LangChain](https://github.com/langchain-ai) GitHub repository.

The following code sample shows how to use the BedrockSessionSaver LangGraph library to track state as a user interacts with Claude. To use this code sample:
+ Install the required dependencies:
  + boto3
  + langgraph
  + langgraph-checkpoint-aws
  + langchain-core
+ Make sure you have access to the Claude 3.5 Sonnet v2 model in your account. Or you can modify the code to use a different model.
+ Replace `REGION` with your region:
  + This Region for your runtime client and the BedrockSessionSaver must match. 
  + It must support Claude 3.5 Sonnet v2 (or the model you are using).

```
import boto3
from typing import Dict, TypedDict, Annotated, Sequence, Union
from langgraph.graph import StateGraph, END
from langgraph_checkpoint_aws.saver import BedrockSessionSaver
from langchain_core.messages import HumanMessage, AIMessage
import json


# Define state structure
class State(TypedDict):
    messages: Sequence[Union[HumanMessage, AIMessage]]
    current_question: str


# Function to get response from Claude
def get_response(messages):
    bedrock = boto3.client('bedrock-runtime', region_name="us-west-2")
    prompt = "\n".join([f"{'Human' if isinstance(m, HumanMessage) else 'Assistant'}: {m.content}"
                        for m in messages])

    response = bedrock.invoke_model(
        modelId="anthropic.claude-3-5-sonnet-20241022-v2:0",
        body=json.dumps({
            "anthropic_version": "bedrock-2023-05-31",
            "max_tokens": 1000,
            "messages": [
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "text",
                            "text": prompt
                        }
                    ]
                }
            ],
            "temperature": 0.7
        })
    )

    response_body = json.loads(response['body'].read())
    return response_body['content'][0]['text']


# Node function to process user question
def process_question(state: State) -> Dict:
    messages = list(state["messages"])
    messages.append(HumanMessage(content=state["current_question"]))

    # Get response from Claude
    response = get_response(messages)
    messages.append(AIMessage(content=response))

    # Print assistant's response
    print("\nAssistant:", response)

    # Get next user input
    next_question = input("\nYou: ").strip()

    return {
        "messages": messages,
        "current_question": next_question
    }


# Node function to check if conversation should continue
def should_continue(state: State) -> bool:
    # Check if the last message was from the user and contains 'quit'
    if state["current_question"].lower() == 'quit':
        return False
    return True


# Create the graph
def create_graph(session_saver):
    # Initialize state graph
    workflow = StateGraph(State)

    # Add nodes
    workflow.add_node("process_question", process_question)

    # Add conditional edges
    workflow.add_conditional_edges(
        "process_question",
        should_continue,
        {
            True: "process_question",
            False: END
        }
    )

    # Set entry point
    workflow.set_entry_point("process_question")

    return workflow.compile(session_saver)


def main():
    # Create a runtime client
    agent_run_time_client = boto3.client("bedrock-agent-runtime",
                                         region_name="REGION")
            
    # Initialize Bedrock session saver. The Region must match the Region used for the agent_run_time_client.
    session_saver = BedrockSessionSaver(region_name="REGION")

    # Create graph
    graph = create_graph(session_saver)

    # Create session
    session_id = agent_run_time_client.create_session()["sessionId"]
    print("Session started. Type 'quit' to end.")

    # Configure graph
    config = {"configurable": {"thread_id": session_id}}

    # Initial state
    state = {
        "messages": [],
        "current_question": "Hello! How can I help you today? (Type 'quit' to end)"
    }

    # Print initial greeting
    print(f"\nAssistant: {state['current_question']}")

    state["current_question"] = input("\nYou: ").strip()

    # Process the question through the graph
    graph.invoke(state, config)
    print("\nSession contents:")
    for i in graph.get_state_history(config, limit=3):
        print(i)


if __name__ == "__main__":
    main()
```