Skip to content

fix(multi-agent): hide agent-runtime: from default mem_search#457

Merged
memtomem merged 2 commits intomainfrom
fix/multi-agent-default-isolation
Apr 24, 2026
Merged

fix(multi-agent): hide agent-runtime: from default mem_search#457
memtomem merged 2 commits intomainfrom
fix/multi-agent-default-isolation

Conversation

@memtomem
Copy link
Copy Markdown
Owner

Summary

search.system_namespace_prefixes default was ["archive:"] only, so
agent A's private chunks (created by mem_agent_register /
mem_agent_search) leaked into agent B's mem_search(namespace=None)
results — directly contradicting the namespace-based isolation
guarantee documented on the multi-agent guide.

This PR extends the default to ["archive:", "agent-runtime:"] and
consolidates the literal in a new memtomem.constants module so config,
MCP tools, and CLI all derive the prefix from one source.

  • New packages/memtomem/src/memtomem/constants.py exports
    AGENT_NAMESPACE_PREFIX, SHARED_NAMESPACE, and
    default_system_prefixes(). multi_agent.py, agent_cmd.py, and
    config.py derive from these symbols.
  • mem_agent_search is unaffected — it builds an explicit namespace
    filter (agent-runtime:<id>,shared) so it bypasses the system prefix
    exclusion entirely.
  • The hidden count surfaces through the existing hidden_system_ns
    hint, so users still see "N hidden — pass namespace=… to include
    them" when relevant.

Behavior change

Callers relying on plain mem_search to read agent-runtime:* chunks
must now either:

  1. Pin namespace="agent-runtime:<id>" on the call, or
  2. Override search.system_namespace_prefixes: [] in config.json
    (or omit agent-runtime: while keeping archive:), or
  3. Use mem_agent_search (recommended).

Documented under [Unreleased] / Changed in CHANGELOG.md.

Threat model

agent-runtime:<id> is a convenience isolation boundary, not a
security boundary. Direct storage access (raw namespace=, ingest
--namespace, list_namespaces, direct SQL) still reaches private
chunks. This PR closes the default-search UX leak only — proper
multi-tenant ACL/auth boundary is tracked as a separate follow-up.

Test plan

  • uv run pytest packages/memtomem/tests/test_multi_agent.py -v
    16 tests pass (10 sanitize + 3 default-isolation pin + 3 pipeline
    end-to-end).
  • uv run pytest -m "not ollama" — 2335 passed, 46 deselected,
    no regression in test_trust_ux, test_init_cmd,
    test_config_overrides, test_agent_cmd, test_server_tools_org.
  • uv run ruff check packages/memtomem/src + ruff format --check
    — clean.
  • uv run mypy on touched files — no new issues.

🤖 Generated with Claude Code

pandas-studio and others added 2 commits April 25, 2026 00:28
`search.system_namespace_prefixes` default was `["archive:"]` only, so
agent A's private chunks (created by `mem_agent_register` /
`mem_agent_search`) leaked into agent B's `mem_search(namespace=None)`
results — directly contradicting the namespace-based isolation
guarantee documented on the multi-agent guide.

Extends the default to `["archive:", "agent-runtime:"]` and consolidates
the literal in a new `memtomem.constants` module so config, MCP tools,
and CLI all derive the prefix from one source. `mem_agent_search` is
unaffected because it builds an explicit namespace filter; the hidden
count surfaces through the existing `hidden_system_ns` hint.

Behavior change: callers relying on plain `mem_search` to read
`agent-runtime:*` chunks must now either pin `namespace=` or override
`search.system_namespace_prefixes: []` in `config.json`. Documented
under [Unreleased] / Changed.

Threat model: `agent-runtime:<id>` is a *convenience* isolation
boundary, not a security boundary. Direct storage access (raw
`namespace=`, ingest `--namespace`, list_namespaces) still reaches
private chunks; this PR closes the default-search UX leak only.

Test surface (test_multi_agent.py):
- `TestDefaultIsolation` pins constants, default factory freshness,
  and `Mem2MemConfig` default — derives from the constant per
  `feedback_pin_test_constant_over_source_scan`.
- `TestAgentRuntimeIsolationPipeline` end-to-end: `agent-runtime:planner`
  chunks excluded from `namespace=None` search but reachable via
  pinned `namespace=`; `shared` namespace stays surfaceable.

Co-Authored-By: Claude <[email protected]>
Addresses three nits from the PR #457 review:

1. Drop the unused CLAUDE_/GEMINI_/CODEX_MEMORY_NAMESPACE_PREFIX exports
   from `constants.py`. Promoting them while `cli/ingest_cmd.py` still
   hardcodes the literals would have created a *new* parallel-literal
   seam — exactly what `feedback_drift_close_must_derive` warns against.
   Wiring the ingest CLI is a separate change, not this PR's scope.

2. Drop the `_AGENT_NAMESPACE_PREFIX = AGENT_NAMESPACE_PREFIX` re-export
   alias in `multi_agent.py`. The "Re-export for callers that previously
   imported the local-private symbol" comment was misleading —
   underscore-private symbols have no external callers by definition,
   and grep confirms zero in-repo references on this branch. Stacked
   PRs (#459 / #461) that import the underscore-private symbol get
   updated when they rebase onto this PR; the public
   `AGENT_NAMESPACE_PREFIX` is the right import target.

3. Update the comment above `config.search.system_namespace_prefixes =
   ["archive:"]` in `test_trust_ux.py:68`. After this PR's default flip
   the override is *narrowing* (default has both `archive:` and
   `agent-runtime:`), not "spelling out" — the new comment says so and
   notes that multi-agent isolation has its own coverage in
   `test_multi_agent`.

No behavior change. 2335 tests still pass.

Co-Authored-By: Claude <[email protected]>
@memtomem memtomem merged commit 035a70d into main Apr 24, 2026
7 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 24, 2026
@memtomem memtomem deleted the fix/multi-agent-default-isolation branch April 27, 2026 14:56
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants