Knowledge Management
How ElizaOS manages agent knowledge, facts, and document processing for intelligent context retrieval with actual implementation details
Knowledge Management
ElizaOS knowledge management system provides agents with the ability to store, organize, and retrieve structured knowledge. This includes facts about users, documents, and domain-specific information that can be used to enhance conversations and decision-making.
Modern Approach: Plugin-Knowledge
The recommended way to implement knowledge management is through the @elizaos/plugin-knowledge
plugin, which provides a complete RAG (Retrieval-Augmented Generation) solution:
Installation and Setup
// In your character configuration
const character = {
name: "KnowledgeAgent",
plugins: [
"@elizaos/plugin-sql", // Required first
"@elizaos/plugin-openai", // Or other AI provider
"@elizaos/plugin-knowledge", // Knowledge management
"@elizaos/plugin-bootstrap" // Required last
]
};
Using Plugin-Knowledge Service
// Get the knowledge service
const knowledgeService = runtime.getService('knowledge');
// Add knowledge programmatically
await knowledgeService.addKnowledge({
content: "ElizaOS is an open-source AI agent framework",
contentType: "text/plain",
metadata: {
source: "documentation",
tags: ["framework", "ai"]
}
});
// Add PDF document
const pdfContent = await fs.readFile('path/to/document.pdf');
await knowledgeService.addKnowledge({
content: pdfContent,
contentType: "application/pdf",
metadata: {
source: "company-handbook.pdf"
}
});
// Search knowledge base
const results = await knowledgeService.searchKnowledge({
query: "What is ElizaOS?",
limit: 5,
threshold: 0.7
});
Automatic Document Loading
Place documents in a docs
folder relative to your agent, and they'll be automatically loaded:
my-agent/
├── package.json
├── character.json
└── docs/
├── product-manual.pdf
├── faq.md
└── knowledge-base.txt
Web Interface
Plugin-Knowledge includes a web interface for document management. Access it at http://localhost:3000/knowledge
when your agent is running.
Core Memory-Based Approach
While plugin-knowledge is recommended for most use cases, ElizaOS also supports direct memory-based knowledge management for custom implementations.
Knowledge Types
Knowledge Item Structure
interface KnowledgeItem {
id: UUID;
content: Content;
metadata?: MemoryMetadata;
}
enum KnowledgeScope {
SHARED = "shared", // Accessible across agents
PRIVATE = "private", // Agent-specific knowledge
}
Adding Knowledge
Character Knowledge
Knowledge can be defined in the agent's character configuration:
const character = {
name: "Assistant",
knowledge: [
// Direct knowledge items
{
text: "The company was founded in 2020",
tags: ["company", "history"],
},
{
text: "Our main product is an AI platform",
tags: ["product", "business"],
},
// Reference to knowledge files
"path/to/knowledge-base.json",
// Directory of knowledge files
{
directory: "knowledge/domain-specific",
shared: true, // Make available to all agents
},
],
};
Runtime Knowledge Addition
import { MemoryType } from "@elizaos/core";
import { v4 as generateUUID } from "uuid";
// Add a single knowledge item as a fact memory
await runtime.createMemory(
{
id: generateUUID(),
entityId: userId,
roomId: roomId,
content: {
text: "The user prefers morning meetings",
},
metadata: {
type: MemoryType.DESCRIPTION,
source: "user_preference",
tags: ["preferences", "scheduling"],
},
},
"facts"
);
// Bulk knowledge import
const knowledgeItems = [
{ content: { text: "Fact 1" } },
{ content: { text: "Fact 2" } },
{ content: { text: "Fact 3" } },
];
for (const item of knowledgeItems) {
await runtime.createMemory(
{
...item,
entityId: userId,
roomId: roomId,
metadata: {
type: MemoryType.DESCRIPTION,
source: "bulk_import",
},
},
"facts"
);
}
Knowledge Processing
Document Processing
Large documents are automatically chunked and embedded:
async function processKnowledgeDocument(filePath: string) {
const content = await fs.readFile(filePath, "utf-8");
const documentId = generateUUID();
// Create main document entry
await runtime.createMemory(
{
content: {
text: path.basename(filePath),
fullText: content,
source: filePath,
},
metadata: {
type: MemoryType.DOCUMENT,
source: "filesystem",
timestamp: Date.now(),
},
},
"documents"
);
// Process chunks for semantic search
const chunks = chunkDocument(content);
for (let i = 0; i < chunks.length; i++) {
const chunk = chunks[i];
const embedding = await runtime.useModel(ModelType.TEXT_EMBEDDING, {
text: chunk.text,
});
await runtime.createMemory(
{
content: { text: chunk.text },
embedding,
metadata: {
type: MemoryType.FRAGMENT,
documentId,
position: i,
source: filePath,
},
},
"fragments"
);
}
}
Knowledge Extraction
Extract structured knowledge from text:
class KnowledgeExtractor {
async extractFacts(text: string): Promise<KnowledgeItem[]> {
// Use LLM to extract facts
const extraction = await runtime.useModel(ModelType.TEXT_COMPLETION, {
prompt: `Extract key facts from the following text as JSON array:
Text: ${text}
Format each fact as: { "fact": "...", "confidence": 0.0-1.0, "tags": [] }`,
});
const facts = JSON.parse(extraction);
return facts.map((f) => ({
id: generateUUID(),
content: { text: f.fact },
metadata: {
type: MemoryType.DESCRIPTION,
confidence: f.confidence,
tags: f.tags,
},
}));
}
}
Knowledge Retrieval
Facts Provider
The built-in facts provider retrieves relevant knowledge:
const factsProvider: Provider = {
name: "FACTS",
get: async (runtime, message, state) => {
// Get recent facts about the user
const userFacts = await runtime.getMemories({
entityId: message.entityId,
tableName: "facts",
count: 10,
unique: true,
});
// Search for relevant facts based on message
const relevantFacts = await runtime.searchMemories({
query: message.content.text,
tableName: "facts",
count: 5,
match_threshold: 0.7,
});
const facts = [...userFacts, ...relevantFacts].map((f) => f.content.text).join("\n");
return {
values: { facts: facts.split("\n") },
text: facts,
};
},
};
Semantic Knowledge Search
// Search for specific knowledge
const results = await runtime.searchMemories({
query: "What are the company policies on remote work?",
tableName: "documents",
count: 3,
match_threshold: 0.8,
});
// Get knowledge with specific tags
const taggedKnowledge = await runtime
.getMemories({
tableName: "facts",
count: 50,
})
.then((memories) => memories.filter((m) => m.metadata?.tags?.includes("policy")));
Knowledge Organization
Hierarchical Knowledge
Organize knowledge in hierarchical structures:
interface KnowledgeHierarchy {
topic: string;
subtopics: KnowledgeHierarchy[];
facts: KnowledgeItem[];
}
class KnowledgeOrganizer {
async buildHierarchy(domain: string): Promise<KnowledgeHierarchy> {
// Get all facts for domain
const facts = await runtime
.getMemories({
tableName: "facts",
count: 1000,
})
.then((memories) => memories.filter((m) => m.metadata?.tags?.includes(domain)));
// Group by subtopics
const grouped = this.groupByTags(facts);
return {
topic: domain,
subtopics: this.buildSubtopics(grouped),
facts: facts.map((f) => ({
id: f.id,
content: f.content,
metadata: f.metadata,
})),
};
}
}
Knowledge Graphs
Create relationships between knowledge items:
// Create knowledge relationships
await runtime.createRelationship({
sourceEntityId: fact1Id,
targetEntityId: fact2Id,
tags: ["related", "prerequisite"],
metadata: {
relationshipType: "requires",
strength: 0.8,
},
});
// Query related knowledge
async function getRelatedKnowledge(factId: UUID) {
const relationships = await runtime.getRelationships({
entityId: factId,
tags: ["related"],
});
const relatedFacts = await Promise.all(
relationships.map((r) => runtime.getMemoryById(r.targetEntityId))
);
return relatedFacts.filter(Boolean);
}
Knowledge Caching
Cache Frequently Used Knowledge
const KNOWLEDGE_CACHE_PREFIX = CacheKeyPrefix.KNOWLEDGE;
async function getCachedKnowledge(key: string): Promise<any> {
const cacheKey = `${KNOWLEDGE_CACHE_PREFIX}:${key}`;
// Check cache first
const cached = await runtime.getCache(cacheKey);
if (cached) return cached;
// Load and cache knowledge
const knowledge = await loadKnowledge(key);
await runtime.setCache(cacheKey, knowledge);
return knowledge;
}
Embedding Cache
Cache embeddings for faster retrieval:
async function getCachedEmbedding(text: string): Promise<number[]> {
const cached = await runtime.getCachedEmbeddings({
query_table_name: "knowledge_embeddings",
query_input: text,
query_field_name: "text",
query_field_sub_name: "content",
query_match_count: 1,
query_threshold: 0.99, // Very high threshold for exact matches
});
if (cached.length > 0) {
return cached[0].embedding;
}
// Generate new embedding
return await runtime.useModel(ModelType.TEXT_EMBEDDING, { text });
}
Best Practices
1. Knowledge Validation
class KnowledgeValidator {
validateFact(fact: string): boolean {
// Check minimum length
if (fact.length < 10) return false;
// Check for actual content
if (fact.trim().split(" ").length < 3) return false;
// Check for placeholders
const placeholders = ["TODO", "FIXME", "XXX"];
if (placeholders.some((p) => fact.includes(p))) return false;
return true;
}
}
2. Knowledge Deduplication
async function deduplicateKnowledge() {
const allFacts = await runtime.getMemories({
tableName: "facts",
count: 10000,
});
const seen = new Map<string, Memory>();
const duplicates: UUID[] = [];
for (const fact of allFacts) {
const normalized = fact.content.text.toLowerCase().trim();
if (seen.has(normalized)) {
duplicates.push(fact.id!);
} else {
seen.set(normalized, fact);
}
}
if (duplicates.length > 0) {
await runtime.deleteManyMemories(duplicates);
}
}
3. Knowledge Confidence
Track confidence levels for facts:
interface ConfidentKnowledge extends KnowledgeItem {
confidence: number;
source: string;
verifiedAt?: number;
}
async function addConfidentKnowledge(
text: string,
confidence: number,
source: string,
entityId: UUID,
roomId: UUID
) {
await runtime.createMemory(
{
id: generateUUID(),
entityId,
roomId,
content: { text },
metadata: {
type: MemoryType.DESCRIPTION,
confidence,
source,
timestamp: Date.now(),
},
},
"facts"
);
}
Example: Domain Knowledge System
Here's a complete example of a domain knowledge system:
class DomainKnowledgeSystem {
constructor(
private runtime: IAgentRuntime,
private domain: string
) {}
async initialize() {
// Load base knowledge
await this.loadBaseKnowledge();
// Set up knowledge provider
this.runtime.registerProvider({
name: `${this.domain.toUpperCase()}_KNOWLEDGE`,
get: async (runtime, message) => {
const knowledge = await this.getRelevantKnowledge(message.content.text);
return {
values: {
[`${this.domain}Knowledge`]: knowledge,
},
text: knowledge.map((k) => k.content.text).join("\n"),
};
},
});
}
private async loadBaseKnowledge() {
const knowledgeDir = `knowledge/${this.domain}`;
const files = await fs.readdir(knowledgeDir);
for (const file of files) {
if (file.endsWith(".json")) {
const content = await fs.readFile(path.join(knowledgeDir, file), "utf-8");
const items = JSON.parse(content);
for (const item of items) {
await this.runtime.createMemory(
{
id: generateUUID(),
entityId: this.runtime.agentId,
roomId: this.runtime.agentId, // Use agent ID as room ID for shared knowledge
content: { text: item.text },
metadata: {
type: MemoryType.DESCRIPTION,
source: file,
tags: [this.domain, ...item.tags],
},
},
"facts"
);
}
}
}
}
async getRelevantKnowledge(query: string): Promise<Memory[]> {
// Get domain-specific knowledge
const domainKnowledge = await this.runtime.searchMemories({
query,
tableName: "facts",
count: 5,
match_threshold: 0.7,
});
// Filter by domain tag
return domainKnowledge.filter((k) => k.metadata?.tags?.includes(this.domain));
}
async updateKnowledge(factId: UUID, updates: Partial<Content>) {
const existing = await this.runtime.getMemoryById(factId);
if (!existing) throw new Error("Knowledge not found");
await this.runtime.updateMemory({
id: factId,
content: { ...existing.content, ...updates },
metadata: {
...existing.metadata,
updatedAt: Date.now(),
},
});
}
}
// Usage
const medicalKnowledge = new DomainKnowledgeSystem(runtime, "medical");
await medicalKnowledge.initialize();
Choosing the Right Approach
Use Plugin-Knowledge When:
- You need zero-configuration RAG capabilities
- Working with standard document formats (PDF, MD, TXT)
- Want automatic document indexing and search
- Need a web interface for document management
- Building conversational agents that answer questions from documents
Use Core Memory-Based Approach When:
- Building custom knowledge management systems
- Need fine-grained control over memory storage
- Implementing specialized knowledge graphs
- Working with structured data relationships
- Integrating with existing database schemas
Hybrid Approach
You can combine both approaches:
// Use plugin-knowledge for documents
const knowledgeService = runtime.getService('knowledge');
await knowledgeService.addKnowledge({
content: documentContent,
contentType: 'application/pdf'
});
// Use memory system for structured facts
await runtime.createMemory({
content: { text: "User prefers morning meetings" },
entityId: userId,
metadata: {
type: MemoryType.DESCRIPTION,
source: "user_preference"
}
}, "facts");
Related Topics
- Memory System - Core memory storage and retrieval
- State Management - Using knowledge in state composition
- Character Definition - Defining agent knowledge