Documentation
Graph memory
A property graph of people, projects, and typed edges. Reads are cheap and sync; writes are queued to three background workers.
What it is
The graph is a property graph: nodes (Person, Project, Technology, Preference, …) and typed edges (WORKS_ON, USES, PREFERS, …). It is not a chat log and not vector search.
On each run with .graph(true):
- Read (sync, cheap):
graph.contextFor(prompt, userId)is appended to the system prompt so the model can use known facts. - Write (async): the user + assistant text is queued. Three timers process the queue. Your
run()returns without waiting for extraction.
Use when you want durable, queryable structure: who works on what, which stack, what they prefer. Typical products: support, CRM-like assistants, internal “who owns this service?” bots.
Use memory instead when you only need similar past sentences. Use sessions when you only need the current thread.
Start it
import { Agent, graph, createFileGraph } from "shirube-ai";
graph.start();
const agent = Agent.builder()
.name("ops")
.instructions(
"Use the knowledge graph about this user. If a fact is missing, ask — do not invent employers or repos.",
)
.apiKey(process.env.OPENAI_API_KEY!)
.graph(true)
.build();
await agent.run("I'm Ada. I am working on Project Shirube using TypeScript. I prefer sci-fi.", {
userId: "ada",
});
await graph.flush();
console.log(graph.contextFor("Shirube TypeScript", "ada"));Persist across restarts:
const runtime = await createFileGraph("./.shirube-graph.json");
runtime.start();
Agent.builder().graph(runtime);.graph(false) or omitting .graph() means this agent neither reads nor ingests.
The three background processes
They are separate intervals, not steps inside run(). One failing does not stop the others. Each item is retried up to three times; counters live on graph.stats.
1. Memory extraction
Reads queued conversations. Upserts nodes for people, projects, technologies, preferences, and similar entities (names, “working on X”, “using Y”, “I prefer Z”).
Problem it solves: transcripts are messy; the graph needs canonical nodes.
2. Relationship builder
Looks at the same text (and new nodes) and creates edges. The same (from, type, to) updates confidence instead of inserting a duplicate.
Problem it solves: “Ada uses TypeScript” mentioned twice should not be two edges.
3. Graph maintenance
Merges nodes that normalize to the same id, decays stale edges, prunes very low-confidence isolates, boosts frequently seen links.
Problem it solves: graphs rot — duplicates, dead links, contradictions as noise.
Production uses extractMs / relateMs / maintainMs (defaults 250 / 400 / 2000). Tests call graph.flush().
graph.start({ extractMs: 250, relateMs: 400, maintainMs: 2000 });
graph.stats;Retrieval
contextFor scores nodes against the query (token overlap + confidence + mention count) and prints neighbors:
Knowledge graph:
- (Project) Shirube
USES → (Technology) TypeScript
- (Person) Ada
WORKS_ON → (Project) ShirubeScope with userId so tenants do not see each other’s graph.
Opt out / inspect
graph.reset() clears store and workers (used in tests). graph.stop() pauses timers without wiping data.