{
  "schema_version": 2,
  "id": "develop/ai/context-engine/agent-memory/sessions",
  "title": "Sessions",
  "url": "https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/sessions/",
  "summary": "Add and retrieve conversation events, configure retention, and summarize older messages.",
  "tags": [
    "docs",
    "develop",
    "ai"
  ],
  "last_updated": "2026-11-03T10:02:56-08:00",
  "children": [
    {
      "id": "develop/ai/context-engine/agent-memory/sessions/list-sessions",
      "summary": "List session metadata by owner or namespace, sort results, and follow pagination.",
      "title": "List and sort sessions",
      "url": "https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/sessions/list-sessions/"
    }
  ],
  "page_type": "content",
  "content_hash": "be59185db8328e2fa30e189a323d235b0b2ae5b383dd5c0e9ac8f33e99fe00a6",
  "sections": [
    {
      "id": "code-examples",
      "title": "Code examples",
      "role": "example",
      "text": "These examples connect to Iris services using SDKs or HTTP requests with curl. Follow one language throughout each walkthrough.\n\n\nSession 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.\n\nFor 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.\n\nThis 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."
    },
    {
      "id": "add-session-events",
      "title": "Add session events",
      "role": "content",
      "text": "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`.\n\nRedis Agent Memory adds the event ID and storage timestamp. The event fields are:\n\n| Field | Who supplies it | Purpose |\n|:------|:----------------|:--------|\n| `eventId` | Server-generated. | Identifies the event. |\n| `sessionId` | Client-supplied in the path, or server-generated when you create a session without one. | Identifies the session that contains the event. |\n| `actorId` | Required from the client. | Identifies the user, agent, or other actor that produced the event. |\n| `role` | Required from the client. | Role of the message in the conversation. |\n| `content` | Required from the client. | Message content, including its text. |\n| `createdAt` | Required from the client. | Time the event occurred in the application. |\n| `systemTimestamp` | Server-generated. | Time Redis Agent Memory stored the event. |\n| `metadata` | Optional from the client. | Application-specific information associated with the event. |\n\n1. 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()`.\n1. 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.\n1. Set the message's `role`, `content`, and `createdAt` timestamp.\n1. Send the request.\n\nThese 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.\n\nEach 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.\n\n\n**Available in:** Python (Iris), cURL (Iris)\n\n##### Python (Iris)\n\n[code example]\n\n##### cURL (Iris)\n\n[code example]\n\n\n\nSend each new message once, using the same session ID throughout the conversation.\n\nThe 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."
    },
    {
      "id": "retrieve-conversation-context",
      "title": "Retrieve conversation context",
      "role": "content",
      "text": "When the next message arrives, retrieve the session by its ID before calling the model:\n\n**Available in:** Python (Iris), cURL (Iris), CLI (Iris)\n\n##### Python (Iris)\n\n[code example]\n\n##### cURL (Iris)\n\n[code example]\n\n##### CLI (Iris)\n\n[code example]\n\n\n\nThe `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.\n\nYour 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."
    },
    {
      "id": "list-sessions",
      "title": "List sessions",
      "role": "content",
      "text": "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.\n\nFilter the list by owner or namespace.\n\nFor 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).\n\nTo list one user's session IDs:\n\n**Available in:** Python (Iris), cURL (Iris), CLI (Iris)\n\n##### Python (Iris)\n\n[code example]\n\n##### cURL (Iris)\n\n[code example]\n\n##### CLI (Iris)\n\n[code example]\n\n\n\nTo 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.\n\n**Available in:** Python (Iris), cURL (Iris)\n\n##### Python (Iris)\n\n[code example]\n\n##### cURL (Iris)\n\n[code example]\n\n\n\n`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.\n\nAdd `ownerId` to return sessions that match both the namespace and the owner:\n\n**Available in:** Python (Iris), cURL (Iris)\n\n##### Python (Iris)\n\n[code example]\n\n##### cURL (Iris)\n\n[code example]\n\n\n\nTo list all sessions, omit both filters and set `includeAll=true`:\n\n**Available in:** Python (Iris), cURL (Iris)\n\n##### Python (Iris)\n\n[code example]\n\n##### cURL (Iris)\n\n[code example]\n\n\n\nDo not combine `includeAll=true` with either filter. A request without a filter must set `includeAll=true`.\n\nThe 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."
    },
    {
      "id": "configure-session-retention",
      "title": "Configure session retention",
      "role": "configuration",
      "text": "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.\n\nIn the Redis Cloud console, open your service's **Configuration** tab and select **Edit**. Set **Short-term TTL** under **Memory configuration**.\n\nSee [memory configuration](https://redis.io/docs/latest/operate/iris/agent-memory/create-service#memory-configuration) to configure the session-memory TTL in Redis Cloud."
    },
    {
      "id": "configure-automatic-summarization",
      "title": "Configure automatic summarization",
      "role": "configuration",
      "text": "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.\n\nIn the Redis Cloud console, open your service's **Configuration** tab and select **Edit**. Under **Memory configuration**, enable **Automatic summarization** and set:\n\n* **Summarize after:** The number of messages a session can contain before older messages are summarized.\n* **Keep most recent:** The number of recent messages that remain available in full.\n\nFor 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.\n\nSee [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.\n\nFor 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).\n\nTo 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)."
    },
    {
      "id": "try-automatic-summarization",
      "title": "Try automatic summarization",
      "role": "content",
      "text": "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.\n\nEach 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.\n\n\nFollow [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`."
    },
    {
      "id": "add-conversation-turns",
      "title": "Add conversation turns",
      "role": "content",
      "text": "Add these events to the session from the quickstart to continue the conversation past the configured threshold:\n\n**Available in:** Python (Iris), cURL (Iris)\n\n##### Python (Iris)\n\n[code example]\n\n##### cURL (Iris)\n\n[code example]\n\n\n\nRun these writes once. Summarization runs in the background."
    },
    {
      "id": "retrieve-the-summarized-session",
      "title": "Retrieve the summarized session",
      "role": "content",
      "text": "Retrieve the session again. The Python and cURL examples check every 10 seconds, for up to two minutes, until a summary appears:\n\n**Available in:** Python (Iris), cURL (Iris), CLI (Iris)\n\n##### Python (Iris)\n\n[code example]\n\n##### cURL (Iris)\n\n[code example]\n\n##### CLI (Iris)\n\n[code example]\n\n\n\nIf `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.\n\n> [!NOTE]\n> **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."
    }
  ],
  "examples": [
    {
      "id": "add-session-events-ex0",
      "language": "python",
      "code": "conversation = memory.conversation(owner=OWNER_ID, session_id=SESSION_ID)\nsaved = conversation.user(\"I am vegetarian.\")\nprint(\"Saved event\", saved.event_id, \"in\", saved.session_id)",
      "section_id": "add-session-events"
    },
    {
      "id": "add-session-events-ex1",
      "language": "bash",
      "code": "jq -n --arg owner \"$OWNER_ID\" --arg now \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\" --arg key \"$(uuidgen)\" '{\n  actorId: $owner,\n  role: \"USER\",\n  content: [{text: \"I am vegetarian.\"}],\n  createdAt: $now,\n  idempotencyKey: $key\n}' > event.json\ncurl --fail-with-body --silent --show-error \\\n  -X POST \"$MEMORY_API/sessions/$SESSION_ID/events\" -H \"$AUTH\" \\\n  -H 'Content-Type: application/json' --data-binary @event.json | jq .",
      "section_id": "add-session-events"
    },
    {
      "id": "retrieve-conversation-context-ex0",
      "language": "python",
      "code": "transcript = conversation.transcript()\nif transcript.owner != OWNER_ID:\n    raise PermissionError(\"This session belongs to another user.\")\nprint(\"Summary:\", transcript.summary)\nfor event in transcript.events:\n    print(event.role, event.actor_id, event.text)",
      "section_id": "retrieve-conversation-context"
    },
    {
      "id": "retrieve-conversation-context-ex1",
      "language": "bash",
      "code": "curl --fail-with-body --silent --show-error \\\n  \"$MEMORY_API/sessions/$SESSION_ID\" -H \"$AUTH\" |\n  jq '{ownerId, summary: .summary.text, events: [.events[] | {role, actorId, content}]}'",
      "section_id": "retrieve-conversation-context"
    },
    {
      "id": "retrieve-conversation-context-ex2",
      "language": "bash",
      "code": "iris agent-memory sessions show travel-planning-session",
      "section_id": "retrieve-conversation-context"
    },
    {
      "id": "list-sessions-ex0",
      "language": "python",
      "code": "for session_id in memory.sessions(OWNER_ID):\n    print(session_id)",
      "section_id": "list-sessions"
    },
    {
      "id": "list-sessions-ex1",
      "language": "bash",
      "code": "curl --fail-with-body --silent --show-error --get \\\n  \"$MEMORY_API/sessions\" -H \"$AUTH\" \\\n  --data-urlencode \"ownerId=$OWNER_ID\" | jq '.items[].sessionId'",
      "section_id": "list-sessions"
    },
    {
      "id": "list-sessions-ex2",
      "language": "bash",
      "code": "iris agent-memory sessions list --owner quickstart-user",
      "section_id": "list-sessions"
    },
    {
      "id": "list-sessions-ex3",
      "language": "python",
      "code": "created = memory.client.create_namespace(\n    request={\n        \"name\": \"example-travel\",\n        \"scope\": models.NamespaceScope.PERSONAL,\n        \"owner_id\": OWNER_ID,\n    }\n)\nNAMESPACE_ID = created.namespace.namespace_id\n\ntrip = memory.conversation(\n    owner=OWNER_ID, session_id=\"example-kyoto-trip\", namespace_id=NAMESPACE_ID\n)\ntrip.user(\"Plan two days in Kyoto.\")\n\npage = memory.client.list_sessions(namespace_id=NAMESPACE_ID)\nfor session in page.items:\n    print(session.session_id, session.owner_id, session.namespace_id)",
      "section_id": "list-sessions"
    },
    {
      "id": "list-sessions-ex4",
      "language": "bash",
      "code": "jq -n --arg owner \"$OWNER_ID\" \\\n  '{name: \"example-travel\", scope: \"PERSONAL\", ownerId: $owner}' > namespace.json\nNAMESPACE_ID=$(curl --fail-with-body --silent --show-error \\\n  -X POST \"$MEMORY_API/namespaces\" -H \"$AUTH\" \\\n  -H 'Content-Type: application/json' --data-binary @namespace.json |\n  jq -r '.namespace.namespaceId')\n\njq -n --arg owner \"$OWNER_ID\" --arg ns \"$NAMESPACE_ID\" \\\n  --arg now \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\" --arg key \"$(uuidgen)\" '{\n  actorId: $owner,\n  role: \"USER\",\n  content: [{text: \"Plan two days in Kyoto.\"}],\n  createdAt: $now,\n  namespaceId: $ns,\n  idempotencyKey: $key\n}' > trip.json\ncurl --fail-with-body --silent --show-error \\\n  -X POST \"$MEMORY_API/sessions/example-kyoto-trip/events\" -H \"$AUTH\" \\\n  -H 'Content-Type: application/json' --data-binary @trip.json > /dev/null\n\ncurl --fail-with-body --silent --show-error --get \\\n  \"$MEMORY_API/sessions\" -H \"$AUTH\" \\\n  --data-urlencode \"namespaceId=$NAMESPACE_ID\" | jq '.items'",
      "section_id": "list-sessions"
    },
    {
      "id": "list-sessions-ex5",
      "language": "python",
      "code": "page = memory.client.list_sessions(namespace_id=NAMESPACE_ID, owner_id=OWNER_ID)\nfor session in page.items:\n    print(session.session_id, session.updated_at)",
      "section_id": "list-sessions"
    },
    {
      "id": "list-sessions-ex6",
      "language": "bash",
      "code": "curl --fail-with-body --silent --show-error --get \\\n  \"$MEMORY_API/sessions\" -H \"$AUTH\" \\\n  --data-urlencode \"namespaceId=$NAMESPACE_ID\" \\\n  --data-urlencode \"ownerId=$OWNER_ID\" | jq '.items'",
      "section_id": "list-sessions"
    },
    {
      "id": "list-sessions-ex7",
      "language": "python",
      "code": "page = memory.client.list_sessions(include_all=True, limit=20)\nfor session in page.items:\n    print(session.session_id, session.owner_id)\nprint(\"Next page:\", page.next_cursor)",
      "section_id": "list-sessions"
    },
    {
      "id": "list-sessions-ex8",
      "language": "bash",
      "code": "curl --fail-with-body --silent --show-error --get \\\n  \"$MEMORY_API/sessions\" -H \"$AUTH\" \\\n  --data-urlencode 'includeAll=true' --data-urlencode 'limit=20' |\n  jq '{sessions: [.items[] | {sessionId, ownerId}], nextCursor}'",
      "section_id": "list-sessions"
    },
    {
      "id": "add-conversation-turns-ex0",
      "language": "python",
      "code": "turns = [\n    (\"assistant\", \"What dates are you traveling?\"),\n    (\"user\", \"I arrive on October 10 and leave on October 18.\"),\n    (\"assistant\", \"Would you like formal or casual restaurants?\"),\n    (\"user\", \"Mostly casual places near public transit.\"),\n    (\"assistant\", \"Do you have a preferred budget?\"),\n    (\"user\", \"About 40 euros per person.\"),\n]\nfor role, text in turns:\n    add = conversation.user if role == \"user\" else conversation.assistant\n    add(text)",
      "section_id": "add-conversation-turns"
    },
    {
      "id": "add-conversation-turns-ex1",
      "language": "bash",
      "code": "add_event() {  # add_event ROLE ACTOR_ID TEXT\n  jq -n --arg role \"$1\" --arg actor \"$2\" --arg text \"$3\" \\\n    --arg now \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\" --arg key \"$(uuidgen)\" \\\n    '{actorId: $actor, role: $role, content: [{text: $text}], createdAt: $now, idempotencyKey: $key}' |\n    curl --fail-with-body --silent --show-error \\\n      -X POST \"$MEMORY_API/sessions/$SESSION_ID/events\" -H \"$AUTH\" \\\n      -H 'Content-Type: application/json' --data-binary @- | jq -c '.event | {sessionId, eventId}'\n}\nadd_event ASSISTANT travel-agent \"What dates are you traveling?\"\nadd_event USER \"$OWNER_ID\" \"I arrive on October 10 and leave on October 18.\"\nadd_event ASSISTANT travel-agent \"Would you like formal or casual restaurants?\"\nadd_event USER \"$OWNER_ID\" \"Mostly casual places near public transit.\"\nadd_event ASSISTANT travel-agent \"Do you have a preferred budget?\"\nadd_event USER \"$OWNER_ID\" \"About 40 euros per person.\"",
      "section_id": "add-conversation-turns"
    },
    {
      "id": "retrieve-the-summarized-session-ex0",
      "language": "python",
      "code": "for _ in range(12):  # summarization runs in the background\n    compacted = conversation.transcript()\n    if compacted.summary:\n        break\n    time.sleep(10)\nprint(\"Summary:\", compacted.summary)\nprint(\"Summarized up to event:\", compacted.summarized_up_to)\nfor role, text in compacted.turns:\n    print(role, text)",
      "section_id": "retrieve-the-summarized-session"
    },
    {
      "id": "retrieve-the-summarized-session-ex1",
      "language": "bash",
      "code": "for _ in $(seq 12); do  # summarization runs in the background\n  SESSION=$(curl --fail-with-body --silent --show-error \\\n    \"$MEMORY_API/sessions/$SESSION_ID\" -H \"$AUTH\")\n  [ \"$(jq '.summary != null' <<< \"$SESSION\")\" = true ] && break\n  sleep 10\ndone\njq '{summary, events: [.events[] | {role, content}]}' <<< \"$SESSION\"",
      "section_id": "retrieve-the-summarized-session"
    },
    {
      "id": "retrieve-the-summarized-session-ex2",
      "language": "bash",
      "code": "iris agent-memory sessions show travel-planning-session",
      "section_id": "retrieve-the-summarized-session"
    }
  ]
}
