Migrate a Python application to NAMS
To change an existing Bolt application to NAMS, inventory its operations and data assumptions, replace unsupported paths, then verify the application against a separate workspace.
Prerequisites
-
An application with a passing Bolt baseline and identified memory reads/writes.
-
Python 3.10+ with
neo4j-agent-memory[nams]==0.7.0; follow the installation and connection check in Connect a Python application to NAMS. -
A NAMS sandbox workspace key and a synthetic test dataset. Use a separate workspace for migration tests.
-
A data-migration decision. Keep the source database until any separately planned import and rollback procedure has been verified.
1. Inventory operations before changing configuration
Use the capability matrix as the canonical inventory. Search application code for graph writes, preferences/facts, user registry calls, buffering, consolidation, geospatial queries, schema setup and legacy reasoning traces.
| Existing behavior | Migration action |
|---|---|
Raw read Cypher |
Use |
Raw write Cypher or |
Retain the operation on Bolt or redesign around supported service writes. NAMS has no direct client-created relationship equivalent. |
Preference/fact CRUD |
Retain Bolt or deliberately redesign application storage. A message containing a preference is not a drop-in replacement for preference records. |
|
Keep application identity/authorization explicit. Check which methods accept and forward user metadata; it is not universal isolation. |
Buffering, schema adoption, geocoding or client consolidation |
Keep the relevant pipeline on Bolt or replace it with an explicitly supported service/application operation. Do not assume an unavailable operation runs automatically on the server. |
Legacy reasoning traces |
Verify the hosted step representation. Synthetic trace IDs/task/outcome state are not durable equivalents; see reasoning reference. |
If an essential behavior has no supported replacement, finish that design before switching the application.
2. Configure a sandbox connection
Follow Connect a Python application to NAMS and run its message write/readback check. Use explicit NamsSettings for migration code so an unrelated environment variable cannot silently select a different backend.
For applications retaining MemoryClient, the equivalent explicit settings are:
import os
from pydantic import SecretStr
from neo4j_agent_memory import MemoryClient, MemorySettings, NamsConfig
settings = MemorySettings(
backend="nams",
nams=NamsConfig(api_key=SecretStr(os.environ["MEMORY_API_KEY"])),
)
client = MemoryClient(settings)
Connect and close this client through its async context manager or application lifecycle.
3. Adapt identifiers, results and readiness
-
Persist the ID returned by
create_conversation; do not continue using its display name as the message session ID. -
Handle entity creation correctly: Bolt returns
(Entity, DeduplicationResult), while NAMS returns anEntity. Keep backend-specific code explicit when the application needs merge details. -
After asynchronous ingestion, use a bounded extraction wait and verify the exact expected entity or session status.
-
Remove inactive client-side embedding/extraction/resolution settings from the NAMS configuration. Configure an LLM provider separately only for client-side summary or application model work.
-
Replace combined-context isolation assumptions with explicit retrieval and application authorization. Test a second conversation with different synthetic content.
4. Verify the ported application
Run the following checks in the sandbox and retain the returned IDs and failures:
-
Store a message and retrieve it by the returned conversation ID.
-
Start a fresh process and reopen that ID without reseeding its original content.
-
Store and read an entity through supported operations; if extraction is used, verify its bounded success and timeout paths.
-
Exercise the application’s model/tool failure path and inspect the recorded hosted steps/tool results.
-
Test authentication failures, rate limits and unsupported operations. Mock tests should reject unimplemented routes instead of silently returning success.
-
Confirm that content from another user/conversation is handled by the intended access policy; do not treat the presence of a
userIdfield as proof.
Only switch the application after these application-specific checks pass. The detailed supported operations and exceptions remain in backend capabilities and the Python API reference.
Limits and gotchas
-
Changing a backend setting does not transfer the existing Neo4j database; keep the source database until a separately planned import and rollback procedure has been verified.
-
This guide does not promise an unshipped removal version or a NAMS write-Cypher replacement.
-
A nonempty workspace search does not prove a given run’s extraction completed — verify the exact expected entity or session status instead.
-
A successful Bolt test suite is a baseline, not evidence of hosted equivalence.