feat: knowledge-graph resource + observe identity provenance - #5
Merged
Conversation
Parity with @memmesh/sdk v0.9.0 (thinkfleet-memory-sdk#21). New `mm.memory.graph` — stats, list_entities, get_entity, list_edges, traverse, on both the sync and async clients. There was no graph surface before, so the structural half of memory was unreachable from Python. Read-only on purpose: entities and edges are written by extraction during observe(), and exposing the manual create/retire routes would invite hand-maintained graphs, which is the work the engine exists to do. Prefer graph.stats() over len(list_entities()) for any size question — the list routes page, so their length is the page size, not the total. Against a real project that is 1000 vs 12142. observe() now forwards user_id / agent_id / session_id. The server route has always accepted them; the SDK was dropping them, so provenance never arrived. Omitted rather than sent as null, so an existing call site produces byte-identical requests. They are provenance, NOT a tenancy boundary: search filters `chatIdentityId IS NULL OR = $1`, permissive by design. Verified live against app.memmesh.ai: all five graph methods return real data (12142 entities / 287698 edges). 136 tests pass, 10 new.
list_edges / traverse / get_entity().edges return the server's GraphTraversalEdge — subject and object are hydrated entity dicts, not ids, plus a hop counter. There is no subjectId on the wire. Python returns plain dicts so this never failed at runtime, but the type alias and docs described a shape the API does not produce. The Rust port did fail, which is how it was found.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Python parity with
@memmesh/sdkv0.9.0 — seethinkfleet-memory-sdk#21.
New:
mm.memory.graphstats()GET /admin/memory/graph/statslist_entities(...)GET /admin/memory/entitiesget_entity(id, ...)GET /admin/memory/entities/:idlist_edges(...)GET /admin/memory/graph/edgestraverse(id, ...)POST /admin/memory/graph/traverseOn both
MemMeshandAsyncMemMesh. There was no graph surface before, so thestructural half of memory — the entities and typed edges extraction builds —
was unreachable from Python.
Read-only on purpose: entities and edges are written by extraction during
observe(), and exposing the manual create/retire routes would invitehand-maintained graphs — the work the engine exists to do.
Use
stats(), notlen(list_entities()), for any "how big is it" question.The list routes page, so their length is the page size. Against a real project
that is the difference between reporting 1,000 and the actual 12,142.
observe()forwards identityuser_id/agent_id/session_idnow reach the server. The route has alwaysaccepted them; the SDK was dropping them, so provenance never arrived on
anything written through
observe().They are provenance, not a tenancy boundary — search filters
chatIdentityId IS NULL OR = $1, permissive by design so project-wide memoriesstay visible. Documented as such.
Compatibility
Additive only. The fields are omitted rather than sent as null, so an existing
call site produces a byte-identical request — covered by
test_observe_text_omits_identity_when_unset.Verification
tests/test_graph.py), coveringrequest shaping for all five graph methods, filter omission, and sync/async
parity.
app.memmesh.ai: all five methods return real data— 12,142 entities, 287,698 edges, 184,737 memories with edges.
Remaining parity gaps
Go, Rust, and .NET have the same two gaps and are being brought up separately.
Go is furthest behind — it has no raw-text
observeat all.