Skip to main content

Fact Integration

Info

Last Updated: 2026-01-13

Facts Throughout the System

Facts are automatically integrated into recall(), search results, and memory enrichment. This page covers advanced patterns for working with extracted facts.

Tip

v0.30.0: Facts now support semantic search via embeddings. When an embedding is available in recall(), facts are searched by semantic similarity, not just keywords.

How Embeddings Work in Batteries-Included Mode

v0.30.0+: Configure embedding once at SDK initialization for batteries-included semantic search:

import { Cortex } from '@cortexmemory/sdk';

const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
// Configure embedding provider - batteries included!
embedding: {
provider: 'openai',
apiKey: process.env.OPENAI_API_KEY,
model: 'text-embedding-3-small', // optional, this is the default
},
});

// Now every recall() automatically:
// 1. Generates an embedding for the query
// 2. Uses semantic search for both memories AND facts
// No manual embedding code needed!
const result = await cortex.memory.recall({
memorySpaceId: 'user-space',
query: "What are the user's preferences?",
// Embedding is auto-generated from the query!
});

// remember() also auto-generates embeddings for facts
await cortex.memory.remember({
memorySpaceId: 'user-space',
userMessage: "I prefer dark mode",
agentResponse: "Got it!",
// Facts extracted are automatically given embeddings
});

You can also use environment variables for zero-config setup:

# Set these env vars
export CORTEX_EMBEDDING=true
export OPENAI_API_KEY=sk-...
// SDK auto-configures embedding from env vars!
const cortex = await Cortex.create({
convexUrl: process.env.CONVEX_URL!,
});
Looking for Extraction?

See Fact Extraction for how to configure automatic or custom fact extraction from conversations.


Using Facts in Retrieval

recall() Includes Facts Automatically

recall() searches facts as a primary source, not just enrichment. No extra configuration needed.

// With embedding - uses semantic search for facts (recommended)
const result = await cortex.memory.recall({
memorySpaceId: 'user-space',
query: "What are the user's preferences?",
embedding: await embed("What are the user's preferences?"), // Enables semantic fact search
});

// Facts included automatically in sources
console.log(`Found ${result.sources.facts?.items.length || 0} facts`);

result.sources.facts?.items.forEach(fact => {
console.log(`- ${fact.fact} (${fact.confidence}% confidence)`);
});

// LLM-ready context includes facts
console.log(result.context);
// "## Known Facts
// - User prefers dark mode (95% confidence)
// - User likes TypeScript (88% confidence)
//
// ## Recent Memories
// ..."
Info

v0.30.0+: When embedding is provided, facts are searched semantically—meaning "What colors does the user like?" can find "User prefers purple" even without the word "color" in the fact.

Filter Facts in recall()

// Get only high-confidence facts
const result = await cortex.memory.recall({
memorySpaceId: 'user-space',
query: 'user preferences',
sources: {
facts: {
minConfidence: 80,
factType: 'preference',
isSuperseded: false, // Current beliefs only
},
},
});

Direct Fact Operations

await cortex.facts.store({
memorySpaceId: 'user-space',
userId: 'user-123',
fact: 'User prefers TypeScript over JavaScript',
factType: 'preference',
subject: 'user-123',
predicate: 'language_preference',
object: 'TypeScript',
confidence: 90,
sourceType: 'conversation',
tags: ['coding', 'preferences'],
});

Fact Types

ParameterTypeRequiredDefaultDescription
preferenceFactTypeNoUser likes/dislikes something (e.g., 'User prefers dark mode')
identityFactTypeNoWho someone is (e.g., 'User is a software engineer')
knowledgeFactTypeNoSomething the user knows (e.g., 'User knows Python')
relationshipFactTypeNoConnection between entities (e.g., 'User works_at Google')
eventFactTypeNoSomething that happened (e.g., 'User joined on 2025-01-15')
observationFactTypeNoSystem-observed behavior (e.g., 'User logs in daily')

Fact Versioning

Facts are Versioned

When a fact is updated or superseded via belief revision, previous versions are preserved for audit trails.

// Get complete version history
const history = await cortex.facts.getHistory('user-space', factId);

history.forEach(version => {
console.log(`v${version.version}: ${version.fact}`);
console.log(` Confidence: ${version.confidence}%`);
console.log(` Updated: ${new Date(version.updatedAt).toISOString()}`);
});

// Get supersession chain (evolution of belief)
const chain = await cortex.facts.getSupersessionChain(factId);
// Returns: [oldest] -> [older] -> [current]

chain.forEach((entry, i) => {
console.log(`${i + 1}. ${entry.fact}`);
if (entry.supersededBy) {
console.log(` Superseded by: ${entry.supersededBy}`);
}
});

Best Practices

Extract Atomic Facts
// Bad: Compound fact
{ fact: 'User is 25 years old from California and likes hiking' }

// Good: Atomic facts
[
{ fact: 'User is 25 years old', factType: 'identity' },
{ fact: 'User is from California', factType: 'identity' },
{ fact: 'User likes hiking', factType: 'preference' },
]
Use Consistent Subject IDs
// Always use same format for subject
extractFacts: async (userMsg, agentResp) => [{
fact: 'User prefers email notifications',
subject: userId, // Consistent ID
confidence: 90,
}],
Tag for Organization
{
fact: 'User speaks English and Spanish',
factType: 'knowledge',
tags: ['language', 'communication', 'multilingual'],
}

Next Steps