Skip to content

fix(memory)!: rename LocalMemoryStore to TestMemoryStore#3123

Merged
opieter-aws merged 4 commits into
strands-agents:mainfrom
opieter-aws:opieter-aws/rename-localmemorystore-alias
Jul 9, 2026
Merged

fix(memory)!: rename LocalMemoryStore to TestMemoryStore#3123
opieter-aws merged 4 commits into
strands-agents:mainfrom
opieter-aws:opieter-aws/rename-localmemorystore-alias

Conversation

@opieter-aws

@opieter-aws opieter-aws commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Description

LocalMemoryStore was named for where it runs rather than what it is for. It's a zero-infrastructure, JSON-file-backed store meant for prototyping, offline use, and tests — not a production backend (each write rewrites the whole file; recall is lexical, not semantic). Renaming it to TestMemoryStore signals that intended role at the call site and reads more clearly next to the production-grade BedrockKnowledgeBaseStore.

LocalMemoryStore shipped only in the most recent release, so rather than carry a deprecation shim we make this a clean breaking change: the old names and the old import path are removed outright, with no aliases. This keeps the surface honest — there's no deprecated subclass, no __getattr__ warning branch, and no lingering local path to migrate off later.

The rename is applied across both SDKs in lockstep for cross-SDK parity. The subsystem directory is also renamed localtest_memory_store (Python) / test-memory-store (TS) so the import path matches the class, mirroring the sibling bedrock_knowledge_base/ convention. The on-disk JSON format and all record field names are unchanged, so a file written by the previous release still loads.

Public API Changes (breaking)

Renamed symbols (both SDKs): LocalMemoryStoreTestMemoryStore, LocalMemoryStoreConfigTestMemoryStoreConfig, LocalMemoryAddResultTestMemoryAddResult. The import path changes with the directory rename. The old names and the old path are gone.

# Before
from strands.vended_memory_stores.local import LocalMemoryStore
store = LocalMemoryStore(name="notes")

# After
from strands.vended_memory_stores.test_memory_store import TestMemoryStore
store = TestMemoryStore(name="notes")

# Also re-exported from the parent package:
from strands.vended_memory_stores import TestMemoryStore
// Before
import { LocalMemoryStore } from '@strands-agents/sdk/vended-memory-stores/local'
const store = new LocalMemoryStore({ name: 'notes' })

// After
import { TestMemoryStore } from '@strands-agents/sdk/vended-memory-stores/test-memory-store'
const store = new TestMemoryStore({ name: 'notes' })

Breaking Changes

LocalMemoryStore / LocalMemoryStoreConfig / LocalMemoryAddResult and the .../vended-memory-stores/local import path no longer exist. Because the on-disk format is unchanged, only import sites and type/constructor references need updating — no data migration.

Migration

# Python — update the import path and the symbol names
- from strands.vended_memory_stores.local import LocalMemoryStore
+ from strands.vended_memory_stores.test_memory_store import TestMemoryStore
// TypeScript — update the subpath and the symbol names
- import { LocalMemoryStore } from '@strands-agents/sdk/vended-memory-stores/local'
+ import { TestMemoryStore } from '@strands-agents/sdk/vended-memory-stores/test-memory-store'

Implementation Note (reviewer callout)

Because the class name starts with Test, pytest's default collection would try to load TestMemoryStore (and its sibling types) as test suites. Each carries __test__ = False to opt out. For the TestMemoryStoreConfig TypedDict this is a post-class assignment with a scoped # type: ignore[attr-defined] — mypy strict rejects __test__ both in a TypedDict body ([misc]) and post-class ([attr-defined]), so the suppression is load-bearing and correctly scoped. A regression test asserts __test__ is False on all three definitions so a future edit can't silently re-enable collection.

Related Issues

Documentation PR

No documentation changes are needed: the store is documented via docstrings/TSDoc in the source, which are updated in this PR. The team/designs/0014-storage.md RFC references the old name in a few places; it is a point-in-time design doc and is intentionally left untouched to keep this change focused.

Type of Change

Breaking change

Testing

Ran the affected unit suites in both SDKs (hatch test tests/strands/vended_memory_stores/ and vitest run src/vended-memory-stores/test-memory-store/) plus lint/type checks on the changed files, and re-ran the Python suite with PytestCollectionWarning escalated to errors to confirm the Test* classes are never collected. Verified the breaking change end to end from a REPL script: the new name and path import silently, while both the old LocalMemoryStore name and the old .local import path now raise ImportError/ModuleNotFoundError.

  • I ran hatch run prepare

Checklist

  • I have read the CONTRIBUTING document
  • I have reviewed and understand every line of code in this PR, including any generated by AI tools, and I can explain why it works
  • My change is focused and reasonably small; I have split unrelated work into separate PRs
  • 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.

@github-actions github-actions Bot added size/m python Pull requests that update python code area-community Related to community and contributor health enhancement New feature or request labels Jul 8, 2026
@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@opieter-aws opieter-aws force-pushed the opieter-aws/rename-localmemorystore-alias branch from b57faa9 to 3bf8e27 Compare July 8, 2026 14:40
@opieter-aws opieter-aws marked this pull request as ready for review July 8, 2026 14:40
@opieter-aws opieter-aws requested a review from a team as a code owner July 8, 2026 14:40
@opieter-aws opieter-aws requested a review from mehtarac July 8, 2026 14:40
Comment thread strands-py/src/strands/vended_memory_stores/local/__init__.py Outdated
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Overall a clean, well-tested backwards-compatible rename. Two process/design points beyond the inline comments:

API review label: This changes a public API contract (renaming exported classes/types customers construct). Per team/API_BAR_RAISING.md, that warrants the api/needs-review label (a CI check gates merge on api/review-complete). The PR description already contains the required before/after usage, signatures, and exports, so a reviewer can evaluate it directly — please add the label to route it. Since the rename is motivated by a tenet ("name a construct for what it does"), it's a good candidate for a quick API-reviewer sign-off.

Naming vs. location (question, not blocking): The class is now JsonMemoryStore, but it still lives in the local/ subpackage and is imported from vended-memory-stores/local. The rename's own rationale (name for what it is, not where it runs) now only half-applies, since the import path still says local. I see this was an intentional backwards-compat tradeoff — worth a note in a follow-up about whether the subpath should eventually gain a json alias / be deprecated too, so the surface doesn't stay split long-term.

Comment thread strands-ts/src/vended-memory-stores/local/store.ts Outdated
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Assessment: Comment (approve once the deprecation-message and API-label items are addressed)

A clean, mechanical, and well-tested rename that preserves backwards compatibility correctly in both SDKs (Python identity via __getattr__, TS via a subclass that keeps instanceof). The main gaps are process/policy rather than correctness.

Review themes
  • Deprecation guidance: Warning messages omit the removal version and migration pointer that FEATURE_LIFECYCLE.md requires; the TS class @deprecated tag is also inconsistent with its sibling type aliases.
  • API process: A public-API contract rename should carry the api/needs-review label per API_BAR_RAISING.md.
  • Cross-SDK parity: The deprecation signal differs (Python warns once at import; TS warns on every construction) — worth aligning to avoid log spam.
  • Naming/location: The JsonMemoryStore class still lives under the local/ subpath — a lingering (intentional) inconsistency to track for follow-up.

Nicely scoped change with solid test coverage of the deprecation behavior on both sides.

@JackYPCOnline

Copy link
Copy Markdown
Contributor

Question: Using data format for naming makes me wondering that will we have more storages for other data format ?

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@JackYPCOnline raises a good API-design point that's worth resolving before this merges, since it goes to the naming axis rather than the mechanics of the rename.

There seem to be three candidate axes for naming this store:

  • LocationLocalMemoryStore (today; the PR rightly notes this names where it runs)
  • Serialization formatJsonMemoryStore (this PR)
  • Medium/backend — e.g. FileMemoryStore

The reason the format axis gives me pause: team/designs/0014-storage.md proposes a unified Storage primitive where a MemoryStore uses a pluggable Storage internally (LocalFileStorage, S3Storage, InMemoryStorage, community Redis/IndexedDB, …) rather than owning its persistence. That doc explicitly plans to "adapt LocalMemoryStore — optional storage field replaces raw fs", and its non-goals reference a separate FileMemoryStore design (PR #2895).

If that direction lands, JsonMemoryStore becomes slightly self-contradictory: the store would no longer be inherently tied to JSON-on-disk (it could be backed by S3, IndexedDB, etc.), and JSON is just the serialization the default file backend happens to use. So to answer the question directly — under the current roadmap I would not expect a family of format-named stores (YamlMemoryStore, CsvMemoryStore); the intended extensibility axis is the pluggable Storage backend, which argues for naming by medium (FileMemoryStore) over format (JsonMemoryStore).

This is exactly the kind of call that benefits from an api/needs-review sign-off (see my earlier comment). It'd be worth confirming with the storage-design owner that JsonMemoryStore doesn't collide with the FileMemoryStore/unified-Storage direction before we commit the public name — a second rename later would burn another deprecation cycle. Not necessarily a blocker, but I'd resolve the naming axis first.

@lizradway lizradway self-requested a review July 8, 2026 15:51
@opieter-aws

Copy link
Copy Markdown
Contributor Author

@JackYPCOnline thanks for your comment, it made me check the notes and I realized we'd actually decided to name this TestMemoryStore in the end, to make a stronger signal to devs to use this for testing only. Preparing new rev

@opieter-aws opieter-aws changed the title feat(memory): rename LocalMemoryStore to JsonMemoryStore feat(memory): rename LocalMemoryStore to TestMemoryStore Jul 8, 2026
@lizradway

lizradway commented Jul 8, 2026

Copy link
Copy Markdown
Member

Maybe i missed some conversation on this but:
Do you think we need to maintain the previous exports as well? This was just released today right? Could we just patch this?

@opieter-aws

Copy link
Copy Markdown
Contributor Author

This was just released today right

Just checked and you're right, it got released today only. I don't mind doing a breaking change in that case, @pgrayy wdyt?

Comment thread strands-ts/src/vended-memory-stores/test-memory-store/store.ts
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Re-reviewing after the pivot from JsonMemoryStoreTestMemoryStore. The mechanical execution is still clean, but the new name raises a bigger concern than the one it resolves, so flagging before this locks in.

Important — the Test prefix fights the ecosystem. Naming a shipped public class TestMemoryStore collides with test-framework collection conventions. The PR now has to carry __test__ = False on all three definitions, a scoped # type: ignore[attr-defined] for the TypedDict, and a dedicated regression test — all purely to stop pytest from treating the public API as test suites. When a name requires framework escape hatches to ship, that's usually a signal the name is working against the platform rather than with it. Two knock-on effects worth calling out:

  • The Test* prefix is a strong, near-universal signal for "this is a test case," not "a store you use in tests." So the name is arguably more ambiguous than JsonMemoryStore, and it reads oddly next to BedrockKnowledgeBaseStore.
  • It also still contradicts the 0014-storage.md direction (medium-based FileMemoryStore + pluggable Storage) I raised earlier — that tension didn't go away with this rename, it just moved.

If the goal is to signal "not for production," names that convey that without the framework collision might serve better — e.g. EphemeralMemoryStore, InMemory*, File*, or keeping Local*. Given how consequential and surprising Test* is, and that its provenance so far is "we decided this in the notes," I'd strongly encourage the api/needs-review label + a short decision record before committing the public name. A second rename later burns another deprecation cycle.

On dropping backwards-compat entirely (re: @lizradway / @opieter-aws): if it genuinely shipped only today with ~zero adoption, a clean breaking rename is reasonable and would delete a lot of surface — the __getattr__ aliases, the TS subclass, the deprecation-warning wording my earlier inline comments were about, and arguably the whole "warns once vs. per-construction" parity gap. Two caveats before you pull that trigger:

  • Confirm what the released version's stability contract is (stable vs. pre-release/experimental). Per team/FEATURE_LIFECYCLE.md, "released today" isn't automatically license for a silent breaking change if it went out under a stable guarantee — the tenet is community trust. If it's flagged experimental/pre-1.0, this is clearly fine.
  • Whatever you decide, make it symmetric across both SDKs so cross-SDK parity holds.

Net: I'd resolve the name (with an API reviewer) and the keep-vs-break question first — several of my earlier inline comments become moot depending on those two outcomes.

@opieter-aws opieter-aws changed the title feat(memory): rename LocalMemoryStore to TestMemoryStore fix!(memory): rename LocalMemoryStore to TestMemoryStore Jul 8, 2026
@opieter-aws opieter-aws changed the title fix!(memory): rename LocalMemoryStore to TestMemoryStore fix(memory)!: rename LocalMemoryStore to TestMemoryStore Jul 8, 2026
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Re-reviewed the pivot to a clean breaking change. The mechanics are solid:

  • Old local/ directory removed in both SDKs; renamed to test_memory_store / test-memory-store to match the bedrock_knowledge_base sibling convention.
  • TS package.json exports updated to the new subpath (old ./local gone); no dangling old-name/old-path references anywhere in source.
  • On-disk JSON format unchanged, so files from the prior release still load — nicely, the breaking surface is import-sites-only, and the Migration section documents exactly that.

Dropping the deprecation shims was the right call given ~one-release-old adoption, and it moots my earlier deprecation-message inline comments (those files/aliases no longer exist).

Two things I'd still like an explicit call on, now that @pgrayy is engaged — not blocking, but worth putting on record since a breaking rename is the expensive moment to get the name right:

  1. Test* naming still carries a real ecosystem cost. The name requires __test__ = False on all three definitions + a scoped # type: ignore + a regression test purely so pytest doesn't collect the public API as test suites, and Test* reads as "this is a test case" more than "a store for use in tests." Renaming the directory to test_memory_store doubles down on that framing. It's a legitimate design choice, but given it's now a breaking change with !, I'd want it explicitly blessed rather than carried in on notes.

  2. RFC conflict left open. team/designs/0014-storage.md still names LocalMemoryStore and plans to evolve this exact store toward a pluggable Storage / medium-based FileMemoryStore. Leaving the RFC untouched is fine for a point-in-time doc, but the shipped name now contradicts the documented future direction — worth a quick reconciliation with the RFC owner so we don't ship TestMemoryStore this week and FileMemoryStore next quarter.

Assessment: Comment — approve on the mechanics; the only open items are the naming/RFC calls above, which are a maintainer/API-review decision rather than a code issue.

@opieter-aws opieter-aws merged commit 6c58f97 into strands-agents:main Jul 9, 2026
44 checks passed
@opieter-aws opieter-aws deleted the opieter-aws/rename-localmemorystore-alias branch July 9, 2026 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-community Related to community and contributor health enhancement New feature or request python Pull requests that update python code size/m

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants