Persistent Memory for NemoClaw: Installed Is Not Connected
Install the memory plugin inside a NemoClaw sandbox and every step of the setup reports success. The plugin installs. The key is configured. The gateway restarts. Then you ask the agent what the project decided last week and it has nothing, because the request that would have fetched the answer never left the sandbox.
NemoClaw runs the OpenClaw agent in an OpenShell sandbox that denies outbound traffic by default. Nothing on the network is reachable until its destination is named in the policy. The npm registry already has a place in the default policy, which is why the install completes. api.memoryrouter.ai does not, which is why the memory call gets dropped one layer later.
Installed is not connected. That is what deny-by-default means in practice, and it is the first thing a review has to name.
Install and runtime are two different permissions
A package manager finishing cleanly tells you nothing about what a runtime is allowed to reach. The install and the plugin's memory calls are separate decisions against the policy, because they target separate destinations, and the default policy only covers the first one. The sandbox drops those calls, and from inside the plugin everything still looks healthy.
The fix is not to open the network. It is to name one destination and keep everything else denied. Both the NemoClaw page and the NemoClaw docs page start from that position.
What the setup command writes into the policy
One block, merged into network_policies:
network_policies:
memoryrouter:
name: memoryrouter
endpoints:
- host: api.memoryrouter.ai
port: 443
protocol: rest
tls: terminate
enforcement: enforce
rules:
- allow: { method: GET, path: /** }
- allow: { method: POST, path: /** }
binaries:
- path: /usr/local/bin/openclaw
- path: /usr/local/bin/node
One host on port 443, GET and POST only, and the rule applies to two named binaries, OpenClaw and Node, rather than the sandbox as a whole. No wildcards.
The write path is worth understanding before you run it. openshell policy set swaps the whole policy document rather than patching a section of it, so it reads what you run today, merges the MemoryRouter block into that copy, and applies the combined result. Existing rules survive the write. If you would rather merge it yourself, export the current policy before editing, and follow the manual setup steps.
Run it as a review, not a routine install
Preview the change before it lands:
npx @memoryrouter/nemoclaw setup \
--sandbox my-assistant \
--api-key <your-memory-key> \
--dry-run
Read the proposed diff against the policy you are actually running. Confirm the endpoint is api.memoryrouter.ai:443 and not a wildcard. Confirm the binary paths match your deployment. Then drop --dry-run and let it apply, which also restarts the gateway. Run it twice and nothing duplicates: the second run recognizes the existing block and skips the merge.
Prove recall from a new conversation
A clean setup log proves that the plugin and the policy are in place. It does not prove that storage or recall work. Run the check that ends in a different conversation:
- In a conversation, ask the agent to remember a fact you invented, for example: "the demo passphrase for this vault is CORVID-8823."
- Let the exchange finish, then open a second conversation that does not resume the first. Ask for the demo passphrase without including it in the question.
- The phrase coming back is the pass. If nothing comes back, ask for an explicit MemoryRouter search, and if that stays empty, check the egress block before changing anything else.
From that point on, the plugin recalls relevant memories as each turn starts and stores the conversation when the turn ends. The calls leave through the one permitted endpoint and nothing else.
What crosses the boundary, and what does not
A review should get both directions.
What leaves: the plugin stores direct user and assistant conversation to a hosted memory service and fetches relevant memories before turns. Tool calls, subagent sessions, and internal processing are not captured. If your conversations cannot leave the network at all, this is not the integration for that deployment, and the docs say so in the prerequisites.
What stays: your model provider remains where it is. Provider credentials and inference calls do not pass through MemoryRouter. Every destination other than the one endpoint stays denied by default.
When the sandbox gets rebuilt
Inside the sandbox, the only writable locations are /tmp and /sandbox/.openclaw-data, which is why a local vector store does not survive a rebuild and why the memory lives outside the sandbox. Sandbox restarts, onboard cycles, and compaction do not take the stored memories with them.
What the vault holds is conversation memory, not a copy of the workspace; the sandbox's own storage keeps its own lifecycle.
Two conditions ride along with the persistence story. After a rebuild, recall returns once the key, the plugin, and the policy rule are in place again. And the egress rule binds to specific binary paths, so when a major NemoClaw upgrade moves those paths, the rule stops matching anything. Re-run the setup after major upgrades and confirm the block still lines up with your binaries.
The way out
openclaw mr off stops capturing without deleting anything. openclaw mr delete removes the stored memories. Remove the egress block and the sandbox returns to its original posture. A read-only key can fetch memories and can never capture new ones, which makes it the safe way to hand someone inspection access before anyone writes.
When the diff is one endpoint wide and a fresh session reads back a phrase it was never given, the change has passed the review. Create your MemoryRouter account and prove one synthetic fact on your own sandbox.