diff --git a/docs/commands.md b/docs/commands.md index 3a617b4a..851370d0 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -225,12 +225,12 @@ agentcore add memory \ --expiry 30 ``` -| Flag | Description | -| ---------------------- | ------------------------------------------------------------------------------------- | -| `--name ` | Memory name | -| `--strategies ` | Comma-separated: `SEMANTIC`, `SUMMARIZATION`, `USER_PREFERENCE`, `EPISODIC`, `CUSTOM` | -| `--expiry ` | Event expiry duration in days (default: 30, min: 7, max: 365) | -| `--json` | JSON output | +| Flag | Description | +| ---------------------- | --------------------------------------------------------------------------- | +| `--name ` | Memory name | +| `--strategies ` | Comma-separated: `SEMANTIC`, `SUMMARIZATION`, `USER_PREFERENCE`, `EPISODIC` | +| `--expiry ` | Event expiry duration in days (default: 30, min: 7, max: 365) | +| `--json` | JSON output | ### add gateway diff --git a/docs/configuration.md b/docs/configuration.md index 3c4194a6..0003686e 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -239,13 +239,12 @@ on the next deployment. ### Memory Strategies -| Strategy | Description | -| ----------------- | ----------------------------------------------------------- | -| `SEMANTIC` | Vector-based similarity search for relevant context | -| `SUMMARIZATION` | Compressed conversation history | -| `USER_PREFERENCE` | Store user-specific preferences and settings | -| `EPISODIC` | Capture and reflect on meaningful interaction episodes | -| `CUSTOM` | Self-managed strategy with user-controlled extraction logic | +| Strategy | Description | +| ----------------- | ------------------------------------------------------ | +| `SEMANTIC` | Vector-based similarity search for relevant context | +| `SUMMARIZATION` | Compressed conversation history | +| `USER_PREFERENCE` | Store user-specific preferences and settings | +| `EPISODIC` | Capture and reflect on meaningful interaction episodes | Strategy configuration: diff --git a/docs/memory.md b/docs/memory.md index 615de94b..0a1195b8 100644 --- a/docs/memory.md +++ b/docs/memory.md @@ -168,13 +168,12 @@ conversations, enabling cross-session recall via semantic search. ## Memory Strategies -| Strategy | Description | -| ----------------- | ----------------------------------------------------------- | -| `SEMANTIC` | Vector-based similarity search for relevant context | -| `SUMMARIZATION` | Compressed conversation history | -| `USER_PREFERENCE` | Store user-specific preferences and settings | -| `EPISODIC` | Capture and reflect on meaningful interaction episodes | -| `CUSTOM` | Self-managed strategy with user-controlled extraction logic | +| Strategy | Description | +| ----------------- | ------------------------------------------------------ | +| `SEMANTIC` | Vector-based similarity search for relevant context | +| `SUMMARIZATION` | Compressed conversation history | +| `USER_PREFERENCE` | Store user-specific preferences and settings | +| `EPISODIC` | Capture and reflect on meaningful interaction episodes | You can combine multiple strategies: @@ -189,36 +188,6 @@ You can combine multiple strategies: } ``` -### Self-Managed (Custom) Strategy - -The `CUSTOM` strategy lets you control memory extraction logic externally rather than relying on built-in -implementations. This is useful when you need specialized extraction pipelines or want to integrate with your own -processing infrastructure. - -**Prerequisites:** CUSTOM strategies require user-managed extraction logic and are not functional without it. You must -implement your own extraction mechanism (e.g., via AWS Lambda). - -**Key characteristics:** - -- No default namespaces are assigned — you provide your own or omit them -- Each memory supports at most one CUSTOM strategy -- You are responsible for implementing the extraction logic that processes memory events - -```json -{ - "type": "AgentCoreMemory", - "name": "MyMemory", - "eventExpiryDuration": 30, - "strategies": [ - { - "type": "CUSTOM", - "name": "my_custom_strategy", - "description": "Custom extraction logic" - } - ] -} -``` - ### Strategy Options Each strategy can have optional configuration: diff --git a/src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap b/src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap index 2aaf157e..793de2f3 100644 --- a/src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap +++ b/src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap @@ -1696,11 +1696,6 @@ def get_memory_session_manager(session_id: str, actor_id: str) -> Optional[Agent {{/if}} {{#if (includes memoryProviders.[0].strategies "SUMMARIZATION")}} f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5), -{{/if}} -{{#if (includes memoryProviders.[0].strategies "CUSTOM")}} - # TODO: Add your custom namespace and retrieval config. - # Custom strategies use user-controlled extraction logic. - # Example: f"/custom/{actor_id}/data": RetrievalConfig(top_k=3, relevance_score=0.5), {{/if}} } {{/if}} @@ -3662,11 +3657,6 @@ def get_memory_session_manager(session_id: str, actor_id: str) -> Optional[Agent {{/if}} {{#if (includes memoryProviders.[0].strategies "SUMMARIZATION")}} f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5), -{{/if}} -{{#if (includes memoryProviders.[0].strategies "CUSTOM")}} - # TODO: Add your custom namespace and retrieval config. - # Custom strategies use user-controlled extraction logic. - # Example: f"/custom/{actor_id}/data": RetrievalConfig(top_k=3, relevance_score=0.5), {{/if}} } {{/if}} @@ -4010,7 +4000,7 @@ file maps to a JSON config file and includes validation constraints as comments. - **BuildType**: \`'CodeZip'\` | \`'Container'\` - **NetworkMode**: \`'PUBLIC'\` - **RuntimeVersion**: \`'PYTHON_3_10'\` | \`'PYTHON_3_11'\` | \`'PYTHON_3_12'\` | \`'PYTHON_3_13'\` -- **MemoryStrategyType**: \`'SEMANTIC'\` | \`'SUMMARIZATION'\` | \`'USER_PREFERENCE'\` | \`'EPISODIC'\` | \`'CUSTOM'\` +- **MemoryStrategyType**: \`'SEMANTIC'\` | \`'SUMMARIZATION'\` | \`'USER_PREFERENCE'\` | \`'EPISODIC'\` ### Build Types diff --git a/src/assets/agents/AGENTS.md b/src/assets/agents/AGENTS.md index 86351f3f..10c5b45b 100644 --- a/src/assets/agents/AGENTS.md +++ b/src/assets/agents/AGENTS.md @@ -63,7 +63,7 @@ file maps to a JSON config file and includes validation constraints as comments. - **BuildType**: `'CodeZip'` | `'Container'` - **NetworkMode**: `'PUBLIC'` - **RuntimeVersion**: `'PYTHON_3_10'` | `'PYTHON_3_11'` | `'PYTHON_3_12'` | `'PYTHON_3_13'` -- **MemoryStrategyType**: `'SEMANTIC'` | `'SUMMARIZATION'` | `'USER_PREFERENCE'` | `'EPISODIC'` | `'CUSTOM'` +- **MemoryStrategyType**: `'SEMANTIC'` | `'SUMMARIZATION'` | `'USER_PREFERENCE'` | `'EPISODIC'` ### Build Types diff --git a/src/assets/python/a2a/strands/capabilities/memory/session.py b/src/assets/python/a2a/strands/capabilities/memory/session.py index c95cf40f..9661243b 100644 --- a/src/assets/python/a2a/strands/capabilities/memory/session.py +++ b/src/assets/python/a2a/strands/capabilities/memory/session.py @@ -21,11 +21,6 @@ def get_memory_session_manager(session_id: str, actor_id: str) -> Optional[Agent {{/if}} {{#if (includes memoryProviders.[0].strategies "SUMMARIZATION")}} f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5), -{{/if}} -{{#if (includes memoryProviders.[0].strategies "CUSTOM")}} - # TODO: Add your custom namespace and retrieval config. - # Custom strategies use user-controlled extraction logic. - # Example: f"/custom/{actor_id}/data": RetrievalConfig(top_k=3, relevance_score=0.5), {{/if}} } {{/if}} diff --git a/src/assets/python/http/strands/capabilities/memory/session.py b/src/assets/python/http/strands/capabilities/memory/session.py index afebc29c..dc0cb7bf 100644 --- a/src/assets/python/http/strands/capabilities/memory/session.py +++ b/src/assets/python/http/strands/capabilities/memory/session.py @@ -21,11 +21,6 @@ def get_memory_session_manager(session_id: str, actor_id: str) -> Optional[Agent {{/if}} {{#if (includes memoryProviders.[0].strategies "SUMMARIZATION")}} f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5), -{{/if}} -{{#if (includes memoryProviders.[0].strategies "CUSTOM")}} - # TODO: Add your custom namespace and retrieval config. - # Custom strategies use user-controlled extraction logic. - # Example: f"/custom/{actor_id}/data": RetrievalConfig(top_k=3, relevance_score=0.5), {{/if}} } {{/if}} diff --git a/src/cli/commands/add/__tests__/add-memory.test.ts b/src/cli/commands/add/__tests__/add-memory.test.ts index 7cbab67f..3a518f79 100644 --- a/src/cli/commands/add/__tests__/add-memory.test.ts +++ b/src/cli/commands/add/__tests__/add-memory.test.ts @@ -51,17 +51,16 @@ describe('add memory command', () => { expect(json.error.includes('INVALID'), `Error: ${json.error}`).toBeTruthy(); }); - // Issue #677: CUSTOM strategy is now supported - it('creates memory with CUSTOM strategy', async () => { - const memoryName = `memCustom${Date.now()}`; + // Issue #235: CUSTOM strategy has been removed + it('rejects CUSTOM strategy', async () => { const result = await runCLI( - ['add', 'memory', '--name', memoryName, '--strategies', 'CUSTOM', '--json'], + ['add', 'memory', '--name', 'testCustom', '--strategies', 'CUSTOM', '--json'], projectDir ); - expect(result.exitCode, `stdout: ${result.stdout}, stderr: ${result.stderr}`).toBe(0); + expect(result.exitCode).toBe(1); const json = JSON.parse(result.stdout); - expect(json.success).toBe(true); - expect(json.memoryName).toBe(memoryName); + expect(json.success).toBe(false); + expect(json.error.includes('CUSTOM'), `Error: ${json.error}`).toBeTruthy(); }); }); diff --git a/src/cli/commands/add/__tests__/validate.test.ts b/src/cli/commands/add/__tests__/validate.test.ts index 68c5c098..6c73adb3 100644 --- a/src/cli/commands/add/__tests__/validate.test.ts +++ b/src/cli/commands/add/__tests__/validate.test.ts @@ -953,15 +953,17 @@ describe('validate', () => { ).toEqual({ valid: true }); }); - // Issue #677: CUSTOM strategy is now supported - it('accepts CUSTOM strategy', () => { + // AC23: CUSTOM strategy is not supported (Issue #235) + it('rejects CUSTOM strategy', () => { const result = validateAddMemoryOptions({ ...validMemoryOptions, strategies: 'CUSTOM' }); - expect(result.valid).toBe(true); + expect(result.valid).toBe(false); + expect(result.error).toContain('Invalid strategy: CUSTOM'); }); - it('accepts CUSTOM mixed with other strategies', () => { + it('rejects CUSTOM even when mixed with valid strategies', () => { const result = validateAddMemoryOptions({ ...validMemoryOptions, strategies: 'SEMANTIC,CUSTOM' }); - expect(result.valid).toBe(true); + expect(result.valid).toBe(false); + expect(result.error).toContain('Invalid strategy: CUSTOM'); }); // AC24: Each individual valid strategy should pass diff --git a/src/cli/commands/add/validate.ts b/src/cli/commands/add/validate.ts index 1390ba56..44a01016 100644 --- a/src/cli/commands/add/validate.ts +++ b/src/cli/commands/add/validate.ts @@ -4,7 +4,6 @@ import { BuildTypeSchema, GatewayExceptionLevelSchema, GatewayNameSchema, - MemoryStrategyTypeSchema, ModelProviderSchema, ProtocolModeSchema, RuntimeAuthorizerTypeSchema, @@ -34,8 +33,8 @@ export interface ValidationResult { } // Constants -const MEMORY_OPTIONS = ['none', 'shortTerm', 'longAndShortTerm', 'custom'] as const; -const VALID_STRATEGIES: readonly string[] = MemoryStrategyTypeSchema.options; +const MEMORY_OPTIONS = ['none', 'shortTerm', 'longAndShortTerm'] as const; +const VALID_STRATEGIES = ['SEMANTIC', 'SUMMARIZATION', 'USER_PREFERENCE', 'EPISODIC']; /** * Validate that a credential name exists in the project spec. @@ -135,7 +134,7 @@ export function validateAddAgentOptions(options: AddAgentOptions): ValidationRes if (!MEMORY_OPTIONS.includes(options.memory as (typeof MEMORY_OPTIONS)[number])) { return { valid: false, - error: `Invalid memory option: ${options.memory}. Use none, shortTerm, longAndShortTerm, or custom`, + error: `Invalid memory option: ${options.memory}. Use none, shortTerm, or longAndShortTerm`, }; } // Parse and validate lifecycle configuration for import path @@ -243,7 +242,7 @@ export function validateAddAgentOptions(options: AddAgentOptions): ValidationRes if (!MEMORY_OPTIONS.includes(options.memory as (typeof MEMORY_OPTIONS)[number])) { return { valid: false, - error: `Invalid memory option: ${options.memory}. Use none, shortTerm, longAndShortTerm, or custom`, + error: `Invalid memory option: ${options.memory}. Use none, shortTerm, or longAndShortTerm`, }; } } diff --git a/src/cli/commands/create/action.ts b/src/cli/commands/create/action.ts index 173856c5..b1d17f47 100644 --- a/src/cli/commands/create/action.ts +++ b/src/cli/commands/create/action.ts @@ -102,7 +102,7 @@ export async function createProject(options: CreateProjectOptions): Promise { framework: options.framework as SDKFramework | undefined, modelProvider: options.modelProvider as ModelProvider | undefined, apiKey: options.apiKey, - memory: (options.memory as 'none' | 'shortTerm' | 'longAndShortTerm' | 'custom') ?? 'none', + memory: (options.memory as 'none' | 'shortTerm' | 'longAndShortTerm') ?? 'none', protocol: options.protocol as ProtocolMode | undefined, agentId: options.agentId, agentAliasId: options.agentAliasId, @@ -170,7 +170,7 @@ export const registerCreate = (program: Command) => { ) .option('--model-provider ', 'Model provider (Bedrock, Anthropic, OpenAI, Gemini) [non-interactive]') .option('--api-key ', 'API key for non-Bedrock providers [non-interactive]') - .option('--memory