Context
PRs #491 / #494 / #495 closed the parity gap on caller-supplied
agent_id — every surface that builds agent-runtime:<agent_id>
now runs validate_agent_id. But each session-start entry point
also accepts an explicit namespace= override that bypasses the
gate entirely:
# LangGraph adapter — landed in #495
await store.start_agent_session(agent_id="planner", namespace="agent-runtime:foo:bar")
# MCP — same shape via mem_session_start
mem_session_start(agent_id="planner", namespace="agent-runtime:foo:bar")
# CLI — same shape via mm session start --namespace
mm session start --agent-id planner --namespace 'agent-runtime:foo:bar'
In all three cases agent_id itself is clean ("planner"), but
the explicit namespace= argument lands in the session row
verbatim — a Python / MCP / CLI caller can still write a malformed
"agent-runtime:foo:bar" namespace into storage.
This is the kin issue to the mem_agent_share(target=...) gap
flagged on PR #494 review: the same bypass exists on every surface
where a user-supplied namespace string is accepted alongside
agent_id.
What we want
A NamespaceFormat validator (or extension of validate_name
with kind="namespace") that runs over user-supplied namespace
strings before storage / search ever sees them. Apply at:
The validator should reject the same malformed shapes that
validate_agent_id catches when the namespace contains an
agent-runtime: prefix (so an untrusted agent_id can't be
smuggled through the override), and likely a broader namespace
charset everywhere ([A-Za-z0-9._\\-:,]+ with structural rules
about colon depth and reserved tokens — exact spec is part of the
work).
Acceptance
- All listed entry points reject hostile-shaped
namespace= /
target= values with an InvalidNameError (or its public
alias) before storage is touched.
- Regression test pinning that
store.start_agent_session(agent_id="planner", namespace="agent-runtime:foo:bar") cannot land an
agent-runtime:foo:bar row.
- No silent rewrite: rejection must be loud, mirroring the
agent_id gate's UX.
- The session_start namespace derivation rules in the existing
docstrings (LangGraph adapter + mem_session_start) are updated
to mention the new validator.
Out of scope
- Migrating any namespace rows that may already be malformed in
existing storage — this is a forward gate.
- Validating namespaces that are derived internally
(e.g. f"{AGENT_NAMESPACE_PREFIX}{agent_id}" after
validate_agent_id succeeded) — those paths are already safe by
construction.
Provenance
Context
PRs #491 / #494 / #495 closed the parity gap on caller-supplied
agent_id— every surface that buildsagent-runtime:<agent_id>now runs
validate_agent_id. But each session-start entry pointalso accepts an explicit
namespace=override that bypasses thegate entirely:
In all three cases
agent_iditself is clean ("planner"), butthe explicit
namespace=argument lands in the session rowverbatim — a Python / MCP / CLI caller can still write a malformed
"agent-runtime:foo:bar"namespace into storage.This is the kin issue to the
mem_agent_share(target=...)gapflagged on PR #494 review: the same bypass exists on every surface
where a user-supplied namespace string is accepted alongside
agent_id.What we want
A
NamespaceFormatvalidator (or extension ofvalidate_namewith
kind="namespace") that runs over user-supplied namespacestrings before storage / search ever sees them. Apply at:
MemtomemStore.start_agent_session(namespace=...)(LangGraph)mem_session_start(namespace=...)(MCP)mm session start --namespace/mm session wrap --namespace(CLI)mem_agent_share(target=...)(MCP) — flagged on PR fix: validate agent_id at mem_agent_register / search andmm agent register(#493) #494namespaceparameter fromcaller input
The validator should reject the same malformed shapes that
validate_agent_idcatches when the namespace contains anagent-runtime:prefix (so an untrustedagent_idcan't besmuggled through the override), and likely a broader namespace
charset everywhere (
[A-Za-z0-9._\\-:,]+with structural rulesabout colon depth and reserved tokens — exact spec is part of the
work).
Acceptance
namespace=/target=values with anInvalidNameError(or its publicalias) before storage is touched.
store.start_agent_session(agent_id="planner", namespace="agent-runtime:foo:bar")cannot land anagent-runtime:foo:barrow.agent_idgate's UX.docstrings (LangGraph adapter +
mem_session_start) are updatedto mention the new validator.
Out of scope
existing storage — this is a forward gate.
(e.g.
f"{AGENT_NAMESPACE_PREFIX}{agent_id}"aftervalidate_agent_idsucceeded) — those paths are already safe byconstruction.
Provenance
start_agent_session(agent_id='planner', namespace='agent-runtime:foo:bar')and write a malformednamespace into the session row even though
agent_iditself isclean. Same shape as the
mem_agent_share(target=...)gap Iflagged on fix: validate agent_id at mem_agent_register / search and
mm agent register(#493) #494."agent_idgate work that started in Validate agent_id before agent-runtime namespace concatenation (CLI + MCP) #486.