Reference Implementationsintermediate
Research
semantic-search
Index documents and search by semantic similarity. The RAG foundation.
APIs Used
ctx.llm.embed()ctx.memory.persistentCapabilities Required
research/semantic-searchresearch/index-documentsWhat this demonstrates
- 1ctx.llm.embed() to generate vector embeddings for documents and queries
- 2ctx.memory.persistent.setVector() to store embeddings in the vector store
- 3ctx.memory.persistent.search() for similarity-ranked retrieval
- 4Dual-action pattern: action="index" to store, action="search" to query
- 5Foundation for RAG (retrieval-augmented generation) pipelines
Source
View on GitHubtypescript
/** * Semantic Search - Production Reference Agent * * Canon alignment: KB 105 (Agent SDK), KB 22 (HumanOS) * Demonstrates: ctx.llm.embed, ctx.memory.vector (persistent.setVector/search), ctx.files, ctx.provenance * * Real use case: Index documents into a vector store, then search by semantic * similarity. This is the foundation pattern for RAG (retrieval-augmented * generation). Useful for knowledge bases, support systems, and any * application where users search by meaning rather than keywords. */
import { handler, withProvenanceContext } from '@human/agent-sdk';import type { ExecutionContext } from '@human/agent-sdk';
export const AGENT_ID = 'semantic-search';export const VERSION = '1.0.0';export const CAPABILITIES = ['research/semantic-search', 'research/index-documents'];
export interface SemanticSearchInput { /** Action: 'index' to store documents, 'search' to query */ action: 'index' | 'search'; /** Documents to index (for action='index') */ documents?: Array<{ path: string; metadata?: Record<string, unknown> }>; /** Search query (for action='search') */ query?: string; /** Number of results to return */ top_k?: number; /** Minimum similarity threshold (0-1) */ threshold?: number;}
export interface SemanticSearchOutput { success: boolean; /** Number of documents indexed (for action='index') */ indexed_count?: number; /** Search results (for action='search') */ results?: Array<{ key: string; score: number; metadata?: Record<string, unknown>; }>; provenance_id: string;}
const execute = async ( ctx: ExecutionContext, input: SemanticSearchInput): Promise<SemanticSearchOutput> => { ctx.log.info('Semantic search agent invoked', { action: input.action });
if (input.action === 'index') { return indexDocuments(ctx, input); } else { return searchDocuments(ctx, input); }};
/** * Index documents: read files, generate embeddings, store in vector memory */async function indexDocuments( ctx: ExecutionContext, input: SemanticSearchInput): Promise<SemanticSearchOutput> { const documents = input.documents ?? []; let indexedCount = 0;
for (const doc of documents) { // Read document content (ctx.files) const content = await ctx.files.readText(doc.path);
// Generate embedding (ctx.llm.embed) - the key gap feature const embedding = await ctx.llm.embed(content);
// Store in vector memory (ctx.memory.persistent.setVector) - the other key gap feature const vectorKey = `doc:${doc.path}`; await ctx.memory.persistent.setVector(vectorKey, embedding.vector, { path: doc.path, dimensions: embedding.dimensions, model: embedding.model, indexed_at: new Date().toISOString(), ...doc.metadata, });
ctx.log.info('Indexed document', { path: doc.path, dimensions: embedding.dimensions, cost_usd: embedding.cost.usd, });
indexedCount++; }
const provenanceId = await ctx.provenance.log( withProvenanceContext(ctx, { action: 'semantic_search:indexed', status: 'success', input: { document_count: documents.length }, output: { indexed_count: indexedCount }, }) );
return { success: true, indexed_count: indexedCount, provenance_id: provenanceId, };}
/** * Search documents: embed query, search vector memory, return ranked results */async function searchDocuments( ctx: ExecutionContext, input: SemanticSearchInput): Promise<SemanticSearchOutput> { const query = input.query ?? ''; const topK = input.top_k ?? 5; const threshold = input.threshold ?? 0.5;
if (!query) { ctx.log.warn('Empty search query'); const provenanceId = await ctx.provenance.log( withProvenanceContext(ctx, { action: 'semantic_search:empty_query', status: 'success', input: { query: '' }, output: { results: [] }, }) ); return { success: true, results: [], provenance_id: provenanceId }; }
// Generate embedding for query (ctx.llm.embed) const queryEmbedding = await ctx.llm.embed(query);
// Search vector memory (ctx.memory.persistent.search) const searchResults = await ctx.memory.persistent.search( queryEmbedding.vector, { topK, threshold, includeMetadata: true, } );
const results = searchResults.map((r) => ({ key: r.key, score: r.score, metadata: r.metadata, }));
ctx.log.info('Search completed', { query, result_count: results.length, top_score: results[0]?.score ?? 0, });
const provenanceId = await ctx.provenance.log( withProvenanceContext(ctx, { type: 'semantic_search:searched', status: 'success', metadata: { input: { query, top_k: topK, threshold }, output: { result_count: results.length } }, }) );
return { success: true, results, provenance_id: provenanceId, };}
export default handler({ name: AGENT_ID, id: AGENT_ID, version: VERSION, capabilities: CAPABILITIES, description: 'Index documents and search by semantic similarity (RAG foundation)', manifest: { operations: [ { name: 'index', description: 'Index documents into vector store for semantic search', paramsSchema: { action: { type: 'string', required: true, description: "Must be 'index'" }, documents: { type: 'array', description: 'Documents with path and optional metadata' }, }, resultKind: 'agent.semantic-search.index-result', }, { name: 'search', description: 'Search indexed documents by semantic similarity', paramsSchema: { action: { type: 'string', required: true, description: "Must be 'search'" }, query: { type: 'string', description: 'Search query' }, top_k: { type: 'number', description: 'Number of results' }, threshold: { type: 'number', description: 'Minimum similarity (0-1)' }, }, resultKind: 'agent.semantic-search.search-result', }, ], }, execute,});Run the tests
From monorepo root
$ pnpm test:agents:reference
$ pnpm test:agents:reference:verbose
The reference suite runs all 23 agents with createMockExecutionContext(), verifying every ctx.* API call and output shape.
See Also
SDK Reference