Persistent knowledge

Graph memory for AI agents

Why durable knowledge should be visible and correctable, how UIntellAgent models facts and relations, and how the TUI manages large graphs safely.

11 minute readUpdated July 17, 2026

The memory problem

Persistent agent memory must be visible enough to correct

A model context window can carry recent facts through one interaction, but it is temporary and difficult to audit. Retrieval systems can bring older text back into a prompt, yet an operator still needs to know what was stored, why it was selected, and how it relates to the current task.

Graph memory treats durable knowledge as explicit units and relationships rather than as an invisible transcript. A fact can belong to a dataset, point to a code location, carry provenance and confidence, and connect to other facts through typed edges. The resulting graph can be queried by both the agent and the operator.

Durable units

Facts have stable record IDs, content, type, source, confidence, tags, timestamps, and dataset membership.

Typed relations

Directed relates_to and proves edges preserve more meaning than an unstructured similarity score.

Operator inspection

Graph, Explorer, Query, and Analytics views expose knowledge through different operational lenses.

Repair history

Destructive UI actions are journaled so deletion and relation changes can be undone and redone.

Memory is a policy decision

UIntellAgent keeps graph writes read-only during autonomous runs unless the operator explicitly starts the task with a remember policy.

SurrealDB data model

Facts, datasets, relations, positions, and provenance share one graph

UIntellAgent uses SurrealDB 3 for its knowledge graph. The fact table is schema-full, so the application declares the fields it expects rather than accepting arbitrary record shapes. Separate relation tables connect one fact to another.

RecordImportant fieldsPurpose
factfact_type, content, source, confidence, tagsThe knowledge unit and the metadata used to understand or filter it.
fact locationcode_path, line range, column, symbol, run_idConnects a durable unit to source code or the run that produced it.
fact layoutgraph_x, graph_y, graph_pinnedPersists the operator's visual arrangement instead of recalculating it on every launch.
datasetname, description, created_atPartitions facts into named collections such as default or code.
relates_toin, outRepresents a directed semantic relationship between facts.
provesin, outRepresents one fact as evidence supporting another.
graph_auditaction, entity_id, payload, timestamp, undoneStores enough operation history to reverse supported destructive actions.

A code location is a normal fact with additional path and range fields, not a separate hidden index. That lets the same graph connect a requirement, a design decision, a durable run, and the symbol that implements it.

Visual graph operations

The Memory workspace is a database console, not a static diagram

Open Memory with Alt+2 inside the unified agent, or run cargo run -- db when you want the graph console without loading an AI provider. Both entry points reuse the same state model, repository, event handlers, layout engine, validation, analytics, and spatial index.

1
Graph

Drag, pan, zoom, pin, lasso, filter, auto-layout, fit, select, and inspect connected units in a spatial view.

2
Explorer

Browse datasets and fact types in a Yazi-style list, mark many units, inspect metadata, and perform bulk moves.

3
Query

Use templates or enter SurrealQL, preview mutating statements, inspect results, and cancel or retry background work.

4
Analytics

Review dataset counts, fact types, relation counts, disconnected units, and other graph-health signals.

Position is part of the data. Dragging or pinning a node persists its coordinates, while saved views retain filters, pan, and zoom. This allows operators to create stable working maps instead of losing their arrangement after every refresh.

Graph view commands
:dataset code
:layout
:fit-all
:view-save code-review
:views

SurrealQL safety

Reading and mutation use different command paths

The Query view accepts SurrealQL, but it does not treat every statement equally. :query is the read-only path. A mutating statement requires :query!, followed by a preview and an additional explicit confirmation before execution.

Read-only SurrealQL
:query SELECT id, fact_type, content, dataset
FROM fact
WHERE dataset = "code"
ORDER BY updated_at DESC
LIMIT 20;

The application validates record identifiers and safe labels before interpolating them into graph operations. User text is serialized as a SurrealQL string instead of concatenated directly. Imports are also split into preview and merge commands: :import validates and summarizes a snapshot without changing data, while:import! performs the confirmed merge.

Database syntax is still powerful

Confirmation reduces accidental mutation; it does not make an arbitrary query correct. Export a snapshot and inspect the preview before large changes.

Supported destructive UI operations append an audit entry. Use U or :undo to restore the previous state and R or :redo to reapply it.

Large graph behavior

Load progressively and render only what the viewport needs

A graph UI that works with twenty facts can fail when the database holds thousands. UIntellAgent separates the total graph size from the current interactive window and provides explicit controls for increasing that window.

  • :load-more [count] or > adds another bounded page of facts.
  • :load-all expands the window up to the configured 100,000-node ceiling.
  • Viewport culling skips nodes and edges that cannot affect the current frame.
  • Indexed edge lookup avoids scanning every relation for each visible node.
  • The Explorer virtualizes long lists instead of building a terminal row for every fact.
  • Analytics are cached and refreshed as a background job.

The minimap provides orientation on larger terminals, while fit-selected and fit-all operations recover a useful viewport after filters or bulk layout. Background refresh and layout report progress and remain cancellable withEsc, Ctrl+G, or :cancel.

Memory lifecycle

Store less, inspect often, and make correction routine

Useful agent memory is not the largest possible transcript archive. It is a maintained collection of facts with a reason to persist. Each stored unit should have enough provenance and structure that a future operator can decide whether it remains relevant.

01
Create deliberately

Store a fact through the graph tool, TUI form, code-location action, import, or a run explicitly allowed to remember.

02
Relate with meaning

Choose a directed relation that reflects whether units are associated or one provides evidence for another.

03
Retrieve by task

Use dataset, type, text, topology, or query filters to build a bounded context rather than loading every fact.

04
Correct and repair

Edit stale content, remove unsupported edges, undo mistakes, and run :repair for metadata and duplicate-edge cleanup.

05
Export and verify

Create versioned JSON snapshots. Partial exports record loaded and total fact counts so their scope is unambiguous.

Maintenance
:export ~/.uintell/graph-snapshot.json
:repair
:query SELECT * FROM graph_audit ORDER BY timestamp DESC LIMIT 20;

Use the real interface

Move from architecture to an inspectable run.

Open the complete command reference, configure a provider, and launch all five UIntellAgent workspaces.