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

# Session Class

> Manage conversation sessions, messages, and context retrieval

## Overview

The `Session` class represents a conversation session. It provides methods for adding messages, retrieving context, and processing sessions to update user memories.

## Properties

<ResponseField name="session_id" type="string">
  Unique identifier for the session.
</ResponseField>

<ResponseField name="user_id" type="string">
  ID of the user this session belongs to.
</ResponseField>

<ResponseField name="status" type="SessionStatus">
  Current session status: `PENDING`, `PROCESSING`, `PROCESSED`, or `FAILED`
</ResponseField>

<ResponseField name="metadata" type="dict">
  Session metadata as a dictionary.
</ResponseField>

<ResponseField name="created_at" type="datetime">
  UTC timestamp when the session was created. Can be customized using `custom_created_at_utc` during session creation for benchmarking or importing historical data.
</ResponseField>

<ResponseField name="processed_at" type="datetime | None">
  UTC timestamp when the session was processed, or None if not yet processed.
</ResponseField>

<ResponseField name="auto_process_after_seconds" type="integer | None">
  Seconds of inactivity before auto-processing, or None if disabled.
</ResponseField>

## Session Management Methods

### update()

Update the session metadata.

```python theme={null}
from recallrai.exceptions import SessionNotFoundError

try:
    user = client.get_user("user123")
    session = user.get_session("session-uuid")
    session.update(new_metadata={"type": "support_chat", "priority": "high"})
    print(f"Updated metadata: {session.metadata}")
except SessionNotFoundError as e:
    print(f"Error: {e}")
```

<ParamField path="new_metadata" type="dict" required>
  New metadata to replace the existing metadata. Completely replaces the old metadata.
</ParamField>

**Returns:** None (mutates the instance in place)

**Raises:** `UserNotFoundError`, `SessionNotFoundError`

***

### refresh()

Refresh the session instance with the latest data from the server.

```python theme={null}
session = user.get_session("session-uuid")
session.refresh()
print(f"Current status: {session.status}")
print(f"Processed at: {session.processed_at}")
```

**Returns:** None (updates the instance in place)

**Raises:** `UserNotFoundError`, `SessionNotFoundError`

***

### delete()

Delete this session and all associated data permanently.

```python theme={null}
from recallrai.exceptions import UserNotFoundError, SessionNotFoundError

try:
    session = user.get_session("session-uuid")
    session.delete()
    print("Session deleted successfully")
except SessionNotFoundError as e:
    print(f"Session not found: {e}")
except UserNotFoundError as e:
    print(f"User not found: {e}")
```

<Warning>
  This action is irreversible. Deleting a session permanently removes its messages, memories, memory connections, memory categories, and merge conflicts that were created from it.
</Warning>

**Returns:** None

**Raises:** `UserNotFoundError`, `SessionNotFoundError`

## Message Methods

### add\_message()

Add a message to the session.

```python theme={null}
from recallrai.models import MessageRole
from recallrai.exceptions import InvalidSessionStateError

try:
    session = user.get_session("session-uuid")
    
    # Add a user message
    session.add_message(
        role=MessageRole.USER,
        content="Hello! How are you?"
    )
    
    # Add an assistant message
    session.add_message(
        role=MessageRole.ASSISTANT,
        content="I'm doing well, thank you! How can I help you today?"
    )
    
except InvalidSessionStateError as e:
    print(f"Cannot add messages to a processed session: {e}")
```

<ParamField path="role" type="MessageRole" required>
  Message role: `MessageRole.USER` or `MessageRole.ASSISTANT`
</ParamField>

<ParamField path="content" type="string" required>
  The message content text.
</ParamField>

<Info>
  **MessageRole.USER**: Messages from the user/human\
  **MessageRole.ASSISTANT**: Messages from the AI assistant
</Info>

**Returns:** None

**Raises:** `UserNotFoundError`, `SessionNotFoundError`, `InvalidSessionStateError`

<Warning>
  You cannot add messages to a session that has already been processed.
</Warning>

***

### get\_messages()

Retrieve messages from the session with pagination.

```python theme={null}
session = user.get_session("session-uuid")
messages = session.get_messages(offset=0, limit=50)

print(f"Total messages: {messages.total}")
print(f"Has more: {messages.has_more}")

for msg in messages.messages:
    print(f"{msg.role.value.upper()} (at {msg.timestamp}): {msg.content}")
```

<ParamField path="offset" type="integer">
  Number of messages to skip. Default: `0`
</ParamField>

<ParamField path="limit" type="integer">
  Maximum number of messages to return. Default: `50`
</ParamField>

**Returns:** `MessageList` object with:

* `messages`: List of message objects with `role`, `content`, and `timestamp` fields
* `total`: Total number of messages in the session
* `has_more`: Boolean indicating if more messages are available

**Raises:** `UserNotFoundError`, `SessionNotFoundError`

## Context Retrieval

### get\_context()

Retrieve contextual information for the session based on user memories and conversation history.

```python theme={null}
from recallrai.models import RecallStrategy

# Get context with default parameters
context_response = session.get_context()
print(f"Context: {context_response.context}")

# Get context with memory and session IDs
context_response = session.get_context(
    include_metadata_ids=True
)
if context_response.metadata:
    print(f"Memory IDs: {context_response.metadata.memory_ids}")
    print(f"Session IDs: {context_response.metadata.session_ids}")

# Get context with specific recall strategy
context_response = session.get_context(recall_strategy=RecallStrategy.LOW_LATENCY)

# Get context with custom parameters
context_response = session.get_context(
    recall_strategy=RecallStrategy.BALANCED,
    min_top_k=10,
    max_top_k=100,
    memories_threshold=0.6,
    summaries_threshold=0.5,
    last_n_messages=20,
    last_n_summaries=5,
    timezone="America/New_York",
    include_system_prompt=True,
    include_metadata_ids=True
)
```

### Trusted IDs Fast Path

If your system already trusts the IDs, you can skip SDK pre-validation calls and go directly to context retrieval:

```python theme={null}
trusted_user = client.get_user("user123", validate=False)
trusted_session = trusted_user.get_session(session_id="session-uuid", validate=False)

context_response = trusted_session.get_context()
print(context_response.context)
```

<Tip>
  This skips SDK lookup requests only. It removes extra latency from `get_user()` and `get_session()` when IDs are already validated in your own system.
</Tip>

<Warning>
  Use this only with trusted IDs. The context endpoint still performs server-side validation and can still return `UserNotFoundError` or `SessionNotFoundError`.
</Warning>

### get\_context\_stream()

Stream context events with status updates and structured metadata.

```python theme={null}
from recallrai.models import RecallStrategy

for event in session.get_context_stream(
    recall_strategy=RecallStrategy.BALANCED,
    timezone="America/New_York",
    include_metadata_ids=True
):
    if event.status_update_message:
        print("Status:", event.status_update_message)
    if event.is_final:
        if event.error_message:
            print("Error:", event.error_message)
        else:
            print("Final context:", event.context)
            if event.metadata:
                print("Memory IDs:", event.metadata.memory_ids)
                print("Session IDs:", event.metadata.session_ids)
                print("Vector Queries:", event.metadata.vector_search_queries)
                print("Keywords:", event.metadata.keywords)
                print("Summary Queries:", event.metadata.session_summaries_search_queries)
                print("Date Filters:", event.metadata.date_range_filters)
    if event.metadata.agent_reasoning:
        print("Agent Reasoning:", event.metadata.agent_reasoning)
```

<ParamField path="recall_strategy" type="RecallStrategy">
  Strategy for memory retrieval: `LOW_LATENCY`, `BALANCED`, `AGENTIC`, or `AUTO`.
</ParamField>

<ParamField path="timezone" type="string">
  Timezone for formatting timestamps (e.g., `America/New_York`).
</ParamField>

<ParamField path="include_metadata_ids" type="boolean" default="False">
  Whether to include context metadata (IDs, queries, filters, and agent reasoning in status events) in the response.
</ParamField>

**Yields:** `ContextResponse` objects with the following fields:

<ParamField path="recall_strategy" type="RecallStrategy">
  Strategy for memory retrieval:

  * `LOW_LATENCY`: Fast retrieval with basic relevance
  * `BALANCED`: Good balance of speed and quality (default)
  * `AGENTIC`: Agentic exploration for complex queries
</ParamField>

<ParamField path="min_top_k" type="integer">
  Minimum number of memories to return. Range: 5-50. Default: `15`
</ParamField>

<ParamField path="max_top_k" type="integer">
  Maximum number of memories to return. Range: 10-100. Default: `50`
</ParamField>

<ParamField path="memories_threshold" type="float">
  Similarity threshold for memories. Range: 0.2-0.8. Default: `0.6`
</ParamField>

<ParamField path="summaries_threshold" type="float">
  Similarity threshold for summaries. Range: 0.2-0.8. Default: `0.5`
</ParamField>

<ParamField path="last_n_messages" type="integer">
  Number of last messages to include in context. Range: 1-100. Optional.
</ParamField>

<ParamField path="last_n_summaries" type="integer">
  Number of last summaries to include in context. Range: 1-20. Optional.
</ParamField>

<ParamField path="timezone" type="string" default="UTC">
  Timezone for formatting timestamps in the context (e.g., "America/New\_York", "Europe/London", "Asia/Tokyo"). All timestamps in the retrieved memories and summaries will be formatted according to this timezone. Defaults to UTC.

  <Tip>
    Use the user's local timezone for better temporal context. For example, showing "Today at 2:30 PM" is more meaningful than a UTC timestamp.
  </Tip>
</ParamField>

<ParamField path="include_system_prompt" type="boolean">
  Whether to include the default RecallrAI system prompt. Default: `True`
</ParamField>

<ParamField path="include_metadata_ids" type="boolean" default="False">
  Whether to include context metadata. When `True`, the response includes a `metadata` field with IDs, queries, filters, and agent reasoning when available.

  <Tip>
    Enable this to track which specific memories and sessions were used to generate the context, useful for debugging, auditing, or building UI features that show sources.
  </Tip>
</ParamField>

<Note>
  Timestamps in the context are formatted using the specified `timezone` parameter (defaults to UTC). This ensures temporal information like "Last updated on Monday, January 6th at 3:45 PM EST" is presented in a user-friendly, localized format.
</Note>

**Returns:** `ContextResponse` object with the following fields:

<ResponseField name="is_final" type="boolean">
  Always `True` for non-streaming responses.
</ResponseField>

<ResponseField name="context" type="string">
  The formatted context string containing relevant memories and conversation history.
</ResponseField>

<ResponseField name="metadata" type="ContextMetadata" optional>
  Only present when `include_metadata_ids=True`. Contains:

  * `memory_ids`: List of memory IDs that contributed to the context
  * `session_ids`: List of session IDs that contributed to the context
  * `agent_reasoning`: (Optional) Agent's reasoning process, only populated when using agentic recall strategy
  * `vector_search_queries`: (Optional) Vector search queries generated for recall
  * `keywords`: (Optional) Keywords extracted for recall
  * `session_summaries_search_queries`: (Optional) Queries used to search session summaries
  * `date_range_filters`: (Optional) Date range filters extracted from the query (balanced recall only)

  <Tip>
    When using the **agentic recall strategy**, the `agent_reasoning` field will contain a step-by-step summary of the agent's exploration through your knowledge graph, showing how it arrived at the final context.
  </Tip>
</ResponseField>

**Raises:** `UserNotFoundError`, `SessionNotFoundError`

<Tip>
  Use the context string as part of your system prompt when calling your LLM. This provides the AI with relevant memories and conversation history.
</Tip>

## Processing

### process()

Process the session to update user memories.

```python theme={null}
from recallrai.exceptions import InvalidSessionStateError

try:
    session = user.get_session("session-uuid")
    session.process()
    print("Session processing started")
    
    # Check status later
    session.refresh()
    print(f"Status: {session.status}")
    
except InvalidSessionStateError as e:
    print(f"Cannot process session: {e}")
```

<Info>
  Processing extracts memories from the conversation and updates the user's memory store. This is an asynchronous operation - the session status will change to `PROCESSING` and then `PROCESSED` when complete.
</Info>

**Returns:** None

**Raises:** `UserNotFoundError`, `SessionNotFoundError`, `InvalidSessionStateError`

<Warning>
  You can only process a session once. After processing, you cannot add more messages to the session.
</Warning>

## Usage Example with LLM

Here's how to use sessions with an LLM like OpenAI:

```python theme={null}
import openai
from recallrai import RecallrAI
from recallrai.models import MessageRole

# Initialize clients
rai_client = RecallrAI(api_key="rai_yourapikey", project_id="project-uuid")
oai_client = openai.OpenAI(api_key="your-openai-api-key")

# Get user and create session
user = rai_client.get_user("user123")
session = user.create_session(auto_process_after_seconds=1800)

# Get user input
user_message = input("You: ")

# Add to RecallrAI
session.add_message(role=MessageRole.USER, content=user_message)

# Get context from RecallrAI
context_response = session.get_context()

# Create system prompt with context
system_prompt = "You are a helpful assistant" + context_response.context

# Get conversation history
messages = session.get_messages(limit=50)
previous_messages = [
    {"role": msg.role, "content": msg.content}
    for msg in messages.messages
]

# Call LLM
response = oai_client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": system_prompt},
        *previous_messages,
    ]
)

assistant_message = response.choices[0].message.content
print(f"Assistant: {assistant_message}")

# Add assistant response to RecallrAI
session.add_message(role=MessageRole.ASSISTANT, content=assistant_message)

# Process session when conversation ends
session.process()
```

## Async Session

For async applications, use `AsyncSession`:

```python theme={null}
from recallrai import AsyncRecallrAI
from recallrai.models import MessageRole

client = AsyncRecallrAI(api_key="rai_yourapikey", project_id="project-uuid")
user = await client.get_user("user123")
session = await user.create_session()

# All methods are the same, just use await
await session.add_message(role=MessageRole.USER, content="Hello")
context = await session.get_context()
messages = await session.get_messages(limit=10)
await session.process()
```
