Skip to main content
visualize_memory_provenance() renders the ownership and data-flow story behind your memory — Tenant → User → Agent → Dataset → file, plus agent read/write access and agent-written sessions — to a self-contained HTML file. Before you start:
  • Complete Quickstart to understand basic operations
  • Have some ingested data (the projection reads the relational database, so no graph backend is required)

Code in Action

This projection is read purely from the relational database — it does not require the graph backend or an LLM, so it works even when the graph database is unavailable. Set include_memory=True to also fold in the extracted entities/relationships (from the relational nodes/edges tables) and link them back to the files they were extracted from.

Raw graph data

If you only need the projected graph data (in the same (nodes, edges) shape the renderer consumes) rather than HTML, call get_memory_provenance_graph():

Scoping in multi-tenant deployments

Both functions accept scope_tenant_ids and scope_user_ids to restrict the projection to a tenant or user, and scope_dataset_ids to narrow it to the datasets the caller can read. In multi-tenant deployments you must pass a scope — an unscoped read returns every tenant’s actors, datasets, and files. A tenant scope alone still covers every dataset in the workspace, so for a tenant member who doesn’t administer the tenant also pass scope_dataset_ids; otherwise the graph shows datasets they hold no grant on, along with their files, agents, and sessions. When no scope is given the read is global, which is the intended behavior only for single-user / OSS installs where one user owns everything. A third argument, scope_dataset_ids, narrows the projection further on top of whichever scope above applies. A tenant scope answers “which datasets exist in this workspace”, which is not the same question as “which datasets may this caller read” — every member of a tenant is in tenant scope. Pass the caller’s readable datasets (from get_all_user_permission_datasets(user, "read")) for any caller who does not administer the tenant:
scope_dataset_ids only ever narrows — it never widens a tenant or user scope, and an empty list means “this caller may read nothing”, which yields no dataset nodes rather than all of them. Everything the projection derives from datasets narrows with them: the files in those datasets, the ACL grant edges on them, the agents and sessions that worked on them, and the extracted memory when include_memory=True. It also narrows the actor layer — a role is kept only if it holds an ACL grant on an in-scope dataset, and a user only if they own an in-scope dataset, hold a direct grant on one, or belong to a role that does. Passed without a tenant scope, scope_dataset_ids narrows the Tenant layer too: only the tenants the in-scope datasets belong to are projected, so an unrelated tenant’s name cannot appear in the graph.

Over HTTP

The HTTP endpoints GET /api/v1/schema/provenance (HTML) and GET /api/v1/schema/provenance/json (both take the query param include_memory) scope to the authenticated caller:
A client that treated the provenance payload as a complete user/role directory must read those lists from the permissions endpoints instead — roles and users — since for a non-administrator it is now scoped to their readable datasets.

Full Example

This script ingests two documents into two datasets, then walks the ownership chain down to the mentions edges that tie each memory node back to the file it came from, prints it as a tree, and renders the same projection to .artifacts/memory_provenance.html. Source: examples/guides/memory_provenance.py.

Graph Visualization

Render your knowledge graph to an interactive HTML file

Schema Inventory

Summarize the knowledge graph by semantic type