Skip to content

Graph

The graph contract models a bounded context as typed node and edge kinds and gives three ports over them: a query port (traverse), a command port (mutate), and a raw port (an escape hatch for native queries). A GraphModuleSpec bundles the kinds; refs (VertexRef / EdgeRef) address individual nodes and edges by kind + id.

q = ctx.graph.query(spec)      # traverse
c = ctx.graph.command(spec)    # mutate
r = ctx.graph.raw(spec)        # native-query escape hatch

Spec

GraphModuleSpec — a module-level bundle of vertex and edge kinds:

Field Type Meaning
name str \| StrEnum the graph area / module name
nodes tuple[GraphNodeSpec, ...] the vertex kinds (each a named model)
edges tuple[GraphEdgeSpec, ...] the edge kinds (each a named model)

Each GraphNodeSpec / GraphEdgeSpec carries a name (the kind), a read model, and optional create / update models. An edge also declares its identity ("key" or "endpoints"), its allowed endpoints, and its directionality (directed / symmetric). Field encryption covers nodes and key-addressed edges; endpoint-identity edges reject binds_record_id.

Query port (ctx.graph.query(spec))

Method Notes
get_vertex(ref) / get_vertices(refs) fetch nodes by ref
get_edge(ref) / get_edges(refs) fetch edges by ref
vertex_exists(ref) / edge_exists(ref) presence checks
find_vertices(node_kind, *, property_filter=None, limit=100, offset=0) list nodes of a kind, optionally filtered by properties
find_edges(edge_kind, *, property_filter=None, limit=100, offset=0) list edges of a kind
count_vertices(node_kind, *, property_filter=None) / count_edges(edge_kind, …) counts by kind
neighbors(origin, direction, edge_kinds, *, limit, to_vertex_kinds=None) adjacent nodes with the connecting edge, filtered by kind and direction
incident_edges(origin, direction, edge_kinds, *, limit) the edges touching a node
vertex_degree(ref, …) / count_neighbors(ref, …) degree / distinct-neighbor counts by direction and edge kind
expand(start, params) breadth-limited walk (GraphWalkParams: max_depth, max_results, direction, edge kinds) returning GraphWalkSteps
scoped_walk(anchor, params) multi-step typed traversal (ScopedWalkParams: a tuple of GraphPathSteps with per-step hop bounds, a target_kind, a limit)
shortest_path(from_ref, to_ref, params) one path (ShortestPathParams: max_hops, edge_kinds, optional weight_property for weighted/native paths — needs a GDS-capable backend, else graph_algorithm_unavailable)
k_shortest_paths(from_ref, to_ref, params, *, k) the k best paths, same params

Command port (ctx.graph.command(spec))

Every create/ensure takes return_new: bool = True.

Method Notes
create_vertex(node_kind, cmd) / create_vertices(items) add nodes
create_edge(edge_kind, cmd) / create_edges(items) add edges
ensure_vertex(node_kind, cmd) / ensure_edge(edge_kind, cmd) insert-when-missing (idempotent by identity)
update_vertex(ref, cmd) / update_edge(ref, cmd) patch by ref
delete_vertex(ref) / delete_vertices(refs) remove nodes
delete_edge(ref) / delete_edges(refs) remove edges

Raw port (ctx.graph.raw(spec))

run(query, params=None) executes a native query (Cypher) — the escape hatch for traversals the typed ports don't express.

Management port (ctx.graph.management(spec))

Control-plane schema provisioning, separate from the data-plane command port: ensure_schema() creates constraints/indexes for the declared kinds; drop_schema() removes them.

Implemented by

Backend Integration
Neo4j Neo4j

A mock implements the surface for tests.