Skip to content

Commit 2854150

Browse files
authored
chore: update namespace design for data plane (#1114)
* chore: update namespace design for data plane * fix: add web-UI API types and additional testing
1 parent a4605ef commit 2854150

18 files changed

Lines changed: 866 additions & 63 deletions

File tree

src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,7 +1885,7 @@ dependencies = [
18851885
{{#if (eq modelProvider "Anthropic")}}"anthropic >= 0.30.0",
18861886
{{/if}}"a2a-sdk[all] >= 0.2.0, < 1.0.0",
18871887
"aws-opentelemetry-distro",
1888-
"bedrock-agentcore[a2a] >= 1.0.3",
1888+
"bedrock-agentcore[a2a] >= 1.9.1",
18891889
"botocore[crt] >= 1.35.0",
18901890
{{#if (eq modelProvider "Gemini")}}"google-genai >= 1.0.0",
18911891
{{/if}}{{#if (eq modelProvider "OpenAI")}}"openai >= 1.0.0",
@@ -2722,7 +2722,7 @@ dependencies = [
27222722
{{/if}}"ag-ui-strands >= 0.1.7",
27232723
"ag-ui-protocol >= 0.1.10",
27242724
"aws-opentelemetry-distro",
2725-
"bedrock-agentcore >= 1.0.3",
2725+
"bedrock-agentcore >= 1.9.1",
27262726
"botocore[crt] >= 1.35.0",
27272727
"fastapi >= 0.115.12",
27282728
{{#if (eq modelProvider "Gemini")}}"google-genai >= 1.0.0",
@@ -5103,7 +5103,7 @@ requires-python = ">=3.10"
51035103
dependencies = [
51045104
{{#if (eq modelProvider "Anthropic")}}"anthropic >= 0.30.0",
51055105
{{/if}}"aws-opentelemetry-distro",
5106-
"bedrock-agentcore >= 1.0.3",
5106+
"bedrock-agentcore >= 1.9.1",
51075107
"botocore[crt] >= 1.35.0",
51085108
{{#if (eq modelProvider "Gemini")}}"google-genai >= 1.0.0",
51095109
{{/if}}"mcp >= 1.19.0",

src/assets/python/a2a/strands/base/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ dependencies = [
1212
{{#if (eq modelProvider "Anthropic")}}"anthropic >= 0.30.0",
1313
{{/if}}"a2a-sdk[all] >= 0.2.0, < 1.0.0",
1414
"aws-opentelemetry-distro",
15-
"bedrock-agentcore[a2a] >= 1.0.3",
15+
"bedrock-agentcore[a2a] >= 1.9.1",
1616
"botocore[crt] >= 1.35.0",
1717
{{#if (eq modelProvider "Gemini")}}"google-genai >= 1.0.0",
1818
{{/if}}{{#if (eq modelProvider "OpenAI")}}"openai >= 1.0.0",

src/assets/python/agui/strands/base/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ dependencies = [
1313
{{/if}}"ag-ui-strands >= 0.1.7",
1414
"ag-ui-protocol >= 0.1.10",
1515
"aws-opentelemetry-distro",
16-
"bedrock-agentcore >= 1.0.3",
16+
"bedrock-agentcore >= 1.9.1",
1717
"botocore[crt] >= 1.35.0",
1818
"fastapi >= 0.115.12",
1919
{{#if (eq modelProvider "Gemini")}}"google-genai >= 1.0.0",

src/assets/python/http/strands/base/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ requires-python = ">=3.10"
1111
dependencies = [
1212
{{#if (eq modelProvider "Anthropic")}}"anthropic >= 0.30.0",
1313
{{/if}}"aws-opentelemetry-distro",
14-
"bedrock-agentcore >= 1.0.3",
14+
"bedrock-agentcore >= 1.9.1",
1515
"botocore[crt] >= 1.35.0",
1616
{{#if (eq modelProvider "Gemini")}}"google-genai >= 1.0.0",
1717
{{/if}}"mcp >= 1.19.0",

src/cli/commands/dev/browser-mode.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,27 +60,27 @@ async function resolveDeployedHandlers(
6060
`Memory browsing enabled for ${memories.length} deployed memory(ies): ${memories.map(m => m.name).join(', ')}`
6161
);
6262

63-
result.onListMemoryRecords = async (memoryName, namespace, strategyId) => {
64-
const memory = memories.find(m => m.name === memoryName);
65-
if (!memory) return { success: false, error: `Memory "${memoryName}" not found in deployed state` };
63+
result.onListMemoryRecords = async args => {
64+
const memory = memories.find(m => m.name === args.memoryName);
65+
if (!memory) return { success: false, error: `Memory "${args.memoryName}" not found in deployed state` };
6666
const res = await listMemoryRecords({
6767
region: memory.region,
6868
memoryId: memory.memoryId,
69-
namespace,
70-
memoryStrategyId: strategyId,
69+
memoryStrategyId: args.strategyId,
70+
...(args.namespace ? { namespace: args.namespace } : { namespacePath: args.namespacePath! }),
7171
});
7272
return res.success ? res : { success: false as const, error: res.error.message };
7373
};
7474

75-
result.onRetrieveMemoryRecords = async (memoryName, namespace, searchQuery, strategyId) => {
76-
const memory = memories.find(m => m.name === memoryName);
77-
if (!memory) return { success: false, error: `Memory "${memoryName}" not found in deployed state` };
75+
result.onRetrieveMemoryRecords = async args => {
76+
const memory = memories.find(m => m.name === args.memoryName);
77+
if (!memory) return { success: false, error: `Memory "${args.memoryName}" not found in deployed state` };
7878
const res = await retrieveMemoryRecords({
7979
region: memory.region,
8080
memoryId: memory.memoryId,
81-
namespace,
82-
searchQuery,
83-
memoryStrategyId: strategyId,
81+
searchQuery: args.searchQuery,
82+
memoryStrategyId: args.strategyId,
83+
...(args.namespace ? { namespace: args.namespace } : { namespacePath: args.namespacePath! }),
8484
});
8585
return res.success ? res : { success: false as const, error: res.error.message };
8686
};
@@ -239,15 +239,15 @@ export async function runBrowserMode(opts: BrowserModeOptions): Promise<void> {
239239
};
240240
}
241241
},
242-
onListMemoryRecords: async (memoryName, namespace, strategyId) => {
242+
onListMemoryRecords: async args => {
243243
const deployed = await resolveDeployedHandlers(baseDir, onLog);
244244
if (!deployed.onListMemoryRecords) return { success: false, error: 'No deployed AgentCore Memory found' };
245-
return deployed.onListMemoryRecords(memoryName, namespace, strategyId);
245+
return deployed.onListMemoryRecords(args);
246246
},
247-
onRetrieveMemoryRecords: async (memoryName, namespace, searchQuery, strategyId) => {
247+
onRetrieveMemoryRecords: async args => {
248248
const deployed = await resolveDeployedHandlers(baseDir, onLog);
249249
if (!deployed.onRetrieveMemoryRecords) return { success: false, error: 'No deployed AgentCore Memory found' };
250-
return deployed.onRetrieveMemoryRecords(memoryName, namespace, searchQuery, strategyId);
250+
return deployed.onRetrieveMemoryRecords(args);
251251
},
252252
},
253253
});

src/cli/operations/agent/import/__tests__/translator.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,29 @@ describe('StrandsTranslator', () => {
8181
expect(result.features.hasMemory).toBe(true);
8282
});
8383

84+
it('emits namespace_path (not namespace) in retrieve_memories calls for longAndShortTerm memory', () => {
85+
const config = makeSimpleAgentConfig({
86+
agent: {
87+
...makeSimpleAgentConfig().agent,
88+
memoryConfiguration: { enabledMemoryTypes: ['SESSION_SUMMARY'] },
89+
},
90+
});
91+
const translator = new StrandsTranslator(config, {
92+
agentConfig: config,
93+
enableMemory: true,
94+
memoryOption: 'longAndShortTerm',
95+
enableObservability: false,
96+
});
97+
const result = translator.translate();
98+
99+
// All three retrieval calls should use the new namespace_path kwarg
100+
expect(result.mainPyContent).toContain("namespace_path=f'/users/{user_id}/facts'");
101+
expect(result.mainPyContent).toContain("namespace_path=f'/users/{user_id}/preferences'");
102+
expect(result.mainPyContent).toContain("namespace_path=f'/summaries/{user_id}/'");
103+
// The deprecated kwarg form must not appear for longAndShortTerm retrievals
104+
expect(result.mainPyContent).not.toMatch(/retrieve_memories\([^)]*\bnamespace=/);
105+
});
106+
84107
it('generates action group tools for function-schema action groups', () => {
85108
const config = makeSimpleAgentConfig({
86109
action_groups: [
@@ -221,6 +244,29 @@ describe('LangGraphTranslator', () => {
221244
expect(result.mainPyContent).toContain('gr-123');
222245
expect(result.features.hasGuardrails).toBe(true);
223246
});
247+
248+
it('emits namespace_path (not namespace) in retrieve_memories calls for longAndShortTerm memory', () => {
249+
const config = makeSimpleAgentConfig({
250+
agent: {
251+
...makeSimpleAgentConfig().agent,
252+
memoryConfiguration: { enabledMemoryTypes: ['SESSION_SUMMARY'] },
253+
},
254+
});
255+
const translator = new LangGraphTranslator(config, {
256+
agentConfig: config,
257+
enableMemory: true,
258+
memoryOption: 'longAndShortTerm',
259+
enableObservability: false,
260+
});
261+
const result = translator.translate();
262+
263+
// All three retrieval calls should use the new namespace_path kwarg
264+
expect(result.mainPyContent).toContain("namespace_path=f'/users/{user_id}/facts'");
265+
expect(result.mainPyContent).toContain("namespace_path=f'/users/{user_id}/preferences'");
266+
expect(result.mainPyContent).toContain("namespace_path=f'/summaries/{user_id}/'");
267+
// The deprecated kwarg form must not appear for longAndShortTerm retrievals
268+
expect(result.mainPyContent).not.toMatch(/retrieve_memories\([^)]*\bnamespace=/);
269+
});
224270
});
225271

226272
describe('generatePyprojectToml', () => {

src/cli/operations/agent/import/langgraph-translator.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,9 @@ def invoke_${collabName}(query: str, state: Annotated[dict, InjectedState]) -> s
209209
const memoryRetrieveCode =
210210
this.agentcoreMemoryEnabled && this.hasLongTermStrategies
211211
? `
212-
semantic_memories = memory_client.retrieve_memories(memory_id=memory_id, namespace=f'/users/{user_id}/facts', query="Retrieve relevant facts.", actor_id=user_id, top_k=3)
213-
pref_memories = memory_client.retrieve_memories(memory_id=memory_id, namespace=f'/users/{user_id}/preferences', query="Retrieve user preferences.", actor_id=user_id, top_k=3)
214-
summary_memories = memory_client.retrieve_memories(memory_id=memory_id, namespace=f'/summaries/{user_id}/', query="Retrieve the most recent session summaries.", actor_id=user_id, top_k=3)
212+
semantic_memories = memory_client.retrieve_memories(memory_id=memory_id, namespace_path=f'/users/{user_id}/facts', query="Retrieve relevant facts.", actor_id=user_id, top_k=3)
213+
pref_memories = memory_client.retrieve_memories(memory_id=memory_id, namespace_path=f'/users/{user_id}/preferences', query="Retrieve user preferences.", actor_id=user_id, top_k=3)
214+
summary_memories = memory_client.retrieve_memories(memory_id=memory_id, namespace_path=f'/summaries/{user_id}/', query="Retrieve the most recent session summaries.", actor_id=user_id, top_k=3)
215215
all_memories = semantic_memories + pref_memories + summary_memories
216216
memory_synopsis = "\\n".join([m.get("content", {}).get("text", "") for m in all_memories])`
217217
: this.memoryEnabled

src/cli/operations/agent/import/pyproject-generator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { ImportedFeatures } from './base-translator';
66

77
const BASE_DEPS = [
88
'aws-opentelemetry-distro',
9-
'bedrock-agentcore >= 1.0.3',
9+
'bedrock-agentcore >= 1.9.1',
1010
'botocore[crt] >= 1.35.0',
1111
'boto3>=1.38.0',
1212
];
@@ -22,7 +22,7 @@ const LANGGRAPH_DEPS = [
2222
'tiktoken==0.11.0',
2323
];
2424

25-
const MEMORY_DEPS = ['bedrock-agentcore[memory] >= 1.0.3'];
25+
const MEMORY_DEPS = ['bedrock-agentcore[memory] >= 1.9.1'];
2626

2727
export function generatePyprojectToml(agentName: string, framework: SDKFramework, features: ImportedFeatures): string {
2828
const deps = [...BASE_DEPS];

src/cli/operations/agent/import/strands-translator.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,9 @@ def invoke_${collabName}(query: str) -> str:
185185
const memoryRetrieveLines =
186186
this.agentcoreMemoryEnabled && this.hasLongTermStrategies
187187
? [
188-
' semantic_memories = memory_client.retrieve_memories(memory_id=memory_id, namespace=f\'/users/{user_id}/facts\', query="Retrieve relevant facts.", actor_id=user_id, top_k=3)',
189-
' pref_memories = memory_client.retrieve_memories(memory_id=memory_id, namespace=f\'/users/{user_id}/preferences\', query="Retrieve user preferences.", actor_id=user_id, top_k=3)',
190-
' summary_memories = memory_client.retrieve_memories(memory_id=memory_id, namespace=f\'/summaries/{user_id}/\', query="Retrieve the most recent session summaries.", actor_id=user_id, top_k=3)',
188+
' semantic_memories = memory_client.retrieve_memories(memory_id=memory_id, namespace_path=f\'/users/{user_id}/facts\', query="Retrieve relevant facts.", actor_id=user_id, top_k=3)',
189+
' pref_memories = memory_client.retrieve_memories(memory_id=memory_id, namespace_path=f\'/users/{user_id}/preferences\', query="Retrieve user preferences.", actor_id=user_id, top_k=3)',
190+
' summary_memories = memory_client.retrieve_memories(memory_id=memory_id, namespace_path=f\'/summaries/{user_id}/\', query="Retrieve the most recent session summaries.", actor_id=user_id, top_k=3)',
191191
' all_memories = semantic_memories + pref_memories + summary_memories',
192192
' memory_synopsis = "\\n".join([m.get("content", {}).get("text", "") for m in all_memories])',
193193
]

src/cli/operations/dev/web-ui/README.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,13 @@ Response:
209209
{ "success": true, "spans": [...] }
210210
```
211211

212-
### `GET /api/memory?memoryName=xxx&namespace=yyy[&strategyId=zzz]`
212+
### `GET /api/memory?memoryName=xxx&(namespace=yyy|namespacePath=yyy)[&strategyId=zzz]`
213213

214-
Lists memory records for a given memory and namespace. Requires a deployed memory with `onListMemoryRecords` handler.
214+
Lists memory records for a given memory, filtered by either an exact namespace or a namespace path prefix. Requires a
215+
deployed memory with `onListMemoryRecords` handler.
216+
217+
Exactly one of `namespace` (exact match) or `namespacePath` (hierarchical path prefix) must be provided. Supplying both
218+
returns HTTP 400.
215219

216220
Response:
217221

@@ -223,10 +227,18 @@ Response:
223227

224228
Performs semantic search across memory records. Requires a deployed memory with `onRetrieveMemoryRecords` handler.
225229

230+
Exactly one of `namespace` or `namespacePath` must be provided in the request body.
231+
226232
Request:
227233

228234
```json
229-
{ "memoryName": "MyMemory", "namespace": "/users/123/facts", "searchQuery": "preferences", "strategyId": "optional" }
235+
{ "memoryName": "MyMemory", "namespacePath": "/users/123/", "searchQuery": "preferences", "strategyId": "optional" }
236+
```
237+
238+
Or with exact-match semantics:
239+
240+
```json
241+
{ "memoryName": "MyMemory", "namespace": "/users/123/facts", "searchQuery": "preferences" }
230242
```
231243

232244
Response:

0 commit comments

Comments
 (0)