Context
PR #491 wired validate_agent_id into the three session-start surfaces so a malformed agent_id is loudly rejected:
mem_session_start(agent_id="foo:bar")
→ "Error: invalid agent-id 'foo:bar': must match [A-Za-z0-9._-]+ ..."
The same hostile shape, sent at the multi-agent registration / search surface, takes a different path:
mem_agent_register(agent_id="foo:bar")
→ silently runs sanitize_namespace_segment("foo:bar")
→ stores under sanitised ``agent-runtime:foo_bar`` (or similar)
(See packages/memtomem/src/memtomem/server/tools/multi_agent.py:71-75 and :118-123 plus packages/memtomem/src/memtomem/cli/agent_cmd.py:108-112.)
So the same input now produces two UX outcomes depending on which tool the caller picked first — registering an agent rewrites the id in place, but starting a session for that same agent rejects it. That asymmetry is small today (multi-agent surface review just shipped) but it'll get harder to reason about as more tools fan out.
What we want
A deliberate decision between two options, applied consistently across mem_agent_register, mem_agent_search, and the matching mm agent ... CLI subcommands:
- Switch to validate. Replace
sanitize_namespace_segment calls with validate_agent_id. Same loud-reject behavior as the session-start surfaces. Breaking for any caller that was relying on silent sanitisation, but those callers were storing under unexpected namespaces anyway.
- Document the divergence. Keep the silent sanitise behavior, but add a docstring + user-guide note explaining that registration / search are forgiving and that
mem_session_start is the strict gate.
Option 1 is the cleaner long-term answer; option 2 is the cheaper short-term answer. Either way, the choice should be visible in the docstring + CHANGELOG so users aren't surprised.
Acceptance
- One of the two paths above shipped, not "we'll figure it out later."
- If option 1 (validate): regression tests pin the error parity with the session-start surfaces; CHANGELOG flags the breaking shape.
- If option 2 (document): docstrings +
docs/guides/multi-agent-quickstart.md (or equivalent) note the read/write asymmetry; the validator's docstring in constants.py stays honest about which surfaces it covers.
Out of scope
- The LangGraph adapter parity gap — tracked in its own follow-up issue.
- Adding a new "loose vs strict" config knob — that adds an axis we don't actually need until users ask for it.
Provenance
Context
PR #491 wired
validate_agent_idinto the three session-start surfaces so a malformedagent_idis loudly rejected:The same hostile shape, sent at the multi-agent registration / search surface, takes a different path:
(See
packages/memtomem/src/memtomem/server/tools/multi_agent.py:71-75and:118-123pluspackages/memtomem/src/memtomem/cli/agent_cmd.py:108-112.)So the same input now produces two UX outcomes depending on which tool the caller picked first — registering an agent rewrites the id in place, but starting a session for that same agent rejects it. That asymmetry is small today (multi-agent surface review just shipped) but it'll get harder to reason about as more tools fan out.
What we want
A deliberate decision between two options, applied consistently across
mem_agent_register,mem_agent_search, and the matchingmm agent ...CLI subcommands:sanitize_namespace_segmentcalls withvalidate_agent_id. Same loud-reject behavior as the session-start surfaces. Breaking for any caller that was relying on silent sanitisation, but those callers were storing under unexpected namespaces anyway.mem_session_startis the strict gate.Option 1 is the cleaner long-term answer; option 2 is the cheaper short-term answer. Either way, the choice should be visible in the docstring + CHANGELOG so users aren't surprised.
Acceptance
docs/guides/multi-agent-quickstart.md(or equivalent) note the read/write asymmetry; the validator's docstring inconstants.pystays honest about which surfaces it covers.Out of scope
Provenance
mem_agent_register/mem_agent_searchsemantic divergence with the new session-start gate.