fix: validate agent_id at mem_agent_register / search and mm agent register (#493)#494
Conversation
…egister` (#493) PR #491 wired ``validate_agent_id`` into the three session-start surfaces (``mem_session_start``, ``mm session start``, ``mm session wrap``) so a hostile-shaped ``agent_id`` like ``"foo:bar"`` or ``"../x"`` is rejected loudly. The matching multi-agent registration / search surfaces still ran ``sanitize_namespace_segment``, so the same input produced two UX outcomes: registering an agent silently rewrote the id to ``agent-runtime:foo_bar``, while ``mem_session_start`` for that same id loudly rejected. The asymmetry was small while the multi-agent surface review was in flight, but it would have only gotten harder to reason about as more tools fan out. Switch ``mem_agent_register``, ``mem_agent_search``, and ``mm agent register`` to ``validate_agent_id``. The read / write contract is now symmetric — an id either works on every surface or fails on every surface, with the same ``invalid agent-id 'X'`` error fragment regardless of entry point. ``sanitize_namespace_segment`` itself stays as the permissive helper for the ingest pipeline (where filesystem / provider segments still need rewriting). CHANGELOG flags the breaking shape: callers that relied on silent sanitisation will now see a hard error. Those callers were already storing memories under unexpected namespaces so the fix is the forcing function to pick a canonical id. Tests: extends ``test_validate_agent_id.py`` with a ``TestMcpMultiAgentBoundary`` class (parametrised over the same hostile-id corpus as the session-start surfaces) and a ``TestCliAgentRegisterBoundary`` class for the CLI shape, plus a cross-surface parity assertion that all three multi-agent boundaries emit the same ``invalid agent-id 'foo:bar'`` core fragment. ``test_agent_cmd.py``'s empty-id assertion is updated for the new shared error vocabulary. Closes #493. Co-Authored-By: Claude <[email protected]>
PR #494 reviewer flagged: the docstring listed ``integrations.langgraph.MemtomemStore.start_agent_session`` as a site that validates, but the LangGraph wiring is not in this PR — it lives in the stacked-PR work for #492 (separate branch). Until #492 lands, this PR should not claim LangGraph validates. Move the LangGraph mention into a "Not yet applied at" paragraph, mirroring the structure on ``main`` pre-#493. Also replace the vague "see issue tracker history for the breaking-change note" with the concrete pointer (``CHANGELOG.md`` Unreleased entry + issue #493). No code change — pure docstring honesty fix. The stacked #492 PR will re-promote LangGraph to "Applied at" when it ships. Co-Authored-By: Claude <[email protected]>
|
Thanks — addressed the blocking review item: #1 (LangGraph overclaim) — fixed in 94e9422 You were right, the docstring as written claimed coverage this PR doesn't ship. Moved the LangGraph mention back under #2 (mem_agent_share target validation) — filed as #497
#3 (vague history pointer) — fixed in 94e9422 alongside #1. #4 (validate return value discarded) and #5 (test error string change polish) — leaving as-is per your "acceptable / optional" verdict; the cross-surface error vocabulary unification was the intentional outcome and the empty-id case is covered transitively by the BREAKING entry's "contains... whitespace" line. Ready for re-review when you have a minute. |
Summary
Closes #493.
PR #491 wired
validate_agent_idinto the three session-start surfaces(
mem_session_start/mm session start/mm session wrap) so ahostile-shaped
agent_idlike"foo:bar"or"../x"was rejectedloudly. The matching multi-agent registration / search surfaces
(
mem_agent_register,mem_agent_search,mm agent register) stillran
sanitize_namespace_segment, so the same input produced two UXoutcomes — registering an agent silently rewrote the id to
agent-runtime:foo_bar, whilemem_session_startfor that same idloudly rejected. This PR closes that asymmetry.
The read / write contract is now symmetric across the MCP + CLI
surfaces — an
agent_ideither works on every surface or fails onevery surface, with the same
invalid agent-id 'X'error fragmentregardless of entry point.
sanitize_namespace_segmentitself staysas the permissive helper for the ingest pipeline (where filesystem /
provider segments still need rewriting); only the multi-agent
surfaces stop calling it.
Breaking change
Callers that relied on silent sanitisation will now see a hard error.
Those callers were already storing memories under unexpected
namespaces (e.g.
agent-runtime:foo_barfromagent_id="foo:bar")so the change is the forcing function to pick a canonical id matching
[A-Za-z0-9._-]+. Flagged inCHANGELOG.mdunder[Unreleased] > Changed (BREAKING).What changed
packages/memtomem/src/memtomem/server/tools/multi_agent.py—mem_agent_registerandmem_agent_searchcallvalidate_agent_id(raises
InvalidNameError, surfaced asError: ...bytool_handler); drop the now-redundant non-empty / sanitised-emptybranches; drop the
sanitize_namespace_segmentimport.packages/memtomem/src/memtomem/cli/agent_cmd.py—mm agent registervalidates with the session-starttry/except InvalidNameError → ClickExceptionpattern.packages/memtomem/src/memtomem/constants.py—validate_agent_iddocstring lists every MCP + CLI surface that now validates, points
at
CHANGELOG.mdUnreleased + mem_agent_register / mem_agent_search: validate vs sanitize divergence #493 for the breaking-change note,and keeps the LangGraph adapter under "Not yet applied at" (tracked
in Apply validate_agent_id at LangGraph adapter agent-runtime concat sites #492 — out of scope here).
CHANGELOG.md—Unreleased > Changed (BREAKING)entry.Tests
packages/memtomem/tests/test_validate_agent_id.pyadds:TestMcpMultiAgentBoundary— parametrised over the existingHOSTILE_AGENT_IDScorpus (13 shapes); pins error string + thatagent-runtime:foo:barnever reacheslist_namespace_meta; validids still succeed;
agent_id=Noneformem_agent_searchisunaffected.
TestCliAgentRegisterBoundary—mm agent register foo:bar/../etcreject; storageset_namespace_metanever called on therejection path; valid id still succeeds.
test_session_and_multi_agent_surfaces_share_core_error_text—cross-surface parity pin: all three boundaries emit
invalid agent-id 'foo:bar'.packages/memtomem/tests/test_agent_cmd.py::test_register_rejects_empty_agent_idretargeted to the new shared error vocabulary (
invalid agent-id)packages/memtomem/tests/test_multi_agent.pydocstring corrected —the file now exercises the helper itself, not its (former) use by
the multi-agent tools.
Test plan
uv run ruff check packages/memtomem/src packages/memtomem/tests— cleanuv run ruff format --check packages/memtomem/src packages/memtomem/tests— cleanuv run pytest packages/memtomem/tests -m "not ollama"— 2589 passed, 46 deselecteduv run pytest packages/memtomem/tests/test_validate_agent_id.py— 70 passedOut of scope
MemtomemStore.start_agent_sessionandthe remaining agent-runtime concat sites — tracked in Apply validate_agent_id at LangGraph adapter agent-runtime concat sites #492 as a
separate follow-up (review feedback: this PR shouldn't claim
LangGraph validation it doesn't ship).
mem_agent_share(target=...)validation —targetis a fullnamespace string (not a bare
agent_id), sovalidate_agent_iddoesn't drop in directly. Currently a caller passing
target="agent-runtime:foo:bar"plumbs straight into_mem_add_core(namespace=target)and stores under exactly thehostile namespace this PR closes for register / search. Worth a
follow-up issue under the same mem_agent_register / mem_agent_search: validate vs sanitize divergence #493 banner — see review thread.
need until users ask for it (per mem_agent_register / mem_agent_search: validate vs sanitize divergence #493 acceptance).
Review fixups (post-#494 review)
94e9422— drop LangGraph claim fromvalidate_agent_iddocstring.The original PR docstring listed
integrations.langgraph.MemtomemStore.start_agent_sessionunder"Applied at", but the LangGraph wiring is not in this PR (it lives
in the stacked-PR work for Apply validate_agent_id at LangGraph adapter agent-runtime concat sites #492). Until Apply validate_agent_id at LangGraph adapter agent-runtime concat sites #492 lands this PR shouldn't
claim coverage it doesn't ship — the LangGraph mention is now under
"Not yet applied at" with a concrete pointer to Apply validate_agent_id at LangGraph adapter agent-runtime concat sites #492. The vague
"see issue tracker history" history pointer is also replaced with
a concrete
CHANGELOG.mdUnreleased + mem_agent_register / mem_agent_search: validate vs sanitize divergence #493 anchor.🤖 Generated with Claude Code