Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/memory.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ If you created an Strands agent without memory and want to integrate it with you

retrieval_config = {
f"/users/{actor_id}/facts": RetrievalConfig(top_k=3, relevance_score=0.5),
f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5)
f"/summaries/{actor_id}": RetrievalConfig(top_k=3, relevance_score=0.5)
}

return AgentCoreMemorySessionManager(
Expand Down Expand Up @@ -153,11 +153,11 @@ async def invoke(payload, context):
The `create` and `add agent` commands accept a `--memory` flag with one of three shorthand values. Each maps to a
specific memory configuration:

| Shorthand | Strategies Created |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `none` | No memory resource created |
| `shortTerm` | Memory with no strategies (session context via event expiry only, default 30 days) |
| `longAndShortTerm` | Memory with four strategies: `SEMANTIC` (`/users/{actorId}/facts`), `USER_PREFERENCE` (`/users/{actorId}/preferences`), `SUMMARIZATION` (`/summaries/{actorId}/{sessionId}`), `EPISODIC` (`/episodes/{actorId}/{sessionId}`, reflection: `/episodes/{actorId}`) |
| Shorthand | Strategies Created |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `none` | No memory resource created |
| `shortTerm` | Memory with no strategies (session context via event expiry only, default 30 days) |
| `longAndShortTerm` | Memory with four strategies: `SEMANTIC` (`/users/{actorId}/facts`), `USER_PREFERENCE` (`/users/{actorId}/preferences`), `SUMMARIZATION` (`/summaries/{actorId}`), `EPISODIC` (`/episodes/{actorId}/{sessionId}`, reflection: `/episodes/{actorId}`) |

**Short-term memory** provides basic conversation context within a session — events are stored and expire after the
configured duration, but no long-term extraction or search is performed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2255,7 +2255,7 @@ def get_memory_session_manager(session_id: Optional[str], actor_id: str) -> Opti
f"/episodes/{actor_id}/{session_id}": RetrievalConfig(top_k=5, relevance_score=0.5),
{{/if}}
{{#if (includes memoryProviders.[0].strategies "SUMMARIZATION")}}
f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
f"/summaries/{actor_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
{{/if}}
}
{{/if}}
Expand Down Expand Up @@ -3277,7 +3277,7 @@ def get_memory_session_manager(session_id: Optional[str], actor_id: str) -> Opti
f"/episodes/{actor_id}/{session_id}": RetrievalConfig(top_k=5, relevance_score=0.5),
{{/if}}
{{#if (includes memoryProviders.[0].strategies "SUMMARIZATION")}}
f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
f"/summaries/{actor_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
{{/if}}
}
{{/if}}
Expand Down Expand Up @@ -6545,7 +6545,7 @@ def get_memory_session_manager(session_id: Optional[str], actor_id: str) -> Opti
f"/episodes/{actor_id}/{session_id}": RetrievalConfig(top_k=5, relevance_score=0.5),
{{/if}}
{{#if (includes memoryProviders.[0].strategies "SUMMARIZATION")}}
f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
f"/summaries/{actor_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
{{/if}}
}
{{/if}}
Expand Down
43 changes: 43 additions & 0 deletions src/assets/__tests__/summarization-namespace.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Regression test for cross-session SUMMARIZATION recall (issue #665).
*
* The SUMMARIZATION retrieval namespace must be actor-scoped (`/summaries/{actor_id}`),
* not session-scoped. The SDK's namespace_path is a hierarchical prefix match, so a
* per-session prefix (`/summaries/{actor_id}/{session_id}`) only ever matches the current
* session's own summaries and never surfaces summaries written by prior sessions —
* silently breaking cross-session recall. This guards against another silent revert
* (see PR #1299, reverted by squash release #1547).
*/
import Handlebars from 'handlebars';
import * as fs from 'fs';
import * as path from 'path';
import { describe, expect, it } from 'vitest';
// Importing render registers the `includes` Handlebars helper used by the template.
import '../../cli/templates/render.js';

const FLAVORS = ['http', 'agui', 'a2a'] as const;

function renderSessionTemplate(flavor: string): string {
const templatePath = path.resolve(
__dirname,
'..',
'python',
flavor,
'strands',
'capabilities',
'memory',
'session.py'
);
const content = fs.readFileSync(templatePath, 'utf-8');
return Handlebars.compile(content)({
memoryProviders: [{ envVarName: 'MEMORY_TEST_ID', strategies: ['SUMMARIZATION'] }],
});
}

describe('SUMMARIZATION retrieval namespace', () => {
it.each(FLAVORS)('%s session.py uses an actor-scoped summary namespace', flavor => {
const rendered = renderSessionTemplate(flavor);
expect(rendered).toContain('f"/summaries/{actor_id}": RetrievalConfig');
expect(rendered).not.toContain('/summaries/{actor_id}/{session_id}');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def get_memory_session_manager(session_id: Optional[str], actor_id: str) -> Opti
f"/episodes/{actor_id}/{session_id}": RetrievalConfig(top_k=5, relevance_score=0.5),
{{/if}}
{{#if (includes memoryProviders.[0].strategies "SUMMARIZATION")}}
f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
f"/summaries/{actor_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
{{/if}}
}
{{/if}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def get_memory_session_manager(session_id: Optional[str], actor_id: str) -> Opti
f"/episodes/{actor_id}/{session_id}": RetrievalConfig(top_k=5, relevance_score=0.5),
{{/if}}
{{#if (includes memoryProviders.[0].strategies "SUMMARIZATION")}}
f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
f"/summaries/{actor_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
{{/if}}
}
{{/if}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def get_memory_session_manager(session_id: Optional[str], actor_id: str) -> Opti
f"/episodes/{actor_id}/{session_id}": RetrievalConfig(top_k=5, relevance_score=0.5),
{{/if}}
{{#if (includes memoryProviders.[0].strategies "SUMMARIZATION")}}
f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
f"/summaries/{actor_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
{{/if}}
}
{{/if}}
Expand Down
Loading