Skip to content

feat(memory): add CUSTOM strategy type to agentcore-cli (#677) - #694

Merged
notgitika merged 6 commits into
aws:mainfrom
aidandaly24:feat/custom-memory-strategy
Mar 27, 2026
Merged

feat(memory): add CUSTOM strategy type to agentcore-cli (#677)#694
notgitika merged 6 commits into
aws:mainfrom
aidandaly24:feat/custom-memory-strategy

Conversation

@aidandaly24

@aidandaly24 aidandaly24 commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Description

Adds CUSTOM as a 5th memory strategy type across schema, CLI, TUI, docs, and tests. This enables users to configure self-managed memory strategies with user-controlled extraction logic, closing the gap between the CDK (which already supported CUSTOM) and the CLI.

Closes #677

Changes

  • Added CUSTOM to MemoryStrategyTypeSchema Zod enum (single source of truth)
  • Added CUSTOM description to TUI strategy selection screen
  • Added 'custom' as a new MemoryOption in the project create wizard
  • Updated CLI validation and help text to derive from schema (eliminates source-of-truth drift)
  • CUSTOM intentionally has no default namespaces in DEFAULT_STRATEGY_NAMESPACES (uses Partial<Record> for type safety)
  • Added CUSTOM block to session.py Handlebars templates (HTTP and MCP)
  • Wired mapExistingMemoriesToProviders for dedup when adding agents to projects with existing memories
  • Updated docs (memory.md, commands.md, configuration.md) and AGENTS.md
  • Fixed pre-existing gap: added EPISODIC strategy row to docs/configuration.md
  • Updated snapshot tests for asset changes
  • Added comprehensive unit tests (18 new tests in schema-mapper.test.ts)

TUI Screenshots

Screenshots of the add memory TUI flow showing all 5 strategies (SVG format):

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Other (please describe):

Testing

How have you tested the change?

  • I ran npm run test:unit and npm run test:integ
  • I ran npm run typecheck
  • I ran npm run lint
  • If I modified src/assets/, I ran npm run test:update-snapshots and committed the updated snapshots

Test results:

  • 3088/3090 unit tests pass (2 pre-existing PTY failures unrelated to this PR)
  • 61 schema-mapper tests pass (18 new: CUSTOM mapping, existingMemories dedup, render config wiring)
  • 110/110 validation tests pass (CUSTOM standalone, combined with other strategies)
  • 9/9 add-memory integration tests pass (CUSTOM strategy creation via CLI)
  • TUI harness verified: all 5 strategy options displayed with correct CUSTOM description

New test coverage includes:

  • mapGenerateInputToMemories('custom') — single CUSTOM strategy, no namespaces/reflectionNamespaces
  • mapGenerateConfigToResources with memory: 'custom'
  • mapExistingMemoriesToProviders — CUSTOM strategy, empty strategies, multiple memories
  • mapGenerateConfigToRenderConfig with existingMemories — dedup logic, hasMemory from existing, combining existing + new custom memory

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
terms of your choice.

@aidandaly24
aidandaly24 requested a review from a team March 27, 2026 03:26
@github-actions github-actions Bot added the size/m PR size: M label Mar 27, 2026
@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Mar 27, 2026
Enable self-managed (CUSTOM) memory strategy in the CLI, aligning
with the CDK constructs which already support customMemoryStrategy
via CloudFormation.

Changes:
- Add CUSTOM to MemoryStrategyTypeSchema enum and validation
- Add CUSTOM description to TUI wizard strategy picker
- Update CLI help text, LLM-compacted types, and AGENTS.md
- Add documentation for self-managed strategy in docs/
- Update tests: flip rejection tests to acceptance, add new cases
- Regenerate asset snapshots

Constraint: CDK already maps CUSTOM → customMemoryStrategy in CFN
Rejected: New SELF_MANAGED type | cross-layer naming inconsistency with CDK
Confidence: high
Scope-risk: narrow
Eliminates source-of-truth drift by deriving the valid strategies
array and CLI help text from MemoryStrategyTypeSchema.options
instead of maintaining hand-written duplicates.

Constraint: MemoryStrategyTypeSchema is the single source of truth
Confidence: high
Scope-risk: narrow
Without this, selecting CUSTOM as the only strategy would render
an empty retrieval_config dict with no guidance. Now both HTTP and
A2A Strands templates include a CUSTOM Handlebars block with a
TODO comment guiding users to add their own namespace and
retrieval config.

Constraint: CUSTOM is self-managed — no default namespaces to vend
Rejected: Auto-generating a placeholder namespace | would mislead users into thinking it works out of the box
Confidence: high
Scope-risk: narrow
…ories to new agents

Add 'custom' as a 4th MemoryOption in the create/add-agent wizards,
completing CUSTOM strategy support across all CLI flows. When adding
an agent to a project with existing memories, the template now
references all existing memories instead of always creating new ones.

- Add 'custom' to MemoryOption type, MEMORY_OPTIONS array, and all
  validation/help text across create and add-agent commands
- Add 'custom' case to mapGenerateInputToMemories (CUSTOM strategy,
  no default namespaces) and getMemoryLabel in wizard UI
- Add mapExistingMemoriesToProviders() to convert project Memory[]
  to MemoryProviderRenderConfig[] for template rendering
- Update mapGenerateConfigToRenderConfig to accept existing memories
  and merge them with new memory providers (deduped by name)
- Update writeAgentToProject to skip adding duplicate memories
- Wire existing project.memories through both add-agent paths
  (AgentPrimitive CLI + useAddAgent TUI hook)

Constraint: Strands Agent takes a single session_manager, so session.py
  references memoryProviders[0] as the primary memory
Rejected: Multi-select wizard for memory | template only supports one
  session_manager, all memory env vars already available at runtime
Confidence: high
Scope-risk: moderate
Add 18 new tests to schema-mapper.test.ts covering:
- mapGenerateInputToMemories with 'custom' MemoryOption
- mapGenerateConfigToResources with custom memory
- mapGenerateConfigToRenderConfig with existingMemories parameter
  (dedup logic, hasMemory from existing, combining existing + new)
- mapExistingMemoriesToProviders (CUSTOM, empty strategies, multiple)

Also fix docs/configuration.md missing EPISODIC strategy row.

Constraint: CUSTOM strategy has no default namespaces or reflectionNamespaces
Constraint: Dedup operates on provider name, not strategy type
Confidence: high
Scope-risk: narrow
@aidandaly24
aidandaly24 force-pushed the feat/custom-memory-strategy branch from 59f7804 to 7dc39dc Compare March 27, 2026 04:46
@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Mar 27, 2026
@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Mar 27, 2026
@aidandaly24
aidandaly24 force-pushed the feat/custom-memory-strategy branch from 712f37f to 7dc39dc Compare March 27, 2026 17:16
@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Mar 27, 2026
notgitika
notgitika previously approved these changes Mar 27, 2026

@notgitika notgitika left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For follow up, unrelated to this PR but a preexisting pattern:
MemoryOption type is defined in two places
MemoryOption is defined in both:

  • src/cli/commands/create/action.ts:123 — type MemoryOption = 'none' | 'shortTerm' | 'longAndShortTerm' | 'custom'
  • src/cli/tui/screens/generate/types.ts:51 — same definition

The schema-mapper imports from types.ts. The action.ts definition is a separate copy. If one gets updated and the other doesn't, they'll drift. Consider exporting from one location.


MEMORY_OPTIONS array is defined in 3 places

MEMORY_OPTIONS as ['none', 'shortTerm', 'longAndShortTerm', 'custom'] as const appears in:

  • src/cli/commands/add/validate.ts:37
  • src/cli/commands/create/validate.ts:24
  • src/cli/tui/screens/generate/types.ts:155 (as object array)

@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Mar 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Package Tarball

aws-agentcore-0.3.0-preview.9.0.tgz

How to install

npm install https://github.com/aws/agentcore-cli/releases/download/pr-694-tarball/aws-agentcore-0.3.0-preview.9.0.tgz

@notgitika
notgitika self-requested a review March 27, 2026 17:26

@notgitika notgitika left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@notgitika
notgitika merged commit beac707 into aws:main Mar 27, 2026
18 checks passed
aidandaly24 added a commit that referenced this pull request Mar 27, 2026
aidandaly24 added a commit that referenced this pull request Mar 27, 2026
aidandaly24 added a commit that referenced this pull request Mar 27, 2026
* Revert "feat: add semanticOverride support for SEMANTIC memory strategies (#678) (#696)"

This reverts commit 5e0f584.

* Revert "feat(memory): add CUSTOM strategy type to agentcore-cli (#677) (#694)"

This reverts commit beac707.

* fix: restore EPISODIC strategy to configuration.md

The revert of the CUSTOM strategy commit inadvertently removed the
EPISODIC row from the Memory Strategies table in configuration.md.
notgitika added a commit to notgitika/agentcore-cli that referenced this pull request Aug 18, 2026
Reverts 87be86e. I added CUSTOM because the CDK schema already had it in
MemoryStrategyTypeSchema, which turns out to be the argument PR aws#694 made --
and aws#713 reverted a day later.

The CLI has removed CUSTOM twice on purpose. Offering the type without
somewhere to put its extraction configuration is aws#241 ("select custom memory
strategy, note there is no option to add prompts"); aws#266 removed it as a P0 to
stop users picking an unsupported option, aws#694/aws#696 added it back with
semanticOverride, and aws#713 reverted both as premature. aws#676 tracks doing it
properly. The CDK keeping CUSTOM in its enum without a configuration field is
the same hole, not a licence.

So both forms are rejected again, now with an error that says why and points
at aws#676. The one thing kept from the reverted commit: memory validation errors
name the offending field, since issue.path was being dropped.
notgitika added a commit to notgitika/agentcore-cli that referenced this pull request Aug 19, 2026
Reverts 87be86e. I added CUSTOM because the CDK schema already had it in
MemoryStrategyTypeSchema, which turns out to be the argument PR aws#694 made --
and aws#713 reverted a day later.

The CLI has removed CUSTOM twice on purpose. Offering the type without
somewhere to put its extraction configuration is aws#241 ("select custom memory
strategy, note there is no option to add prompts"); aws#266 removed it as a P0 to
stop users picking an unsupported option, aws#694/aws#696 added it back with
semanticOverride, and aws#713 reverted both as premature. aws#676 tracks doing it
properly. The CDK keeping CUSTOM in its enum without a configuration field is
the same hole, not a licence.

So both forms are rejected again, now with an error that says why and points
at aws#676. The one thing kept from the reverted commit: memory validation errors
name the offending field, since issue.path was being dropped.
notgitika added a commit to notgitika/agentcore-cli that referenced this pull request Aug 20, 2026
Reverts 87be86e. I added CUSTOM because the CDK schema already had it in
MemoryStrategyTypeSchema, which turns out to be the argument PR aws#694 made --
and aws#713 reverted a day later.

The CLI has removed CUSTOM twice on purpose. Offering the type without
somewhere to put its extraction configuration is aws#241 ("select custom memory
strategy, note there is no option to add prompts"); aws#266 removed it as a P0 to
stop users picking an unsupported option, aws#694/aws#696 added it back with
semanticOverride, and aws#713 reverted both as premature. aws#676 tracks doing it
properly. The CDK keeping CUSTOM in its enum without a configuration field is
the same hole, not a licence.

So both forms are rejected again, now with an error that says why and points
at aws#676. The one thing kept from the reverted commit: memory validation errors
name the offending field, since issue.path was being dropped.
notgitika added a commit to notgitika/agentcore-cli that referenced this pull request Aug 21, 2026
Reverts 87be86e. I added CUSTOM because the CDK schema already had it in
MemoryStrategyTypeSchema, which turns out to be the argument PR aws#694 made --
and aws#713 reverted a day later.

The CLI has removed CUSTOM twice on purpose. Offering the type without
somewhere to put its extraction configuration is aws#241 ("select custom memory
strategy, note there is no option to add prompts"); aws#266 removed it as a P0 to
stop users picking an unsupported option, aws#694/aws#696 added it back with
semanticOverride, and aws#713 reverted both as premature. aws#676 tracks doing it
properly. The CDK keeping CUSTOM in its enum without a configuration field is
the same hole, not a licence.

So both forms are rejected again, now with an error that says why and points
at aws#676. The one thing kept from the reverted commit: memory validation errors
name the offending field, since issue.path was being dropped.
notgitika added a commit to notgitika/agentcore-cli that referenced this pull request Aug 21, 2026
Reverts 87be86e. I added CUSTOM because the CDK schema already had it in
MemoryStrategyTypeSchema, which turns out to be the argument PR aws#694 made --
and aws#713 reverted a day later.

The CLI has removed CUSTOM twice on purpose. Offering the type without
somewhere to put its extraction configuration is aws#241 ("select custom memory
strategy, note there is no option to add prompts"); aws#266 removed it as a P0 to
stop users picking an unsupported option, aws#694/aws#696 added it back with
semanticOverride, and aws#713 reverted both as premature. aws#676 tracks doing it
properly. The CDK keeping CUSTOM in its enum without a configuration field is
the same hole, not a licence.

So both forms are rejected again, now with an error that says why and points
at aws#676. The one thing kept from the reverted commit: memory validation errors
name the offending field, since issue.path was being dropped.
jariy17 pushed a commit that referenced this pull request Aug 24, 2026
* feat(project): add `project add memory`

Registers a `memory` leaf under `project add`, following the same
SDK-union -> flat project-schema conversion pattern as `project add
harness`. A memory scaffolds no files, so the command only appends an
entry to `spec.memories` in agentcore.json; the L3 CDK turns that into
an `AWS::BedrockAgentCore::Memory` at deploy time.

Flags: --name, --event-expiry-duration, --strategies, --indexed-keys,
--stream-delivery-resources, --encryption-key-arn, --execution-role-arn,
--tags.

--strategies accepts two forms: a comma-separated list of strategy types
expanded with the CLI's default namespace templates, or a JSON
MemoryStrategyInput[] mirroring the CreateMemory API for strategies that
need explicit names, descriptions, or namespaces.

clientToken is excluded (it is CreateMemory idempotency and this command
makes no API call), and description is excluded until the L3 CDK schema
supports it.

* feat: add --description to 'project add memory'

Stores an optional memory description in agentcore.json, matching the
CreateMemory API's description field (max 4096 characters).

The generated CDK app pins @aws/agentcore-cdk 0.1.0-alpha.45, whose
MemorySchema is a non-strict z.object with no description field, so the key
is stripped at synth rather than rejected until
aws/agentcore-l3-cdk-constructs#325 ships and that pin is bumped. The flag
help text says so.

* feat: accept a CUSTOM memory strategy in 'project add memory'

The CDK's memory schema already models CUSTOM (@aws/agentcore-cdk
0.1.0-alpha.45 maps it to CFN customMemoryStrategy), so the CLI's four-type
enum was the outlier. A customMemoryStrategy in the --strategies JSON now
converts to { type: 'CUSTOM', name, description, namespaceTemplates }.

The shorthand form still takes managed types only: CUSTOM has no default
namespaces to expand. An extraction configuration or memoryRecordSchema is
rejected rather than dropped, since the CDK schema carries neither.

Also names the offending field in the memory validation error.

* revert: drop CUSTOM memory strategy from "project add memory"

Reverts 87be86e. I added CUSTOM because the CDK schema already had it in
MemoryStrategyTypeSchema, which turns out to be the argument PR #694 made --
and #713 reverted a day later.

The CLI has removed CUSTOM twice on purpose. Offering the type without
somewhere to put its extraction configuration is #241 ("select custom memory
strategy, note there is no option to add prompts"); #266 removed it as a P0 to
stop users picking an unsupported option, #694/#696 added it back with
semanticOverride, and #713 reverted both as premature. #676 tracks doing it
properly. The CDK keeping CUSTOM in its enum without a configuration field is
the same hole, not a licence.

So both forms are rejected again, now with an error that says why and points
at #676. The one thing kept from the reverted commit: memory validation errors
name the offending field, since issue.path was being dropped.

* refactor: drop the long-form help for --description

The one-line flag description is enough; the deploy-time caveat lives in the
PR discussion rather than in help output.

* docs: comment change

* fix: change function name and add comment for clarity

* test: add uncovered unsupported stream content type test

* style: make json example concrete, remove comments

* refactor(project): reuse shared spec validation for memory

* fix(project): validate memory JSON inputs

* fix(project): harden memory input validation

* test(project): colocate memory tests with the add/memory handler

Upstream moved the per-resource `project add` tests out of the monolithic
project.test.ts into colocated add/<resource>/index.test.ts suites (harness
in #2034, online-eval in #2048). Move the memory tests to match, with the
same locally-duplicated run/inProject helpers those suites use.

project.test.ts is now identical to upstream/refactor again, so this PR no
longer touches it. Also drops the DeserializationError, FsReadWriteJson and
ReadWriteJson imports, left dead there once the harness tests that used them
moved to add/harness/index.test.ts.

No test content changed: 187 project tests still pass, now across 10 files
instead of 9.

* refactor(project): match --strategies JSON to the agentcore.json schema

The --strategies flag re-declared its own strategy input schema, modelled
on the CreateMemory API's tagged union (semanticMemoryStrategy et al.) and
requiring a name. agentcore.json stores strategies flat with an optional
name, so the flag accepted a shape the project file never holds and
rejected one it does.

Parse the JSON form with MemoryStrategySchema itself, wrapped only for the
unsupported-field diagnostics, so the flag cannot drift from the schema.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Self-managed strategy in memory not yet supported

2 participants