Skip to content

DO NOT MERGE: Add optional NeMo Flow integration#114

Draft
afourniernv wants to merge 1 commit into
neo4j-labs:mainfrom
afourniernv:feat/nemo-flow-integration
Draft

DO NOT MERGE: Add optional NeMo Flow integration#114
afourniernv wants to merge 1 commit into
neo4j-labs:mainfrom
afourniernv:feat/nemo-flow-integration

Conversation

@afourniernv
Copy link
Copy Markdown

DO NOT MERGE

This is a draft PR for design review and live validation only. Please do not merge until the NeMo Flow integration shape, event contract, and memory provider boundaries have been reviewed.

What This Adds

Adds an optional NeMo Flow integration for Neo4j Agent Memory. The integration uses NeMo Flow as the hidden runtime/intercept layer while Neo4j Agent Memory owns memory identity, filtering, retrieval, formatting, and storage.

The intended user-facing DX is:

from neo4j_agent_memory import MemoryClient
from neo4j_agent_memory.integrations import nemo_flow

memory = MemoryClient(settings)
handle = nemo_flow.install(memory)

with nemo_flow.memory_scope(user_id="alex", thread_id="thread-123"):
    result = await agent.ainvoke({"messages": messages})

handle.uninstall()

Application code does not need to import NeMo Flow directly for the common path, as long as the agent/framework LLM boundary is already flowing through NeMo Flow instrumentation.

Integration Behavior

Before an LLM call, the intercept:

  • resolves memory identity from a custom resolver, memory_scope(...), or NeMo Flow scope metadata
  • extracts the latest user query from the request
  • recalls scoped short-term memory context
  • optionally includes long-term and reasoning context
  • injects formatted memory into a copied NeMo Flow LLMRequest

After the LLM call, the intercept:

  • extracts the user and assistant messages
  • stores them through MemoryIntegration.store_message(...) when available
  • otherwise stores them through client.short_term.add_message(...)
  • returns the original model response to the caller

Architecture

The public module is kept intentionally small:

  • integrations/nemo_flow.py: public facade, install/uninstall handle, memory scope
  • _nemo_flow_intercept.py: LLM execution orchestration
  • _nemo_flow_memory.py: Neo4j Agent Memory access and storage
  • _nemo_flow_runtime.py: lazy NeMo Flow import, scope identity, telemetry helpers
  • _nemo_flow_content.py: request/response extraction and request mutation
  • _nemo_flow_types.py: config, enums, registries, shared dataclasses

Observability

The adapter emits NeMo Flow scopes for duration-bearing operations:

  • neo4j_agent_memory.memory
  • neo4j_agent_memory.recall
  • neo4j_agent_memory.capture

It also emits mark events for state transitions:

  • neo4j_agent_memory.identity.resolved
  • neo4j_agent_memory.recall.context_built
  • neo4j_agent_memory.recall.injected
  • neo4j_agent_memory.recall.skipped
  • neo4j_agent_memory.recall.failed
  • neo4j_agent_memory.capture.extracted
  • neo4j_agent_memory.capture.message_stored
  • neo4j_agent_memory.capture.stored
  • neo4j_agent_memory.capture.skipped
  • neo4j_agent_memory.capture.failed

Scope and event payloads avoid raw user query text and recalled memory text. They include operational metadata such as counts, character lengths, insertion index, roles, and storage status.

Included Artifacts

  • Optional dependency extra: neo4j-agent-memory[nemo-flow]
  • Public integration API
  • Unit tests with a fake NeMo Flow runtime
  • Example smoke test without external services
  • Live integration smoke test using the existing Neo4j fixture/testcontainer path
  • Integration docs page and nav/index entries

Validation

Ran:

env UV_CACHE_DIR=/tmp/uv-cache uv run ruff check src/neo4j_agent_memory/integrations/nemo_flow.py src/neo4j_agent_memory/integrations/_nemo_flow_types.py src/neo4j_agent_memory/integrations/_nemo_flow_content.py src/neo4j_agent_memory/integrations/_nemo_flow_runtime.py src/neo4j_agent_memory/integrations/_nemo_flow_memory.py src/neo4j_agent_memory/integrations/_nemo_flow_intercept.py tests/unit/integrations/test_nemo_flow.py tests/examples/test_nemo_flow_memory.py tests/integration/test_nemo_flow_integration.py
env UV_CACHE_DIR=/tmp/uv-cache uv run ruff format --check src/neo4j_agent_memory/integrations/nemo_flow.py src/neo4j_agent_memory/integrations/_nemo_flow_types.py src/neo4j_agent_memory/integrations/_nemo_flow_content.py src/neo4j_agent_memory/integrations/_nemo_flow_runtime.py src/neo4j_agent_memory/integrations/_nemo_flow_memory.py src/neo4j_agent_memory/integrations/_nemo_flow_intercept.py tests/unit/integrations/test_nemo_flow.py tests/examples/test_nemo_flow_memory.py tests/integration/test_nemo_flow_integration.py
env UV_CACHE_DIR=/tmp/uv-cache uv run pytest tests/unit/integrations/test_nemo_flow.py tests/examples/test_nemo_flow_memory.py tests/integration/test_nemo_flow_integration.py -q

Result: 11 passed, Ruff clean.

Known Limitations / Review Items

  • Non-streaming LLM execution path only
  • No direct tool-call memory capture yet
  • Long-term and reasoning recall are opt-in
  • Capture writes conversational short-term memory by default
  • Entity extraction may run indirectly through short-term memory storage, but this adapter does not yet observe extraction/deduplication counts
  • Needs manual observability review with a real NeMo Flow subscriber/exporter setup before merge

@vercel
Copy link
Copy Markdown

vercel Bot commented May 4, 2026

@afourniernv is attempting to deploy a commit to the lyonwj's projects Team on Vercel.

A member of the Team first needs to authorize it.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agent-memory Ready Ready Preview, Comment May 4, 2026 3:57am

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an optional NeMo Flow integration layer to Neo4j Agent Memory, enabling automatic recall/capture and NeMo Flow scope/event observability around instrumented (non-streaming) LLM executions while keeping Neo4j Agent Memory responsible for identity, filtering, storage, and formatting.

Changes:

  • Introduces a public neo4j_agent_memory.integrations.nemo_flow facade plus private adapter modules for request/response shaping, identity resolution, telemetry, recall, and capture.
  • Adds optional dependency extra (neo4j-agent-memory[nemo-flow]), an example script, and unit/example/integration smoke tests.
  • Documents the integration and links it into the integrations docs index + navigation.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
uv.lock Locks nemo-flow package artifacts and wires the new nemo-flow extra into the lock metadata.
pyproject.toml Adds nemo-flow optional dependency extra (Python ≥ 3.11).
src/neo4j_agent_memory/integrations/init.py Exposes nemo_flow from the integrations package namespace.
src/neo4j_agent_memory/integrations/nemo_flow.py Public facade: install/uninstall handle and memory_scope context manager.
src/neo4j_agent_memory/integrations/_nemo_flow_types.py Shared dataclasses/enums/config/registries for scopes/events and identity types.
src/neo4j_agent_memory/integrations/_nemo_flow_runtime.py Lazy NeMo Flow import, identity-from-scope metadata, and telemetry helpers.
src/neo4j_agent_memory/integrations/_nemo_flow_memory.py Neo4j memory access layer (context building + message storage).
src/neo4j_agent_memory/integrations/_nemo_flow_intercept.py NeMo Flow LLM execution intercept orchestrating recall/capture + emitting scopes/events.
src/neo4j_agent_memory/integrations/_nemo_flow_content.py Extracts query/interaction, formats context, injects system message into request content.
tests/unit/integrations/test_nemo_flow.py Unit tests using a fake NeMo Flow runtime to validate install, identity, recall/capture, and observability events.
tests/examples/test_nemo_flow_memory.py Smoke test that loads and runs the example module when nemo_flow is installed.
tests/integration/test_nemo_flow_integration.py Live smoke test through real NeMo Flow + real Neo4j memory fixture.
examples/nemo_flow_memory.py No-external-services demo showing install + memory_scope + instrumented execute path.
docs/modules/ROOT/pages/how-to/integrations/nemo-flow.adoc New how-to page describing installation, behavior, customization, and observability contract.
docs/modules/ROOT/pages/how-to/integrations/index.adoc Adds NeMo Flow integration to the integrations index and quickstart snippets.
docs/modules/ROOT/nav.adoc Adds NeMo Flow to the documentation navigation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +195 to +197
if accepts_positional_query(method):
return await self.invoke(method, query, **kwargs)
return await self.invoke(method, query=query, **kwargs)
Comment on lines +122 to +132
if not parts and hasattr(self.memory, "get_context"):
context = await self._invoke_get_context(
self.memory.get_context,
query,
session_id=session_id,
)
return coerce_recall_context(
context,
NemoFlowContextSource.MEMORY_INTEGRATION,
metadata={"fallback_used": True},
)
Comment on lines +129 to +130
for key, value in identity.metadata().items():
captured.setdefault(key, value)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants