symfonic.memory.backends¶
backends ¶
Backend implementations for graph and vector storage.
InMemoryGraphBackend ¶
In-memory implementation of the GraphBackend protocol.
Stores nodes and edges in dicts keyed by (tenant_id, node_id/edge_id). Suitable for testing and local development only.
Source code in src/symfonic/memory/backends/in_memory.py
add_edge
async
¶
Add an edge to the in-memory store.
add_node
async
¶
Add a node to the in-memory store.
v8.0: stamps the materialised scope_path into the node's
property bag (zero-migration) so the prefix-isolation filter (§5.d)
can be enforced on every read.
Source code in src/symfonic/memory/backends/in_memory.py
delete_edge
async
¶
Delete a single edge by its ID.
delete_node
async
¶
Delete a node, optionally cascading to connected edges.
Source code in src/symfonic/memory/backends/in_memory.py
get_neighbors
async
¶
get_neighbors(
scope: TenantScope,
node_id: NodeId,
relationship: str | None = None,
) -> list[MemoryNode]
Get nodes connected to the given node by edges.
Source code in src/symfonic/memory/backends/in_memory.py
get_node
async
¶
Get a node by ID within the scope's visible prefix chain.
Source code in src/symfonic/memory/backends/in_memory.py
query_edges
async
¶
query_edges(
scope: TenantScope,
filters: dict[str, Any] | None = None,
limit: int = 50,
offset: int = 0,
) -> list[MemoryEdge]
Query edges with optional relationship filter and pagination.
Source code in src/symfonic/memory/backends/in_memory.py
query_nodes
async
¶
query_nodes(
scope: TenantScope,
filters: dict[str, Any],
limit: int | None = 50,
) -> list[MemoryNode]
Filter nodes by properties within the tenant scope.
limit=None returns every matching node (no truncation);
limit=0 returns no rows (v8.7.1 — unified across backends).
Source code in src/symfonic/memory/backends/in_memory.py
traverse
async
¶
BFS traversal from start node up to max_depth.
Source code in src/symfonic/memory/backends/in_memory.py
update_node
async
¶
Partial update of node properties.
Source code in src/symfonic/memory/backends/in_memory.py
upsert_edge
async
¶
Insert edge or increment weight by 1 if (tenant, source, target, rel) matches.
Source code in src/symfonic/memory/backends/in_memory.py
InMemoryVectorBackend ¶
In-memory implementation of the VectorBackend protocol.
Stores embeddings in a list and uses brute-force cosine similarity for search. Suitable for testing only.
Source code in src/symfonic/memory/backends/in_memory.py
add
async
¶
add(
scope: TenantScope,
ids: list[str],
embeddings: list[list[float]],
metadatas: list[dict[str, Any]],
documents: list[str],
) -> None
Add vectors with metadata to the store.
v8.0: stamps the materialised scope_path into the metadata bag so
the prefix-isolation filter (§5.d) can run on every search.
Source code in src/symfonic/memory/backends/in_memory.py
count
async
¶
delete
async
¶
Delete vectors by their IDs.
Source code in src/symfonic/memory/backends/in_memory.py
search
async
¶
Brute-force cosine similarity search.
v8.0: ALWAYS-ON prefix-isolation (§5.d) — only entries whose stored
scope_path is a prefix of the query path are scored. Dual-reads
pre-v8.0 metadata (no scope_path) as a 1-level root path.
Source code in src/symfonic/memory/backends/in_memory.py
PostgresGraphBackend ¶
GraphBackend backed by PostgreSQL with JSONB storage.
All operations enforce tenant isolation via WHERE tenant_id = $N.
Source code in src/symfonic/memory/backends/postgres_graph.py
backfill_scope_paths
async
¶
Eagerly backfill NULL scope_path rows (design §6.b migration).
Pre-v8.0 rows have scope_path IS NULL; they read as a 1-level root
path tenant\x1f<tenant_id> via the query-time dual-read, so this
eager backfill is OPTIONAL (online-safe, idempotent) — it just
materialises the same value into the column so the B-tree index and
the scorer's dual-read agree. Returns the number of rows updated.
Uses a parameterised expression so adopter tenant_ids cannot inject.
Source code in src/symfonic/memory/backends/postgres_graph.py
ensure_schema
async
¶
Create graph tables (nodes + edges) and their indexes.
Does NOT create the memory_vectors table — that is the
responsibility of :class:PostgresVectorBackend.ensure_schema.
Source code in src/symfonic/memory/backends/postgres_graph.py
query_edges
async
¶
query_edges(
scope: TenantScope,
filters: dict[str, Any] | None = None,
limit: int = 50,
offset: int = 0,
) -> list[MemoryEdge]
Query edges directly from memory_edges table with pagination.
Supports optional relationship filter. All other keys in filters
are ignored to avoid SQL injection risk.
Source code in src/symfonic/memory/backends/postgres_graph.py
traverse
async
¶
BFS graph traversal up to max_depth hops from start node.
Source code in src/symfonic/memory/backends/postgres_graph.py
upsert_edge
async
¶
Insert edge or increment weight by 1 if the same edge already exists.
Uniqueness is determined by (tenant_id, source, target, relationship).
The unique index idx_memory_edges_upsert must exist for ON CONFLICT
to resolve correctly (created by ensure_schema).
Source code in src/symfonic/memory/backends/postgres_graph.py
PostgresPoolManager ¶
Async connection pool manager wrapping asyncpg.Pool.
Usage::
pool = PostgresPoolManager(dsn="postgresql://user:pw@host/db")
await pool.open()
async with pool as conn:
await conn.execute("SELECT 1")
await pool.close()
Or as a context manager for the pool itself::
async with PostgresPoolManager(dsn=...) as pool:
conn = await pool.acquire()
try:
await conn.execute("SELECT 1")
finally:
await pool.release(conn)
Source code in src/symfonic/memory/backends/pool.py
dsn
property
¶
Return the configured connection string (read-only).
Used by the v7.1.1 PostgresCheckpointerFactory to build a
separate psycopg pool against the same database. The two pools
intentionally do not share connections (asyncpg vs. psycopg
protocols are incompatible inside langgraph-checkpoint-postgres).
acquire
async
¶
Acquire a connection from the pool.
Caller is responsible for releasing via :meth:release.
Source code in src/symfonic/memory/backends/pool.py
close
async
¶
open
async
¶
Create the underlying asyncpg connection pool.
Passes init=_register_pgvector_on_connection so every new
physical connection registers the pgvector binary codec before
the pool hands it out. See module docstring for the rationale.
Source code in src/symfonic/memory/backends/pool.py
PostgresVectorBackend ¶
VectorBackend backed by PostgreSQL + pgvector.
Uses cosine distance (<=> operator) for similarity search.
All operations enforce tenant isolation via WHERE tenant_id = $N.
Source code in src/symfonic/memory/backends/postgres_vector.py
count
async
¶
Return the total number of stored vectors for the tenant.
Source code in src/symfonic/memory/backends/postgres_vector.py
ensure_schema
async
¶
Create the memory_vectors table and indexes if not present.