Overview
The @deepagents/retrieval package provides a local-first RAG (Retrieval-Augmented Generation) system. It ingests content from various sources, creates vector embeddings using FastEmbed, and enables semantic search over documents.
Installation
npm install @deepagents/retrieval
Built-in Features:
FastEmbed for local embeddings (no API keys required)
SQLite-vec for vector storage
Multiple connectors (GitHub, RSS, PDF, local files)
Markdown and text chunking
Quick Example
import {
FastEmbed ,
SqliteStore ,
ingest ,
similaritySearch ,
} from '@deepagents/retrieval' ;
import { githubConnector } from '@deepagents/retrieval/connectors' ;
const embedder = new FastEmbed ();
const store = new SqliteStore ( './vectors.db' );
// Ingest documentation
await ingest ({
connector: githubConnector ({
owner: 'JanuaryLabs' ,
repo: 'deepagents' ,
path: 'packages' ,
}),
store ,
embedder ,
});
// Semantic search
const results = await similaritySearch ({
query: 'How do agent handoffs work?' ,
store ,
embedder ,
limit: 5 ,
});
for ( const result of results ) {
console . log ( 'Content:' , result . content );
console . log ( 'Similarity:' , result . similarity );
console . log ( 'Metadata:' , result . metadata );
console . log ( '---' );
}
Core API
ingest(config)
Ingest content and create embeddings:
interface IngestConfig {
connector : Connector ; // Content source
store : VectorStore ; // Storage backend
embedder : Embedder ; // Embedding model
chunkSize ?: number ; // Chunk size (default: 512)
chunkOverlap ?: number ; // Overlap (default: 50)
}
await ingest ({
connector: localFilesConnector ( './docs' ),
store: sqliteStore ,
embedder: fastEmbed ,
chunkSize: 1000 ,
chunkOverlap: 100 ,
});
similaritySearch(config)
Search for similar documents:
interface SearchConfig {
query : string ; // Search query
store : VectorStore ; // Vector store
embedder : Embedder ; // Embedding model
limit ?: number ; // Results (default: 10)
threshold ?: number ; // Min similarity (0-1)
}
const results = await similaritySearch ({
query: 'authentication best practices' ,
store ,
embedder ,
limit: 3 ,
threshold: 0.7 ,
});
Returns:
interface SearchResult {
id : string ;
content : string ;
similarity : number ; // 0-1 (higher = more similar)
metadata : Record < string , any >;
}
Embedders
FastEmbed
Local embedding generation (no API required):
import { FastEmbed } from '@deepagents/retrieval' ;
const embedder = new FastEmbed ({
model: 'BAAI/bge-small-en-v1.5' , // Default
});
// Embed text
const vector = await embedder . embed ( 'Your text here' );
console . log ( vector . length ); // 384 dimensions
// Batch embedding
const vectors = await embedder . embedBatch ([
'First document' ,
'Second document' ,
'Third document' ,
]);
Available Models:
BAAI/bge-small-en-v1.5 (default, 384 dims)
BAAI/bge-base-en-v1.5 (768 dims)
sentence-transformers/all-MiniLM-L6-v2 (384 dims)
FastEmbed runs locally and doesn’t require API keys or internet access after initial model download.
Vector Stores
SqliteStore
SQLite-based vector storage with SQLite-vec extension:
import { SqliteStore } from '@deepagents/retrieval' ;
const store = new SqliteStore ( './vectors.db' );
// Insert vectors
await store . insert ({
id: 'doc1' ,
vector: [ 0.1 , 0.2 , 0.3 , ... ],
content: 'Document text' ,
metadata: { source: 'github' , path: 'README.md' },
});
// Search
const results = await store . search ( queryVector , { limit: 10 });
// Delete
await store . delete ( 'doc1' );
// Close
store . close ();
NodeSqliteStore
Node.js-specific SQLite implementation:
import { NodeSqliteStore } from '@deepagents/retrieval' ;
const store = new NodeSqliteStore ( './vectors.db' );
Connectors
Content sources for ingestion.
GitHub Connector
Ingest from GitHub repositories:
import { githubConnector } from '@deepagents/retrieval/connectors' ;
const connector = githubConnector ({
owner: 'JanuaryLabs' ,
repo: 'deepagents' ,
path: 'packages/agent' , // Optional: specific path
branch: 'main' , // Optional: branch
token: process . env . GITHUB_TOKEN , // Optional: for private repos
});
await ingest ({ connector , store , embedder });
Local Files Connector
Ingest local files:
import { localFilesConnector } from '@deepagents/retrieval/connectors' ;
const connector = localFilesConnector ( './docs' , {
extensions: [ '.md' , '.txt' , '.mdx' ],
ignore: [ 'node_modules' , '.git' ],
});
await ingest ({ connector , store , embedder });
PDF Connector
Extract and ingest PDF documents:
import { pdfConnector } from '@deepagents/retrieval/connectors' ;
const connector = pdfConnector ( './documents/*.pdf' );
await ingest ({ connector , store , embedder });
Ingest from RSS feeds:
import { rssConnector } from '@deepagents/retrieval/connectors' ;
const connector = rssConnector ( 'https://blog.example.com/rss' );
await ingest ({ connector , store , embedder });
Linear Connector
Ingest Linear issues:
import { linearConnector } from '@deepagents/retrieval/connectors' ;
const connector = linearConnector ({
apiKey: process . env . LINEAR_API_KEY ,
teamId: 'team_123' ,
});
await ingest ({ connector , store , embedder });
Chunking Strategies
Markdown Splitter
Split by markdown structure:
import { MarkdownTextSplitter } from '@deepagents/retrieval' ;
const splitter = new MarkdownTextSplitter ({
chunkSize: 1000 ,
chunkOverlap: 100 ,
});
const chunks = await splitter . split ( markdownText );
Recursive Character Splitter
General-purpose text splitting:
import { RecursiveCharacterTextSplitter } from '@deepagents/retrieval' ;
const splitter = new RecursiveCharacterTextSplitter ({
chunkSize: 500 ,
chunkOverlap: 50 ,
separators: [ ' \n\n ' , ' \n ' , '. ' , ' ' ],
});
const chunks = await splitter . split ( text );
Complete Example
RAG-Powered Agent
import { agent , execute } from '@deepagents/agent' ;
import { openai } from '@ai-sdk/openai' ;
import { tool } from 'ai' ;
import { z } from 'zod' ;
import {
FastEmbed ,
SqliteStore ,
ingest ,
similaritySearch ,
} from '@deepagents/retrieval' ;
import { githubConnector } from '@deepagents/retrieval/connectors' ;
// Setup
const embedder = new FastEmbed ();
const store = new SqliteStore ( './kb.db' );
// Ingest documentation once
await ingest ({
connector: githubConnector ({
owner: 'JanuaryLabs' ,
repo: 'deepagents' ,
}),
store ,
embedder ,
});
// Create search tool
const searchTool = tool ({
description: 'Search the knowledge base' ,
parameters: z . object ({
query: z . string (). describe ( 'Search query' ),
}),
execute : async ({ query }) => {
const results = await similaritySearch ({
query ,
store ,
embedder ,
limit: 3 ,
});
return results . map ( r => ({
content: r . content ,
similarity: r . similarity ,
}));
},
});
// Create RAG agent
const ragAgent = agent ({
name: 'rag_agent' ,
model: openai ( 'gpt-4o' ),
prompt: 'You answer questions using the knowledge base. Always search first.' ,
tools: { search: searchTool },
});
// Query
const stream = execute (
ragAgent ,
'How do I create an agent with handoffs?' ,
{}
);
for await ( const chunk of stream . textStream ) {
process . stdout . write ( chunk );
}
Advanced Usage
Custom Content ID
Generate unique IDs for content:
import { contentId } from '@deepagents/retrieval' ;
const id = contentId ( 'https://example.com/page' , 'Page content' );
console . log ( id ); // Hash-based ID
Filter search results by metadata:
const results = await store . search ( queryVector , {
limit: 10 ,
filter : ( metadata ) => {
return metadata . source === 'github' && metadata . language === 'typescript' ;
},
});
Incremental Updates
Update specific documents:
// Delete old version
await store . delete ( 'doc1' );
// Insert new version
const vector = await embedder . embed ( newContent );
await store . insert ({
id: 'doc1' ,
vector ,
content: newContent ,
metadata: { updated: new Date (). toISOString () },
});
Best Practices
Chunk Size Use 500-1000 characters for semantic coherence
Overlap 10-20% overlap preserves context across chunks
Metadata Include source, date, author for filtering
Reranking Use top 10-20 results, rerank with LLM if needed
Updates Reingest changed content periodically
Similarity Threshold Start with 0.7, adjust based on results
Batch Embeddings : Use embedBatch() for multiple texts
Index Size : SQLite-vec handles millions of vectors efficiently
Search Limit : Keep under 20 for fast results
Chunking : Smaller chunks = more granular search, larger = more context
Package Info
@deepagents/agent Build RAG-powered agents
@deepagents/toolbox Use retrieval in agent tools