Skip to content

Entity graph

The entity graph (schema head V11) links observations through shared entities — files, symbols, concepts, people, agents — and typed edges (mentions, fixes, contradicts, about). It is what makes obs context return the right neighborhood on the agent’s first call.

  1. SaveWriteRequest::IndexGraph rides the per-project write thread: entities are upserted (dedupe by norm_name), mentions wired, pairwise mentions edges accumulated.
  2. Queryobs search / obs context extract query entities, walk up to graph.hops hops over graph.edge_types, and fuse a third rank list into the hybrid RRF path via graph_rank::graph_score.
  3. Briefingobs context appends budgeted graph-expanded hits capped at graph.budget_pct × max_tokens; it never displaces primary hits, and stale/withdrawn observations drop out with the same rules as the main path.
Terminal window
statefulmemory graph query <entity> --hops 2 # traverse the neighborhood
statefulmemory graph query <entity> --relation fixes # narrow to a relation
statefulmemory graph rebuild # backfill entities from anchors
statefulmemory graph stats
[graph]
enabled = true # default off until the CI multi-hop gate passes (+5 pts)
hops = 2 # hard cap 2
boost = 0.15 # post-fusion multiplier for graph-lift-only hits
edge_types = ["mentions", "fixes", "contradicts"]
budget_pct = 0.4 # max share of briefing tokens from expansion
degree_cap = 256 # skip traversal into hub entities
max_query_entities = 3

Environment overrides: STATEFULMEMORY_GRAPH_ENABLED, STATEFULMEMORY_GRAPH_HOPS, STATEFULMEMORY_GRAPH_BOOST.

The graph stays in the same SQLite file as observations (“inspectable by default” thesis). Recursive-CTE traversal at ≤2 hops with a degree cap returns in milliseconds; a dedicated graph engine (Neo4j-grade) is out of scope by design — see the gap list’s “do not build Neo4j-scale graphs” rule.

memory_graph_query(entity, hops?, relation_filter?) returns the neighborhood as a tree of from --[relation]--> to edges plus observation provenance when an edge carries src_observation_id.

Additive: ListEntities(status), GetEntity, GraphQuery.