Skip to content

feat(langgraph): multi-agent helpers on MemtomemStore#460

Merged
memtomem merged 1 commit intomainfrom
feat/langgraph-multi-agent-helpers
Apr 24, 2026
Merged

feat(langgraph): multi-agent helpers on MemtomemStore#460
memtomem merged 1 commit intomainfrom
feat/langgraph-multi-agent-helpers

Conversation

@memtomem
Copy link
Copy Markdown
Owner

Summary

Before this PR, the LangGraph adapter (MemtomemStore) only exposed
raw namespace= strings — multi-agent users had to hand-build
f"agent-runtime:{id}" on every call, and the multi-agent guide's
advertised "LangGraph adapter for multi-agent" was a thin wrapper
around start_session that hard-coded namespace="default".

This PR threads a multi-agent semantic through the adapter:

  • start_agent_session(agent_id, *, namespace=None) — derives the
    namespace from agent-runtime:<agent_id> (override available),
    records the session in storage, binds _current_agent_id.
  • search(..., include_shared: bool | None = None) — 3-state toggle
    with a documented 6-case state table.
  • add(..., namespace=None) — defaults to the bound agent's private
    bucket; explicit namespace="shared" wins so the caller can publish
    cross-agent without re-binding.
  • end_session resets both _current_session_id and _current_agent_id.
  • Legacy start_session(agent_id, namespace) preserved as a low-level
    escape hatch.

include_shared semantic table

include_shared _current_agent_id resolved namespace filter
None (auto) "planner" "agent-runtime:planner,shared"
None (auto) unset caller's namespace= (legacy)
True "planner" "agent-runtime:planner,shared"
True unset ValueError (no silent leak)
False "planner" "agent-runtime:planner" (no shared)
False unset caller's namespace=

True without a bound agent raises explicitly so a missing
start_agent_session surfaces immediately rather than degrading to a
silent un-pinned search.

Out of scope

Implementing LangGraph's BaseStore (aput / aget /
alist_namespaces) with the same multi-agent awareness — tracked as a
follow-up RFC. The adapter stays a hand-rolled wrapper; multi-agent
helpers live on start_agent_session and search(include_shared=)
only.

Test plan

  • TestResolveSearchNamespace — 6 cases, one per row of the
    state table above. The True + unset case asserts the explicit
    ValueError so silent fallback can never sneak in.
  • TestResolveAddNamespace — 4 cases for the add namespace
    defaulting: no agent / agent + None / agent + explicit override.
  • TestStartAgentSession — agent binding, derived namespace,
    explicit override, empty-id rejection, end_session reset.
  • uv run pytest -m "not ollama" — 2345 passed, 46 deselected.
  • uv run ruff check + ruff format --check — clean.

🤖 Generated with Claude Code

…ssion, include_shared)

Before this PR, the LangGraph adapter only exposed raw `namespace=`
strings — multi-agent users had to hand-build `f"agent-runtime:{id}"`
on every call, and the multi-agent guide's advertised "LangGraph
adapter for multi-agent" was a thin wrapper around `start_session`
that hard-coded `namespace="default"`.

This PR threads a multi-agent semantic through the adapter:

* New `start_agent_session(agent_id, *, namespace=None)` derives the
  namespace from `agent-runtime:<agent_id>` (override available),
  records the session in storage, and binds `_current_agent_id` so
  subsequent search/add calls inherit the agent scope.

* New `search(..., include_shared: bool | None = None)` parameter
  encodes a documented 6-case state table:

    | include_shared | _current_agent_id | resolved namespace                  |
    |----------------|-------------------|--------------------------------------|
    | None (auto)    | "planner"         | "agent-runtime:planner,shared"      |
    | None (auto)    | unset             | caller's namespace= (legacy)        |
    | True           | "planner"         | "agent-runtime:planner,shared"      |
    | True           | unset             | raises ValueError (no silent leak)  |
    | False          | "planner"         | "agent-runtime:planner" (no shared) |
    | False          | unset             | caller's namespace=                 |

  `True` without a bound agent raises explicitly so a missing
  start_agent_session surfaces immediately rather than degrading to a
  silent un-pinned search.

* `add(..., namespace=None)` defaults to the bound agent's private
  bucket. Pass `namespace="shared"` to publish across agents
  mid-session — the explicit value always wins, so the caller can
  cross the bucket boundary without re-binding the session.

* `end_session` now resets both `_current_session_id` and
  `_current_agent_id`, so a stale agent binding can't survive into a
  new session. The legacy `start_session(agent_id, namespace)` is
  preserved as a low-level escape hatch with a docstring pointer to
  `start_agent_session`.

Explicitly out of scope: implementing LangGraph's `BaseStore`
(`aput` / `aget` / `alist_namespaces`) with the same multi-agent
awareness — tracked as a follow-up RFC. The adapter stays a
hand-rolled wrapper; multi-agent helpers live on `start_agent_session`
and `search(include_shared=)` only.

Test surface (test_langgraph.py):
- `TestMemtomemStoreInit.test_agent_id_none_initially` — fresh store
  reports no bound agent.
- `TestResolveSearchNamespace` — 6 cases, one per row of the state
  table above. The `True + unset` case asserts the explicit
  ValueError so silent fallback can never sneak in.
- `TestResolveAddNamespace` — 4 cases for the `add` namespace defaulting:
  no agent / agent + None / agent + explicit override.
- `TestStartAgentSession` — agent binding, derived namespace,
  explicit-namespace override, empty-agent-id rejection,
  end_session resets both fields.

Co-Authored-By: Claude <[email protected]>
@memtomem memtomem force-pushed the feat/langgraph-multi-agent-helpers branch from c507736 to 857f96e Compare April 24, 2026 22:01
@memtomem memtomem merged commit 9d36464 into main Apr 24, 2026
7 checks passed
@memtomem memtomem deleted the feat/langgraph-multi-agent-helpers branch April 24, 2026 22:01
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 24, 2026
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