Creating Knowledge Graphs with Semantic Memory

Semantic memory stores structured knowledge as entities and relationships -- a knowledge graph your agent can query, traverse, and grow over time. Build rich project knowledge bases that connect people, code, concepts, and decisions.

Overview

While episodic memory records what happened, semantic memory records what things are and how they relate. An entity might be a person, a codebase, a concept, or a tool. Relationships connect entities: "Adam owns payments-service," "payments-service uses PostgreSQL," "PostgreSQL is-a database."

Automatic entity extraction

When you create episodic memories, Rekall can automatically extract entities and relationships. You can also create them explicitly for maximum control over your knowledge graph.

Adding Entities

Entities are the nodes in your knowledge graph. Each entity has a name, type, and optional description and properties.

Create entities
import Rekall from '@rekall/agent-sdk';
const rekall = new Rekall({ apiKey: 'rk_your_key' });
// Create a person entity
const adam = await rekall.semantic.createEntity({
name: 'Adam',
type: 'person',
description: 'Lead engineer working on the payments platform',
properties: {
role: 'lead-engineer',
team: 'platform',
email: 'adam@example.com',
},
});
// Create a project entity
const paymentsService = await rekall.semantic.createEntity({
name: 'payments-service',
type: 'project',
description: 'Core payment processing microservice handling Stripe integration',
properties: {
language: 'typescript',
framework: 'fastify',
repo: 'github.com/acme/payments-service',
},
});
// Create a technology entity
const postgres = await rekall.semantic.createEntity({
name: 'PostgreSQL',
type: 'technology',
description: 'Primary relational database for transactional data',
properties: {
version: '16',
hosting: 'neon',
},
});

Entity Types

Entity types are flexible strings -- use whatever makes sense for your domain. Common types include:

person
project
technology
concept
file
function
api
team
decision

Creating Relationships

Relationships are directed edges connecting two entities. Each relationship has a type (the verb), a source entity, a target entity, and optional properties.

Create relationships
// Adam owns payments-service
await rekall.semantic.createRelationship({
sourceId: adam.id,
targetId: paymentsService.id,
type: 'owns',
properties: {
since: '2024-03',
role: 'tech-lead',
},
});
// payments-service uses PostgreSQL
await rekall.semantic.createRelationship({
sourceId: paymentsService.id,
targetId: postgres.id,
type: 'uses',
properties: {
purpose: 'transaction-storage',
critical: true,
},
});
// payments-service depends-on auth-service
const authService = await rekall.semantic.createEntity({
name: 'auth-service',
type: 'project',
description: 'JWT-based authentication and authorization service',
});
await rekall.semantic.createRelationship({
sourceId: paymentsService.id,
targetId: authService.id,
type: 'depends-on',
properties: {
interface: 'REST API',
version: 'v2',
},
});

Relationship Types

Like entity types, relationship types are flexible. Common patterns:

owns
uses
depends-on
created-by
part-of
related-to
blocked-by
implements
extends

Querying the Graph

Search for entities using natural language. Rekall matches against entity names, descriptions, and properties.

Search entities
// Find entities related to a concept
const results = await rekall.semantic.searchEntities({
query: 'payment processing infrastructure',
types: ['project', 'technology'],
limit: 10,
});
for (const entity of results.entities) {
console.log(`[${entity.type}] ${entity.name}: ${entity.description}`);
}
// Find all entities of a specific type
const people = await rekall.semantic.searchEntities({
types: ['person'],
limit: 50,
});

Relationship Queries

Query relationships from a specific entity to discover connections.

Query relationships
// What does payments-service depend on?
const deps = await rekall.semantic.getRelationships({
entityId: paymentsService.id,
direction: 'outgoing',
types: ['depends-on', 'uses'],
});
for (const rel of deps.relationships) {
console.log(`payments-service ${rel.type} ${rel.target.name}`);
}
// payments-service uses PostgreSQL
// payments-service depends-on auth-service
// Who owns what?
const ownership = await rekall.semantic.getRelationships({
entityId: adam.id,
direction: 'outgoing',
types: ['owns'],
});

Traversing Connections

Graph traversal lets you follow chains of relationships to discover indirect connections. For example, find all technologies used by projects that a person owns.

Traverse the knowledge graph
// Traverse: Adam -> owns -> projects -> uses -> technologies
const techStack = await rekall.semantic.traverse({
startEntityId: adam.id,
path: [
{ type: 'owns', direction: 'outgoing' },
{ type: 'uses', direction: 'outgoing' },
],
});
console.log('Technologies Adam works with:');
for (const node of techStack.nodes) {
console.log(` - ${node.name} (${node.type})`);
}
// - PostgreSQL (technology)
// - Redis (technology)
// - Stripe API (technology)
// Find impact radius: what depends on PostgreSQL?
const impacted = await rekall.semantic.traverse({
startEntityId: postgres.id,
path: [
{ type: 'uses', direction: 'incoming' }, // projects that use postgres
{ type: 'owns', direction: 'incoming' }, // people who own those projects
],
});
console.log('People affected if PostgreSQL goes down:');
for (const node of impacted.nodes) {
if (node.type === 'person') {
console.log(` - ${node.name}`);
}
}

Traversal depth

Traversals are limited to a maximum depth of 5 hops by default. For deeper traversals, specify maxDepth in the request (up to 10). Deep traversals may be slower on large graphs.

Building a Project Knowledge Base

Here is a complete example that builds a knowledge base for a software project, connecting people, services, technologies, and architectural decisions.

Complete project knowledge base
1import Rekall from '@rekall/agent-sdk';
2
3const rekall = new Rekall({ apiKey: 'rk_your_key' });
4
5async function buildProjectKnowledgeBase() {
6 // 1. Create team members
7 const team = await Promise.all([
8 rekall.semantic.createEntity({
9 name: 'Alice', type: 'person',
10 description: 'Backend engineer, Rust specialist',
11 properties: { team: 'platform', role: 'senior-engineer' },
12 }),
13 rekall.semantic.createEntity({
14 name: 'Bob', type: 'person',
15 description: 'Full-stack engineer, React + Node',
16 properties: { team: 'product', role: 'engineer' },
17 }),
18 ]);
19
20 // 2. Create services
21 const services = await Promise.all([
22 rekall.semantic.createEntity({
23 name: 'api-gateway', type: 'service',
24 description: 'Central API gateway handling routing and rate limiting',
25 properties: { language: 'rust', port: 8080 },
26 }),
27 rekall.semantic.createEntity({
28 name: 'web-app', type: 'service',
29 description: 'Next.js frontend application',
30 properties: { language: 'typescript', framework: 'next.js' },
31 }),
32 ]);
33
34 // 3. Create architectural decisions
35 const decisions = await Promise.all([
36 rekall.semantic.createEntity({
37 name: 'ADR-001: Use Rust for gateway',
38 type: 'decision',
39 description: 'Chose Rust over Go for the API gateway due to memory safety and performance',
40 properties: { status: 'accepted', date: '2024-06' },
41 }),
42 ]);
43
44 // 4. Wire up relationships
45 await Promise.all([
46 // Ownership
47 rekall.semantic.createRelationship({
48 sourceId: team[0].id, targetId: services[0].id,
49 type: 'owns',
50 }),
51 rekall.semantic.createRelationship({
52 sourceId: team[1].id, targetId: services[1].id,
53 type: 'owns',
54 }),
55 // Dependencies
56 rekall.semantic.createRelationship({
57 sourceId: services[1].id, targetId: services[0].id,
58 type: 'depends-on',
59 properties: { interface: 'REST' },
60 }),
61 // Decision links
62 rekall.semantic.createRelationship({
63 sourceId: decisions[0].id, targetId: services[0].id,
64 type: 'applies-to',
65 }),
66 rekall.semantic.createRelationship({
67 sourceId: team[0].id, targetId: decisions[0].id,
68 type: 'proposed',
69 }),
70 ]);
71
72 console.log('Knowledge base built successfully');
73}
74
75buildProjectKnowledgeBase();

Incremental building

You do not need to build the entire knowledge base at once. Entities and relationships can be added incrementally as your agent learns about the project. Use upsert: true to avoid duplicates when creating entities that may already exist.

Next Steps

Rekall
rekall