From a7e29198750d52353bb7d5dd5752b642273c2451 Mon Sep 17 00:00:00 2001 From: Robert Shelton Date: Fri, 30 Oct 2026 16:01:52 -0400 Subject: [PATCH] Iris docs: Agent Memory SDK snippets on the 1.0 SDKs Update Python and TypeScript snippets to the redis-agent-memory and @redis-iris/agent-memory 1.0 APIs: cursor pagination (items/next_cursor), list_sessions/listSessions, namespace_id/namespaceId in place of namespace references, query for search text, uppercase enum values, positional addSessionEvent(sessionId, body), viewId/view_id, and destination_namespace_id for routing rules. Fix the long-term memory link in the developer guide. Co-Authored-By: Claude Opus 5.5 --- .../agent-memory/developer-guide.md | 4 +- .../agent-memory/ingestion-webhooks.md | 6 +- .../agent-memory/long-term-memory.md | 23 +++--- .../context-engine/agent-memory/memory-etl.md | 79 +++++++++---------- .../agent-memory/namespaces/_index.md | 30 +++---- .../namespaces/namespace-routing.md | 18 ++--- .../agent-memory/sessions/_index.md | 3 +- .../agent-memory/sessions/list-sessions.md | 41 +++++----- .../agent-memory/summary-views.md | 44 +++++------ .../agent-memory/agent_memory_sdk.py | 2 +- .../agent-memory/agent_memory_sdk.ts | 5 +- 11 files changed, 124 insertions(+), 131 deletions(-) diff --git a/content/develop/ai/context-engine/agent-memory/developer-guide.md b/content/develop/ai/context-engine/agent-memory/developer-guide.md index 17a6100c4e..e718cd3378 100644 --- a/content/develop/ai/context-engine/agent-memory/developer-guide.md +++ b/content/develop/ai/context-engine/agent-memory/developer-guide.md @@ -84,7 +84,7 @@ The following Python example prepares that context. It uses the client, `SESSION session = agent_memory.get_session_memory(session_id=SESSION_ID) memories = agent_memory.search_long_term_memory( request={ - "text": question, + "query": question, "filter_": {"owner_id": {"eq": USER_ID}}, "limit": 5, }, @@ -183,7 +183,7 @@ The ingestion-hook `503` retry error and `422` stopped error also have distinct Create memories directly when your application already has information to store, such as a preference submitted through a form. Set the owner and a stable record ID. Creating an eligible record with the same ID again replaces it; access checks and protection for document-managed records still apply. Check the bulk response for per-record errors. Direct creation does not apply automatic extraction or sensitive-data exclusions. -See [Long-term memory]({{< relref "/develop/ai/context-engine/agent-memory/memories" >}}) for creation methods, search fields, retention, and extraction controls. +See [Long-term memory]({{< relref "/develop/ai/context-engine/agent-memory/long-term-memory" >}}) for creation methods, search fields, retention, and extraction controls. For unstructured documents, use [MemoryETL](/content/develop/ai/context-engine/agent-memory/memory-etl.md) to configure an extractor, submit a revision, and track its outputs. Source links let you trace extracted memories back to document or session inputs. diff --git a/content/develop/ai/context-engine/agent-memory/ingestion-webhooks.md b/content/develop/ai/context-engine/agent-memory/ingestion-webhooks.md index 29e4bf8706..73b6c29f1d 100644 --- a/content/develop/ai/context-engine/agent-memory/ingestion-webhooks.md +++ b/content/develop/ai/context-engine/agent-memory/ingestion-webhooks.md @@ -280,7 +280,7 @@ async def main(): page = await memory.list_ingestion_hook_statuses_async( limit=20, cursor=cursor, http_headers=headers, ) - for status in page.statuses: + for status in page.items: print(status.model_dump_json(by_alias=True)) cursor = page.next_cursor if not cursor: @@ -310,7 +310,7 @@ async function main() { let cursor: string | undefined; do { const page = await memory.listIngestionHookStatuses(20, cursor, options); - console.dir(page.statuses, { depth: null }); + console.dir(page.items, { depth: null }); cursor = page.nextCursor; } while (cursor); } @@ -343,7 +343,7 @@ fi {{< /multitabs >}} -Lists return `statuses` and `nextCursor`. Pass `nextCursor` as `cursor`, even when the page is empty; ownership filtering can produce that result. Keep the same store, credential, and list parameters. The maximum page size is 100. +Lists return `items` and `nextCursor`. Pass `nextCursor` as `cursor`, even when the page is empty; ownership filtering can produce that result. Keep the same store, credential, and list parameters. The maximum page size is 100. Private pending content expires within 24 hours or the earlier operation deadline. Compact status and write receipts remain for seven days after completion or expiry. Status omits private input, generated content, prompts, endpoint configuration, and keys. diff --git a/content/develop/ai/context-engine/agent-memory/long-term-memory.md b/content/develop/ai/context-engine/agent-memory/long-term-memory.md index c4bf196d68..a6123919ea 100644 --- a/content/develop/ai/context-engine/agent-memory/long-term-memory.md +++ b/content/develop/ai/context-engine/agent-memory/long-term-memory.md @@ -88,7 +88,7 @@ Omit `query` to retrieve records by filters without a semantic query. For exampl recent_memories = agent_memory.search_long_term_memory(request={ "filter_": {"owner_id": {"eq": USER_ID}}, "sort_by": "updatedAt", - "sort_order": "desc", + "sort_order": "DESC", "limit": 10, }) show("Recent memories", recent_memories) @@ -99,7 +99,7 @@ Omit `query` to retrieve records by filters without a semantic query. For exampl ```typescript const recentMemories = await agentMemory.searchLongTermMemory({ filter: { ownerId: { eq: userId } }, - sortBy: "updatedAt", sortOrder: "desc", limit: 10, + sortBy: "updatedAt", sortOrder: "DESC", limit: 10, }); console.dir(recentMemories, { depth: null }); ``` @@ -201,8 +201,8 @@ After enabling the type, add a travel message to a new session. Run this write o -tab-sep- ```typescript - await agentMemory.addSessionEvent({ - sessionId: "trip-preference-session", actorId: userId, role: "USER", + await agentMemory.addSessionEvent("trip-preference-session", { + actorId: userId, role: "USER", content: [{ text: "I am visiting Tokyo and Kyoto next month. I am vegetarian." }], createdAt: new Date(), }); @@ -228,7 +228,7 @@ Search for the structured memory: ```python custom_results = agent_memory.search_long_term_memory( request={ - "text": "What are the requirements for the user's trip?", + "query": "What are the requirements for the user's trip?", "filter_": { "owner_id": {"eq": USER_ID}, "memory_type": {"eq": "trip_preference"}, @@ -243,7 +243,7 @@ Search for the structured memory: ```typescript const customResults = await agentMemory.searchLongTermMemory({ - text: "What are the requirements for the user's trip?", + query: "What are the requirements for the user's trip?", filter: { ownerId: { eq: userId }, memoryType: { eq: "trip_preference" }, @@ -357,7 +357,7 @@ If your application already has structured trip data, write it directly using th ```python direct_result = agent_memory.bulk_create_long_term_memories(memories=[{ - "memoryId": "trip-form-1", + "memory_id": "trip-form-1", "text": "The user plans to visit Tokyo and Kyoto next month and requires vegetarian food.", "owner_id": USER_ID, "memory_type": "trip_preference", @@ -376,7 +376,7 @@ If your application already has structured trip data, write it directly using th ```typescript const directResult = await agentMemory.bulkCreateLongTermMemories({ memories: [{ - id: "trip-form-1", + memoryId: "trip-form-1", text: "The user plans to visit Tokyo and Kyoto next month and requires vegetarian food.", ownerId: userId, memoryType: "trip_preference", @@ -456,8 +456,7 @@ The semantic exclusion prompt tells Redis Agent Memory which information should -tab-sep- ```typescript - const sensitiveEvent = await agentMemory.addSessionEvent({ - sessionId, + const sensitiveEvent = await agentMemory.addSessionEvent(sessionId, { actorId: userId, role: "USER", content: [{ @@ -502,7 +501,7 @@ Run the event write once. In the SDK files, comment out event creation and its o ```python exclusion_results = agent_memory.search_long_term_memory( request={ - "text": "Where is the user staying in Tokyo?", + "query": "Where is the user staying in Tokyo?", "filter_": { "owner_id": {"eq": USER_ID}, }, @@ -516,7 +515,7 @@ Run the event write once. In the SDK files, comment out event creation and its o ```typescript const exclusionResults = await agentMemory.searchLongTermMemory({ - text: "Where is the user staying in Tokyo?", + query: "Where is the user staying in Tokyo?", filter: { ownerId: { eq: userId }, }, diff --git a/content/develop/ai/context-engine/agent-memory/memory-etl.md b/content/develop/ai/context-engine/agent-memory/memory-etl.md index b1b9802ebd..019855c9fd 100644 --- a/content/develop/ai/context-engine/agent-memory/memory-etl.md +++ b/content/develop/ai/context-engine/agent-memory/memory-etl.md @@ -90,23 +90,23 @@ async def main(): ingestion_id=ingestion_id, http_headers=headers, ) status = record.ingestion.status - if status.processing in {"succeeded", "partial", "failed"}: + if status.processing in {"SUCCEEDED", "PARTIAL", "FAILED"}: print(status.model_dump_json(by_alias=True)) break await asyncio.sleep(2) else: raise TimeoutError(f"Continue polling ingestion {ingestion_id}") - offset = 0 + cursor = None while True: page = await memory.list_document_ingestion_outputs_async( - ingestion_id=ingestion_id, limit=100, offset=offset, http_headers=headers, + ingestion_id=ingestion_id, limit=100, cursor=cursor, http_headers=headers, ) - if not page.memory_ids: + print(page.items) + cursor = page.next_cursor + if not cursor: break - print(page.memory_ids) - offset += len(page.memory_ids) - if status.processing != "succeeded": + if status.processing != "SUCCEEDED": raise RuntimeError(f"Inspect ingestion {ingestion_id}: {status.processing}") @@ -140,7 +140,7 @@ async function main() { let processing: string | undefined; for (let attempt = 0; attempt < 60; attempt++) { const { ingestion } = await memory.getDocumentIngestion(ingestionId, options); - if (["succeeded", "partial", "failed"].includes(ingestion.status.processing)) { + if (["SUCCEEDED", "PARTIAL", "FAILED"].includes(ingestion.status.processing)) { processing = ingestion.status.processing; console.dir(ingestion.status, { depth: null }); finished = true; @@ -149,14 +149,13 @@ async function main() { await delay(2000); } if (!finished) throw new Error(`Continue polling ingestion ${ingestionId}`); - let offset = 0; - for (;;) { - const page = await memory.listDocumentIngestionOutputs(ingestionId, 100, offset, options); - if (!page.memoryIds.length) break; - console.log(page.memoryIds); - offset += page.memoryIds.length; - } - if (processing !== "succeeded") throw new Error(`Inspect ingestion ${ingestionId}: ${processing}`); + let cursor: string | undefined; + do { + const page = await memory.listDocumentIngestionOutputs(ingestionId, 100, cursor, options); + console.log(page.items); + cursor = page.nextCursor; + } while (cursor); + if (processing !== "SUCCEEDED") throw new Error(`Inspect ingestion ${ingestionId}: ${processing}`); } main().catch((error) => { console.error(error instanceof Error ? error.message : "Request failed"); process.exitCode = 1; }); @@ -243,34 +242,34 @@ Set `MEMORY_ID` to one returned output ID. These examples follow both source pag {{< multitabs id="document-provenance" tab1="Python" tab2="TypeScript" tab3="curl" >}} ```python - source_page_token = None + source_cursor = None while True: links = await memory.list_memory_source_links_async( memory_id=os.environ["MEMORY_ID"], limit=100, - page_token=source_page_token, http_headers=headers, + cursor=source_cursor, http_headers=headers, ) for source in links.items: print(source.model_dump_json(by_alias=True)) - evidence_token = source.evidence_next_page_token - while evidence_token: + evidence_cursor = source.evidence_next_cursor + while evidence_cursor: evidence = await memory.list_memory_source_evidence_async( memory_id=os.environ["MEMORY_ID"], source_id=source.source_id, - limit=100, page_token=evidence_token, http_headers=headers, + limit=100, cursor=evidence_cursor, http_headers=headers, ) print(evidence.source.model_dump_json(by_alias=True)) - evidence_token = evidence.source.evidence_next_page_token - reverse_token = None + evidence_cursor = evidence.source.evidence_next_cursor + reverse_cursor = None while True: related = await memory.list_source_memories_async( source_id=source.source_id, owner_id=os.environ["OWNER_ID"], - limit=100, page_token=reverse_token, http_headers=headers, + limit=100, cursor=reverse_cursor, http_headers=headers, ) print(related.model_dump_json(by_alias=True)) - reverse_token = related.next_page_token - if not reverse_token: + reverse_cursor = related.next_cursor + if not reverse_cursor: break - source_page_token = links.next_page_token - if not source_page_token: + source_cursor = links.next_cursor + if not source_cursor: break ``` @@ -279,30 +278,30 @@ Set `MEMORY_ID` to one returned output ID. These examples follow both source pag ```typescript const memoryId = process.env.MEMORY_ID; if (!memoryId) throw new Error("Set MEMORY_ID to an output memory ID."); - let sourcePageToken: string | undefined; + let sourceCursor: string | undefined; do { - const links = await memory.listMemorySourceLinks(memoryId, 100, sourcePageToken, options); + const links = await memory.listMemorySourceLinks(memoryId, 100, sourceCursor, options); for (const source of links.items) { console.dir(source, { depth: null }); - let evidenceToken = source.evidenceNextPageToken; - while (evidenceToken) { + let evidenceCursor = source.evidenceNextCursor; + while (evidenceCursor) { const evidence = await memory.listMemorySourceEvidence( - memoryId, source.sourceId, 100, evidenceToken, options, + memoryId, source.sourceId, 100, evidenceCursor, options, ); console.dir(evidence.source, { depth: null }); - evidenceToken = evidence.source.evidenceNextPageToken; + evidenceCursor = evidence.source.evidenceNextCursor; } - let reverseToken: string | undefined; + let reverseCursor: string | undefined; do { const related = await memory.listSourceMemories( - source.sourceId, OWNER_ID, 100, reverseToken, options, + source.sourceId, OWNER_ID, 100, reverseCursor, options, ); console.dir(related.items, { depth: null }); - reverseToken = related.nextPageToken; - } while (reverseToken); + reverseCursor = related.nextCursor; + } while (reverseCursor); } - sourcePageToken = links.nextPageToken; - } while (sourcePageToken); + sourceCursor = links.nextCursor; + } while (sourceCursor); ``` -tab-sep- diff --git a/content/develop/ai/context-engine/agent-memory/namespaces/_index.md b/content/develop/ai/context-engine/agent-memory/namespaces/_index.md index 5af9f55d08..82f54b61f4 100644 --- a/content/develop/ai/context-engine/agent-memory/namespaces/_index.md +++ b/content/develop/ai/context-engine/agent-memory/namespaces/_index.md @@ -35,7 +35,6 @@ Add this code inside the `with` block. It creates a personal namespace for the u }) namespace_id = created_namespace.namespace.namespace_id print(f'export NAMESPACE_ID="{namespace_id}"') - namespace_ref = {"namespace_id": namespace_id} ``` Run the file once, then run the printed `export` command in your shell before running the file again. Later runs reuse that ID. Creating the same namespace again returns `409 Conflict`. If you lose the ID, use `list_namespaces` with `scope="PERSONAL"` and `owner_id=USER_ID` to find it. @@ -47,7 +46,7 @@ Start a new session with this namespace. Extracted memories inherit it: session_id="travel-planning-with-namespace", actor_id=USER_ID, role=models.MessageRole.USER, content=[models.Text(text="I am visiting Tokyo and Kyoto next month.")], - created_at=datetime.now(timezone.utc), namespace_ref=namespace_ref, + created_at=datetime.now(timezone.utc), namespace_id=namespace_id, ) ``` @@ -66,7 +65,6 @@ Add this code inside `run`. It creates a personal namespace for the user's trave namespaceId = createdNamespace.namespace.namespaceId; console.log(`export NAMESPACE_ID="${namespaceId}"`); } - const namespaceRef = { namespaceId }; ``` Run the file once, then run the printed `export` command in your shell before running the file again. Later runs reuse that ID. Creating the same namespace again returns `409 Conflict`. If you lose the ID, use `listNamespaces` with `scope: "PERSONAL"` and `ownerId: userId` to find it. @@ -74,10 +72,10 @@ Run the file once, then run the printed `export` command in your shell before ru Start a new session with this namespace. Extracted memories inherit it: ```typescript - await agentMemory.addSessionEvent({ - sessionId: "travel-planning-with-namespace", actorId: userId, role: "USER", + await agentMemory.addSessionEvent("travel-planning-with-namespace", { + actorId: userId, role: "USER", content: [{ text: "I am visiting Tokyo and Kyoto next month." }], - createdAt: new Date(), namespaceRef, + createdAt: new Date(), namespaceId, }); ``` @@ -135,7 +133,6 @@ Add this code inside the `with` block: }) shared_namespace_id = shared_namespace.namespace.namespace_id print(f'export SHARED_NAMESPACE_ID="{shared_namespace_id}"') - shared_namespace_ref = {"namespace_id": shared_namespace_id} ``` Run the file once, then run the printed `export` command in your shell. Later runs reuse the namespace ID. @@ -154,7 +151,6 @@ Add this code inside `run`: sharedNamespaceId = sharedNamespace.namespace.namespaceId; console.log(`export SHARED_NAMESPACE_ID="${sharedNamespaceId}"`); } - const sharedNamespaceRef = { namespaceId: sharedNamespaceId }; ``` Run the file once, then run the printed `export` command in your shell. Later runs reuse the namespace ID. @@ -180,7 +176,7 @@ Continue after the request succeeds and prints a namespace ID. Reuse that ID for Creating the same root again returns `409 Conflict`. If you lose the ID, list root namespaces with `scope=SHARED` and find `team-travel`. -To add a conversation to this namespace, use a new session ID and set its first event's namespace reference to the shared ID. Use `namespace_ref=shared_namespace_ref` in Python, `namespaceRef: sharedNamespaceRef` in TypeScript, or `"namespaceId": "$SHARED_NAMESPACE_ID"` in curl. For direct long-term memory creation, set the reference on each record. Creating the namespace does not move existing memories into it. +To add a conversation to this namespace, use a new session ID and set its first event's namespace ID to the shared ID. Use `namespace_id=shared_namespace_id` in Python, `namespaceId: sharedNamespaceId` in TypeScript, or `"namespaceId": "$SHARED_NAMESPACE_ID"` in curl. For direct long-term memory creation, set the namespace ID on each record. Creating the namespace does not move existing memories into it. ### Recall shared memories @@ -190,8 +186,8 @@ After writing memories to the shared namespace, search with its namespace ID. Th ```python shared_results = agent_memory.search_long_term_memory(request={ - "text": "What travel requirements has the team discussed?", - "filter_": {"namespace_ref": {"eq": shared_namespace_id}}, + "query": "What travel requirements has the team discussed?", + "filter_": {"namespace_id": {"eq": shared_namespace_id}}, "limit": 5, }) show("Shared travel memories", shared_results) @@ -201,8 +197,8 @@ After writing memories to the shared namespace, search with its namespace ID. Th ```typescript const sharedResults = await agentMemory.searchLongTermMemory({ - text: "What travel requirements has the team discussed?", - filter: { namespaceRef: { eq: sharedNamespaceId } }, + query: "What travel requirements has the team discussed?", + filter: { namespaceId: { eq: sharedNamespaceId } }, limit: 5, }); console.dir(sharedResults, { depth: null }); @@ -265,7 +261,7 @@ For runnable examples, see [Create a personal namespace]({{< relref "/develop/ai | Operation | Behavior | |:----------|:---------| -| List | List roots, or pass `parentId` to list direct children. Sort by `id`, `name`, `createdAt`, or `updatedAt` with `sortBy`; `sortOrder` accepts `ASC` or `DESC`. Defaults are `id` and `asc`. Follow `nextCursor` with the same filters and sort options. | +| List | List roots, or pass `parentId` to list direct children. Sort by `id`, `name`, `createdAt`, or `updatedAt` with `sortBy`; `sortOrder` accepts `ASC` or `DESC`. Defaults are `id` and `ASC`. Follow `nextCursor` with the same filters and sort options. | | Get | Retrieve the current name, path, scope, and state by ID. | | Rename | Update `name`; continue using the same ID for placement and retrieval. | | Archive | Set `state` to `ARCHIVED` to stop new children and placements. You cannot unarchive a namespace. | @@ -281,7 +277,7 @@ Use the client from the [quickstart](/content/develop/ai/context-engine/agent-me ```python namespaces = agent_memory.list_namespaces( - scope="SHARED", limit=20, sort_by="name", sort_order="asc", + scope="SHARED", limit=20, sort_by="name", sort_order="ASC", ) show("Shared namespaces", namespaces) ``` @@ -294,10 +290,10 @@ Use the client from the [quickstart](/content/develop/ai/context-engine/agent-me "SHARED", // scope undefined, // ownerId 20, // limit - undefined, // pageToken + undefined, // cursor undefined, // request options "name", // sortBy - "asc", // sortOrder + "ASC", // sortOrder ); console.dir(namespaces, { depth: null }); ``` diff --git a/content/develop/ai/context-engine/agent-memory/namespaces/namespace-routing.md b/content/develop/ai/context-engine/agent-memory/namespaces/namespace-routing.md index 53d3c2a604..43decb6d12 100644 --- a/content/develop/ai/context-engine/agent-memory/namespaces/namespace-routing.md +++ b/content/develop/ai/context-engine/agent-memory/namespaces/namespace-routing.md @@ -59,11 +59,11 @@ async def main(): "rules": [{ "id": "travel", "enabled": True, - "action": "accept", - "destination": {"namespace_id": os.environ["SHARED_NAMESPACE_ID"]}, + "action": "ACCEPT", + "destination_namespace_id": os.environ["SHARED_NAMESPACE_ID"], "strategies": [{ - "kind": "matcher_spec", - "matcher": {"kind": "regex", "regex": {"pattern": "(?i)travel"}}, + "kind": "MATCHER_SPEC", + "matcher": {"kind": "REGEX", "regex": {"pattern": "(?i)travel"}}, }], }], }) @@ -91,11 +91,11 @@ async function main() { policy: { enabled: true, rules: [{ - id: "travel", enabled: true, action: "accept", - destination: { namespaceId: SHARED_NAMESPACE_ID }, + id: "travel", enabled: true, action: "ACCEPT", + destinationNamespaceId: SHARED_NAMESPACE_ID, strategies: [{ - kind: "matcher_spec", - matcher: { kind: "regex", regex: { pattern: "(?i)travel" } }, + kind: "MATCHER_SPEC", + matcher: { kind: "REGEX", regex: { pattern: "(?i)travel" } }, }], }], }, @@ -189,4 +189,4 @@ curl --fail-with-body --silent --show-error \ {{< /multitabs >}} -Add the SDK snippet inside the client block or `main` function from [Configure a policy](/content/develop/ai/context-engine/agent-memory/namespaces/namespace-routing.md#configure-a-policy). Set `MEMORY_ID` before running it. The example memory must already belong to a shared namespace and contain matching text. The request accepts 1–100 IDs. To choose a destination explicitly, also pass `namespace_ref={"namespace_id": ""}` in Python or `namespaceRef: { namespaceId: "" }` in TypeScript or the request body. Explicit placement still runs admission checks. +Add the SDK snippet inside the client block or `main` function from [Configure a policy](/content/develop/ai/context-engine/agent-memory/namespaces/namespace-routing.md#configure-a-policy). Set `MEMORY_ID` before running it. The example memory must already belong to a shared namespace and contain matching text. The request accepts 1–100 IDs. To choose a destination explicitly, also pass `namespace_id=""` in Python, `namespaceId: ""` in TypeScript, or `"namespaceId"` in the request body. Explicit placement still runs admission checks. diff --git a/content/develop/ai/context-engine/agent-memory/sessions/_index.md b/content/develop/ai/context-engine/agent-memory/sessions/_index.md index a6c0f4162b..32da6c0af9 100644 --- a/content/develop/ai/context-engine/agent-memory/sessions/_index.md +++ b/content/develop/ai/context-engine/agent-memory/sessions/_index.md @@ -175,8 +175,7 @@ Add these events to the session from the quickstart to continue the conversation ] as const; for (const turn of turns) { - await agentMemory.addSessionEvent({ - sessionId, + await agentMemory.addSessionEvent(sessionId, { actorId: turn.actorId, role: turn.role, content: [{ text: turn.text }], diff --git a/content/develop/ai/context-engine/agent-memory/sessions/list-sessions.md b/content/develop/ai/context-engine/agent-memory/sessions/list-sessions.md index d2c0ffe0c1..b3e8ecf097 100644 --- a/content/develop/ai/context-engine/agent-memory/sessions/list-sessions.md +++ b/content/develop/ai/context-engine/agent-memory/sessions/list-sessions.md @@ -50,17 +50,17 @@ async def main(): store_id=os.environ["STORE_ID"], api_key=os.environ["API_KEY"], ) as agent_memory: - page_token = None + cursor = None while True: - page = await agent_memory.list_session_summaries_async( - filter_owner_id=os.environ["OWNER_ID"], - sort_by="updatedAt", sort_order="desc", - limit=20, page_token=page_token, + page = await agent_memory.list_sessions_async( + owner_id=os.environ["OWNER_ID"], + sort_by="updatedAt", sort_order="DESC", + limit=20, cursor=cursor, ) for session in page.items: print(session.model_dump_json(by_alias=True)) - page_token = page.next_page_token - if not page_token: + cursor = page.next_cursor + if not cursor: break @@ -80,20 +80,21 @@ async function main() { const agentMemory = new AgentMemory({ serverURL: AGENT_MEMORY_URL, storeId: STORE_ID, apiKey: API_KEY, }); - let pageToken: string | undefined; + let cursor: string | undefined; do { - const page = await agentMemory.listSessionSummaries( + const page = await agentMemory.listSessions( 20, // limit - pageToken, // pageToken - OWNER_ID, // filterOwnerId - undefined, // namespaceRef + cursor, // cursor + OWNER_ID, // ownerId undefined, // includeAll + undefined, // options + undefined, // namespaceId "updatedAt", // sortBy - "desc", // sortOrder + "DESC", // sortOrder ); console.dir(page.items, { depth: null }); - pageToken = page.nextPageToken; - } while (pageToken); + cursor = page.nextCursor; + } while (cursor); } main().catch((error) => { console.error(error instanceof Error ? error.message : "Request failed"); process.exitCode = 1; }); @@ -102,22 +103,22 @@ main().catch((error) => { console.error(error instanceof Error ? error.message : -tab-sep- ```sh -page_token='' +cursor='' while :; do page=$(curl --fail-with-body --silent --show-error --get \ --header "Authorization: Bearer $API_KEY" \ --data-urlencode "ownerId=$OWNER_ID" \ --data-urlencode 'sortBy=updatedAt' --data-urlencode 'sortOrder=DESC' \ - --data-urlencode 'limit=20' --data-urlencode "cursor=$page_token" \ + --data-urlencode 'limit=20' --data-urlencode "cursor=$cursor" \ "$AGENT_MEMORY_URL/iris/data/v1/agent-memory/stores/$STORE_ID/sessions") || break printf '%s\n' "$page" | jq '.items' - page_token=$(printf '%s\n' "$page" | jq -r '.nextCursor // empty') - [ -n "$page_token" ] || break + cursor=$(printf '%s\n' "$page" | jq -r '.nextCursor // empty') + [ -n "$cursor" ] || break done ``` {{< /multitabs >}} -Pass each returned `nextCursor` as `cursor`. Keep filters and sort options unchanged; the token is bound to them. Stop when the token is absent. The token is opaque, so URL-encode it in REST requests. Changing a filter or sort requires a new request without the old token. +Pass each returned `nextCursor` as `cursor`. Keep filters and sort options unchanged; the cursor is bound to them. Stop when the cursor is absent. The cursor is opaque, so URL-encode it in REST requests. Changing a filter or sort requires a new request without the old cursor. Sessions stored without owner or timestamp metadata can omit `ownerId`, `createdAt`, or `updatedAt`. Handle those missing values when rendering a conversation list. A row's timestamps describe session metadata; they do not promise that background extraction or summarization has completed. diff --git a/content/develop/ai/context-engine/agent-memory/summary-views.md b/content/develop/ai/context-engine/agent-memory/summary-views.md index 4976d683f4..ad2c61f0c4 100644 --- a/content/develop/ai/context-engine/agent-memory/summary-views.md +++ b/content/develop/ai/context-engine/agent-memory/summary-views.md @@ -38,7 +38,7 @@ Shared does not mean a particular team. Enforce team membership in your backend ## Create, refresh, and read a view -These examples create one private profile for `OWNER_ID`, request a full refresh, and poll its result. First [create ordinary long-term memories](/content/develop/ai/context-engine/agent-memory/long-term-memory.md#create-a-custom-memory-directly) in this self-managed store, using the delegated client and matching `OWNER_ID`. A successful refresh with no matching sources returns `empty`. +These examples create one private profile for `OWNER_ID`, request a full refresh, and poll its result. First [create ordinary long-term memories](/content/develop/ai/context-engine/agent-memory/long-term-memory.md#create-a-custom-memory-directly) in this self-managed store, using the delegated client and matching `OWNER_ID`. A successful refresh with no matching sources returns `EMPTY`. Save the view ID for later requests. Creation and refresh are asynchronous; their responses do not contain generated output. @@ -58,32 +58,32 @@ async def main(): api_key=os.environ["API_KEY"], ) as memory: view = await memory.create_summary_view_async( - name="Travel profile", source="long_term", group_by=[], + name="Travel profile", source="LONG_TERM", group_by=[], filter_={"owner_id": {"eq": os.environ["OWNER_ID"]}}, - output={"format_": "text", "instructions": "Summarize the user's travel preferences."}, - refresh_policy={"mode": "manual"}, http_headers=headers, + output={"format_": "TEXT", "instructions": "Summarize the user's travel preferences."}, + refresh_policy={"mode": "MANUAL"}, http_headers=headers, ) - print("View ID:", view.id) + print("View ID:", view.view_id) accepted = await memory.refresh_summary_view_async( - view_id=view.id, target="full", http_headers=headers, + view_id=view.view_id, target="FULL", http_headers=headers, ) print(accepted.model_dump_json(by_alias=True)) for _ in range(60): result = await memory.get_summary_view_result_async( - view_id=view.id, include_source_memory_ids=True, http_headers=headers, + view_id=view.view_id, include_source_memory_ids=True, http_headers=headers, ) - if result.status == "failed": + if result.status == "FAILED": raise RuntimeError(f"Refresh failed: {result.error_code}") - if result.status == "empty": + if result.status == "EMPTY": print("No matching source memories.") return - if result.status == "ready" and not result.stale: + if result.status == "READY" and not result.stale: if result.value is None: raise RuntimeError("Ready result omitted its value") print(result.model_dump_json(by_alias=True)) return await asyncio.sleep(2) - raise TimeoutError(f"Continue polling view {view.id}") + raise TimeoutError(f"Continue polling view {view.view_id}") asyncio.run(main()) @@ -103,36 +103,36 @@ async function main() { const memory = new AgentMemory({ serverURL: AGENT_MEMORY_URL, storeId: STORE_ID, apiKey: API_KEY }); const options = { headers: { "X-Iris-User-Token": USER_TOKEN } }; const view = await memory.createSummaryView({ - name: "Travel profile", source: "long_term", groupBy: [], + name: "Travel profile", source: "LONG_TERM", groupBy: [], filter: { ownerId: { eq: OWNER_ID } }, - output: { format: "text", instructions: "Summarize the user's travel preferences." }, - refreshPolicy: { mode: "manual" }, + output: { format: "TEXT", instructions: "Summarize the user's travel preferences." }, + refreshPolicy: { mode: "MANUAL" }, }, options); - console.log("View ID:", view.id); - console.dir(await memory.refreshSummaryView(view.id, { target: "full" }, options)); + console.log("View ID:", view.viewId); + console.dir(await memory.refreshSummaryView(view.viewId, { target: "FULL" }, options)); for (let attempt = 0; attempt < 60; attempt++) { const result = await memory.getSummaryViewResult( - view.id, // viewId + view.viewId, // viewId undefined, // ownerId undefined, // sessionId - undefined, // namespaceRef + undefined, // namespaceId undefined, // memoryType true, // includeSourceMemoryIds options, // request options ); - if (result.status === "failed") throw new Error(`Refresh failed: ${result.errorCode}`); - if (result.status === "empty") { + if (result.status === "FAILED") throw new Error(`Refresh failed: ${result.errorCode}`); + if (result.status === "EMPTY") { console.log("No matching source memories."); return; } - if (result.status === "ready" && !result.stale) { + if (result.status === "READY" && !result.stale) { if (!result.value) throw new Error("Ready result omitted its value"); console.dir(result, { depth: null }); return; } await delay(2000); } - throw new Error(`Continue polling view ${view.id}`); + throw new Error(`Continue polling view ${view.viewId}`); } main().catch((error) => { console.error(error instanceof Error ? error.message : "Request failed"); process.exitCode = 1; }); diff --git a/local_examples/agent-memory/agent_memory_sdk.py b/local_examples/agent-memory/agent_memory_sdk.py index 26130f14b7..fc7ec80c9d 100644 --- a/local_examples/agent-memory/agent_memory_sdk.py +++ b/local_examples/agent-memory/agent_memory_sdk.py @@ -112,7 +112,7 @@ def main(): results = agent_memory.search_long_term_memory( request={ - "text": "What dietary requirements and food preferences does the user have?", + "query": "What dietary requirements and food preferences does the user have?", "filter_": { "owner_id": { "eq": USER_ID, diff --git a/local_examples/agent-memory/agent_memory_sdk.ts b/local_examples/agent-memory/agent_memory_sdk.ts index fd734a40d0..e8045abe75 100644 --- a/local_examples/agent-memory/agent_memory_sdk.ts +++ b/local_examples/agent-memory/agent_memory_sdk.ts @@ -55,8 +55,7 @@ async function run() { console.log("Store health:"); console.dir(health, { depth: null }); - const event = await agentMemory.addSessionEvent({ - sessionId, + const event = await agentMemory.addSessionEvent(sessionId, { actorId: userId, role: "USER", content: [{ @@ -103,7 +102,7 @@ async function run() { console.dir(health, { depth: null }); const results = await agentMemory.searchLongTermMemory({ - text: "What dietary requirements and food preferences does the user have?", + query: "What dietary requirements and food preferences does the user have?", filter: { ownerId: { eq: userId,