# Sessions

```json metadata
{
  "schema_version": 2,
  "title": "Sessions",
  "description": "Add and retrieve conversation events, configure retention, and summarize older messages.",
  "categories": ["docs","develop","ai"],
  "tableOfContents": {"sections":[{"id":"add-session-events","title":"Add session events"},{"id":"retrieve-conversation-context","title":"Retrieve conversation context"},{"id":"list-sessions","title":"List sessions"},{"id":"configure-session-retention","title":"Configure session retention"},{"id":"configure-automatic-summarization","title":"Configure automatic summarization"},{"children":[{"id":"add-conversation-turns","title":"Add conversation turns"},{"id":"retrieve-the-summarized-session","title":"Retrieve the summarized session"}],"id":"try-automatic-summarization","title":"Try automatic summarization"}]}

,
  "codeExamples": [{"codetabsId":"iris_agent_memory_sessions-stepagent-memory-sessions-add","difficulty":"beginner","id":"agent-memory-sessions-add","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-add"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-add"}]},{"codetabsId":"iris_agent_memory_sessions-stepagent-memory-sessions-retrieve","difficulty":"beginner","id":"agent-memory-sessions-retrieve","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-retrieve"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-retrieve"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-retrieve"}]},{"codetabsId":"iris_agent_memory_sessions-stepagent-memory-sessions-list-owner","difficulty":"beginner","id":"agent-memory-sessions-list-owner","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-list-owner"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-list-owner"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-list-owner"}]},{"codetabsId":"iris_agent_memory_sessions-stepagent-memory-sessions-list-namespace","difficulty":"beginner","id":"agent-memory-sessions-list-namespace","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-list-namespace"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-list-namespace"}]},{"codetabsId":"iris_agent_memory_sessions-stepagent-memory-sessions-list-namespace-owner","difficulty":"beginner","id":"agent-memory-sessions-list-namespace-owner","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-list-namespace-owner"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-list-namespace-owner"}]},{"codetabsId":"iris_agent_memory_sessions-stepagent-memory-sessions-list-all","difficulty":"beginner","id":"agent-memory-sessions-list-all","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-list-all"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-list-all"}]},{"codetabsId":"iris_agent_memory_sessions-stepagent-memory-sessions-add-turns","difficulty":"beginner","id":"agent-memory-sessions-add-turns","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-add-turns"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-add-turns"}]},{"codetabsId":"iris_agent_memory_sessions-stepagent-memory-sessions-summary","difficulty":"beginner","id":"agent-memory-sessions-summary","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-summary"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-summary"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_agent_memory_sessions-stepagent-memory-sessions-summary"}]}]
}
```

## Code examples

These examples connect to Iris services using SDKs or HTTP requests with curl. Follow one language throughout each walkthrough.


Session memory holds a conversation's transcript. Your application saves each message as an event, then retrieves the transcript when the user sends the next message. This gives the agent the history it needs to continue the conversation.

For example, a travel assistant can retrieve the cities a user mentioned earlier in the chat instead of asking again. Each chat has a session ID (`sessionId`) that ties its events together. The same ID lets your application retrieve the conversation later.

This page covers adding events, retrieving a conversation, and finding session IDs by owner or namespace. It also explains two settings that control the history: retention determines how long a session stays available, and summarization condenses older messages so they take less space in the model's context window.

## Add session events

A session event represents one message from a user, assistant, or system. To append one, send `POST /iris/data/v1/agent-memory/stores/{storeId}/sessions/{sessionId}/events`, which creates the session if it does not exist. In Python, `memory.conversation(owner=..., session_id=...)` returns a conversation whose `user` and `assistant` methods append events. To start a session with a server-generated ID, send its first event to `POST /iris/data/v1/agent-memory/stores/{storeId}/sessions` instead. In Python, omit `session_id` and the SDK generates one; read it from `conversation.session_id`.

Redis Agent Memory adds the event ID and storage timestamp. The event fields are:

| Field | Who supplies it | Purpose |
|:------|:----------------|:--------|
| `eventId` | Server-generated. | Identifies the event. |
| `sessionId` | Client-supplied in the path, or server-generated when you create a session without one. | Identifies the session that contains the event. |
| `actorId` | Required from the client. | Identifies the user, agent, or other actor that produced the event. |
| `role` | Required from the client. | Role of the message in the conversation. |
| `content` | Required from the client. | Message content, including its text. |
| `createdAt` | Required from the client. | Time the event occurred in the application. |
| `systemTimestamp` | Server-generated. | Time Redis Agent Memory stored the event. |
| `metadata` | Optional from the client. | Application-specific information associated with the event. |

1. Set the first event's `actorId` to the signed-in user's account ID from your application. Use the same ID each time this user returns. The server uses it as the session owner. Later events can identify other actors, such as the assistant. In Python, `conversation.user` sends the `owner` as `actorId`, and `conversation.assistant` sends the `assistant_id` passed to `AgentMemory.from_env()`.
1. Supply a `sessionId`, or omit it to let the server create one. Save the returned `event.sessionId` for later requests. See [Identify users and conversations](https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/developer-guide#identify-users-and-conversations) for examples.
1. Set the message's `role`, `content`, and `createdAt` timestamp.
1. Send the request.

These examples continue from the [quickstart](https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/quickstart). Load the same `.env` connection values and reuse its user ID. Expand an example to copy a complete program that connects for you.

Each run repeats every write in the program. Session-event writes and memory creates with a new idempotency key add new records, so run cleanup or change the identifiers before rerunning.


**Available in:** Python (Iris), cURL (Iris)

##### Python (Iris)

```python
conversation = memory.conversation(owner=OWNER_ID, session_id=SESSION_ID)
saved = conversation.user("I am vegetarian.")
print("Saved event", saved.event_id, "in", saved.session_id)
```

##### cURL (Iris)

```bash
jq -n --arg owner "$OWNER_ID" --arg now "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg key "$(uuidgen)" '{
  actorId: $owner,
  role: "USER",
  content: [{text: "I am vegetarian."}],
  createdAt: $now,
  idempotencyKey: $key
}' > event.json
curl --fail-with-body --silent --show-error \
  -X POST "$MEMORY_API/sessions/$SESSION_ID/events" -H "$AUTH" \
  -H 'Content-Type: application/json' --data-binary @event.json | jq .
```



Send each new message once, using the same session ID throughout the conversation.

The session's `ownerId` comes from the first event's `actorId` and is returned when you retrieve the session. In on-prem deployments with [server-side ownership enforcement](https://redis.io/docs/latest/operate/iris/agent-memory/self-managed/authentication#server-side-ownership-enforcement), the first event's `actorId` must match the authenticated user ID.

## Retrieve conversation context

When the next message arrives, retrieve the session by its ID before calling the model:

**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
transcript = conversation.transcript()
if transcript.owner != OWNER_ID:
    raise PermissionError("This session belongs to another user.")
print("Summary:", transcript.summary)
for event in transcript.events:
    print(event.role, event.actor_id, event.text)
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error \
  "$MEMORY_API/sessions/$SESSION_ID" -H "$AUTH" |
  jq '{ownerId, summary: .summary.text, events: [.events[] | {role, actorId, content}]}'
```

##### CLI (Iris)

```bash
iris agent-memory sessions show travel-planning-session
```



The `events` array contains the retained conversation messages. If older events have been summarized, the response also includes `summary.text`. Pass both to the model with the current user message; in Python, `transcript.as_messages()` returns them as chat messages. See [Build context for each agent turn](https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/developer-guide#build-context-for-each-agent-turn) for an example.

Your application must check that the current user can access this session before using it. The request selects a session by ID; it does not include an owner filter. Compare the returned `ownerId` (`transcript.owner` in Python) with the authenticated user, as the example does.

## List sessions

To let a user reopen an earlier conversation, list their sessions and retrieve the selected session by ID. Use `GET /iris/data/v1/agent-memory/stores/{storeId}/sessions`, `memory.sessions(owner)` or `memory.client.list_sessions` in Python, or `iris agent-memory sessions list`. These rows do not contain events or generated summary text. See [List and sort sessions](https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/sessions/list-sessions) for SDK examples and pagination.

Filter the list by owner or namespace.

For a user's personal conversations, set `ownerId` to that user's authenticated ID. A namespace-only query is suitable for shared conversations only after your application checks access to that namespace. Reserve `includeAll=true` for callers your application authorizes to list the whole store. See [Authorize every memory request](https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/developer-guide#authorize-every-memory-request).

To list one user's session IDs:

**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
for session_id in memory.sessions(OWNER_ID):
    print(session_id)
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error --get \
  "$MEMORY_API/sessions" -H "$AUTH" \
  --data-urlencode "ownerId=$OWNER_ID" | jq '.items[].sessionId'
```

##### CLI (Iris)

```bash
iris agent-memory sessions list --owner quickstart-user
```



To list sessions in one namespace, filter by its stable ID. This example creates a personal namespace, starts a session in it, and lists that namespace's sessions. In an application, [create the namespace](https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/namespaces#create-a-personal-namespace) once and save its ID.

**Available in:** Python (Iris), cURL (Iris)

##### Python (Iris)

```python
created = memory.client.create_namespace(
    request={
        "name": "example-travel",
        "scope": models.NamespaceScope.PERSONAL,
        "owner_id": OWNER_ID,
    }
)
NAMESPACE_ID = created.namespace.namespace_id

trip = memory.conversation(
    owner=OWNER_ID, session_id="example-kyoto-trip", namespace_id=NAMESPACE_ID
)
trip.user("Plan two days in Kyoto.")

page = memory.client.list_sessions(namespace_id=NAMESPACE_ID)
for session in page.items:
    print(session.session_id, session.owner_id, session.namespace_id)
```

##### cURL (Iris)

```bash
jq -n --arg owner "$OWNER_ID" \
  '{name: "example-travel", scope: "PERSONAL", ownerId: $owner}' > namespace.json
NAMESPACE_ID=$(curl --fail-with-body --silent --show-error \
  -X POST "$MEMORY_API/namespaces" -H "$AUTH" \
  -H 'Content-Type: application/json' --data-binary @namespace.json |
  jq -r '.namespace.namespaceId')

jq -n --arg owner "$OWNER_ID" --arg ns "$NAMESPACE_ID" \
  --arg now "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg key "$(uuidgen)" '{
  actorId: $owner,
  role: "USER",
  content: [{text: "Plan two days in Kyoto."}],
  createdAt: $now,
  namespaceId: $ns,
  idempotencyKey: $key
}' > trip.json
curl --fail-with-body --silent --show-error \
  -X POST "$MEMORY_API/sessions/example-kyoto-trip/events" -H "$AUTH" \
  -H 'Content-Type: application/json' --data-binary @trip.json > /dev/null

curl --fail-with-body --silent --show-error --get \
  "$MEMORY_API/sessions" -H "$AUTH" \
  --data-urlencode "namespaceId=$NAMESPACE_ID" | jq '.items'
```



`namespaceId` matches the namespace ID exactly, including case. It excludes descendant namespaces, sessions with only the older `namespace` string label, and sessions without a namespace resource.

Add `ownerId` to return sessions that match both the namespace and the owner:

**Available in:** Python (Iris), cURL (Iris)

##### Python (Iris)

```python
page = memory.client.list_sessions(namespace_id=NAMESPACE_ID, owner_id=OWNER_ID)
for session in page.items:
    print(session.session_id, session.updated_at)
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error --get \
  "$MEMORY_API/sessions" -H "$AUTH" \
  --data-urlencode "namespaceId=$NAMESPACE_ID" \
  --data-urlencode "ownerId=$OWNER_ID" | jq '.items'
```



To list all sessions, omit both filters and set `includeAll=true`:

**Available in:** Python (Iris), cURL (Iris)

##### Python (Iris)

```python
page = memory.client.list_sessions(include_all=True, limit=20)
for session in page.items:
    print(session.session_id, session.owner_id)
print("Next page:", page.next_cursor)
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error --get \
  "$MEMORY_API/sessions" -H "$AUTH" \
  --data-urlencode 'includeAll=true' --data-urlencode 'limit=20' |
  jq '{sessions: [.items[] | {sessionId, ownerId}], nextCursor}'
```



Do not combine `includeAll=true` with either filter. A request without a filter must set `includeAll=true`.

The response contains session rows in `items` and no total count. If the response includes `nextCursor`, pass it as `cursor` with the same filters to fetch the next page. See the [List Sessions API reference](https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/api-reference#operation/ListSessions) for pagination limits.

## Configure session retention

The session-memory time to live (TTL) controls how long sessions remain available. Choose a duration that lets users resume conversations for as long as your application needs. When a session expires, its events are no longer available through session-memory retrieval.

In the Redis Cloud console, open your service's **Configuration** tab and select **Edit**. Set **Short-term TTL** under **Memory configuration**.

See [memory configuration](https://redis.io/docs/latest/operate/iris/agent-memory/create-service#memory-configuration) to configure the session-memory TTL in Redis Cloud.

## Configure automatic summarization

As a conversation grows, its messages take more space in the model's context window. Automatic summarization replaces older messages with a shorter summary while keeping recent messages in full.

In the Redis Cloud console, open your service's **Configuration** tab and select **Edit**. Under **Memory configuration**, enable **Automatic summarization** and set:

* **Summarize after:** The number of messages a session can contain before older messages are summarized.
* **Keep most recent:** The number of recent messages that remain available in full.

For example, with **Summarize after** set to 20 and **Keep most recent** set to 10, Redis Agent Memory summarizes the older 10 messages when the session reaches 20 messages and retains the 10 most recent messages in full.

See [automatic summarization](https://redis.io/docs/latest/operate/iris/agent-memory/create-service#automatic-summarization) to enable summarization and configure both thresholds in Redis Cloud.

For an example that combines session events with long-term recall, follow the [developer guide](https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/developer-guide). For complete schemas, see the [session-memory application programming interface (API) reference](https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/api-reference#operation/GetSessionMemory).

To group a session and its extracted memories, use an optional [namespace](https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/namespaces#place-and-retrieve-memories).

## Try automatic summarization

These examples continue from the [quickstart](https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/quickstart). Load the same `.env` connection values and reuse its user ID. Expand an example to copy a complete program that connects for you.

Each run repeats every write in the program. Session-event writes and memory creates with a new idempotency key add new records, so run cleanup or change the identifiers before rerunning.


Follow [Configure automatic summarization](#configure-automatic-summarization). Set **Summarize after** to `6` and **Keep most recent** to `2` for this example. The retrieved session will contain a `summary` object and the two most recent events in `events`.


### Add conversation turns

Add these events to the session from the quickstart to continue the conversation past the configured threshold:

**Available in:** Python (Iris), cURL (Iris)

##### Python (Iris)

```python
turns = [
    ("assistant", "What dates are you traveling?"),
    ("user", "I arrive on October 10 and leave on October 18."),
    ("assistant", "Would you like formal or casual restaurants?"),
    ("user", "Mostly casual places near public transit."),
    ("assistant", "Do you have a preferred budget?"),
    ("user", "About 40 euros per person."),
]
for role, text in turns:
    add = conversation.user if role == "user" else conversation.assistant
    add(text)
```

##### cURL (Iris)

```bash
add_event() {  # add_event ROLE ACTOR_ID TEXT
  jq -n --arg role "$1" --arg actor "$2" --arg text "$3" \
    --arg now "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg key "$(uuidgen)" \
    '{actorId: $actor, role: $role, content: [{text: $text}], createdAt: $now, idempotencyKey: $key}' |
    curl --fail-with-body --silent --show-error \
      -X POST "$MEMORY_API/sessions/$SESSION_ID/events" -H "$AUTH" \
      -H 'Content-Type: application/json' --data-binary @- | jq -c '.event | {sessionId, eventId}'
}
add_event ASSISTANT travel-agent "What dates are you traveling?"
add_event USER "$OWNER_ID" "I arrive on October 10 and leave on October 18."
add_event ASSISTANT travel-agent "Would you like formal or casual restaurants?"
add_event USER "$OWNER_ID" "Mostly casual places near public transit."
add_event ASSISTANT travel-agent "Do you have a preferred budget?"
add_event USER "$OWNER_ID" "About 40 euros per person."
```



Run these writes once. Summarization runs in the background.


### Retrieve the summarized session

Retrieve the session again. The Python and cURL examples check every 10 seconds, for up to two minutes, until a summary appears:

**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
for _ in range(12):  # summarization runs in the background
    compacted = conversation.transcript()
    if compacted.summary:
        break
    time.sleep(10)
print("Summary:", compacted.summary)
print("Summarized up to event:", compacted.summarized_up_to)
for role, text in compacted.turns:
    print(role, text)
```

##### cURL (Iris)

```bash
for _ in $(seq 12); do  # summarization runs in the background
  SESSION=$(curl --fail-with-body --silent --show-error \
    "$MEMORY_API/sessions/$SESSION_ID" -H "$AUTH")
  [ "$(jq '.summary != null' <<< "$SESSION")" = true ] && break
  sleep 10
done
jq '{summary, events: [.events[] | {role, content}]}' <<< "$SESSION"
```

##### CLI (Iris)

```bash
iris agent-memory sessions show travel-planning-session
```



If `summary` is still missing, run the retrieval again. Compare `summary.text` with the recent events. The summary should preserve earlier trip decisions while recent turns remain available in full.

> [!NOTE]
> **What to expect:** A `summary` object that preserves details such as Tokyo, Kyoto, the travel dates, and food preferences. `summarizedUpToEventId` identifies the last event covered by the summary, while `events` contains the newer turns that remain in full. The exact summary text can vary.

