Example
Research assistant
Import several sources with provenance, retrieve precise evidence, and graft broader research context for synthesis.
Estimated time: 15 minutes
Level: Advanced
Overview
This example ingests each research source into its own explicit session with source and project tags. It uses tagged recall for precise evidence and graftByRelevance() for broader context from a selected source session.
What this demonstrates
Source-scoped document ingestion.
Project-wide tagged evidence retrieval.
Precise fact recall versus broader topic grafting.
Source provenance and conflicting claims.
Token and similarity controls for research prompts.
Architecture
Source documents
Tagged source sessions
Evidence recall
Bounded synthesis
Memory design
One explicit session per source document.
Stable tags such as
project:retrieval-study and source:paper-42.Source metadata using the application’s canonical source ID.
Memory types for claims, insights, questions, tasks, and references.
Application-owned citation metadata outside generated model prose.
Project structure
files
src/
config.ts
ingest-source.ts
recall-evidence.ts
build-context.ts
research-example.tsStep 1: Ingest sources
src/ingest-source.ts
await memo.ingestText(paperText, "paper-42", {
label: "Paper 42",
source: "doi:10.1000/example-42",
tags: ["project:retrieval-study", "source:paper-42"],
});
await memo.ingestText(reportText, "report-17", {
label: "Industry report 17",
source: "report:17",
tags: ["project:retrieval-study", "source:report-17"],
});Step 2: Recall precise evidence
src/recall-evidence.ts
const evidence = await reader.recall(
"What evidence describes retrieval quality?",
{
tags: ["project:retrieval-study"],
scope: "tagged",
limit: 12,
minSimilarity: 0.5,
tokenBudget: 1400,
},
);
console.table(
evidence.facts.map((fact) => ({
value: fact.value,
source: fact.source,
confidence: fact.confidence,
similarity: fact.similarity,
})),
);Step 3: Build broader source context
Recall searches atomic memories across authorized tagged sources. Grafting operates on broader topic context within the explicit source session passed to the core API.
src/build-context.ts
const paperContext = await memo.graftByRelevance(
"paper-42",
"retrieval evaluation method and limitations",
{
topK: 4,
minSimilarity: 0.55,
hopDepth: 1,
},
);
console.log(paperContext.systemPrompt);Complete example
src/research-example.ts
import "dotenv/config";
import {
MemoGrafter,
MemoGrafterAgent,
OpenAIEmbedAdapter,
OpenAILLMAdapter,
} from "memo-grafter";
const llm = new OpenAILLMAdapter("gpt-4o");
const config = {
db: { connectionString: process.env.DATABASE_URL! },
llm,
embedder: new OpenAIEmbedAdapter("text-embedding-3-small"),
};
const memo = new MemoGrafter(config);
const reader = new MemoGrafterAgent(config);
await memo.initialize();
await reader.initialize();
const paperText = [
"Confidence-weighted retrieval improved precision in the evaluation.",
"The study used a small benchmark and requires broader validation.",
].join(" ");
const reportText = [
"The industry report found lower latency with cached vector search.",
"Its results did not measure answer quality.",
].join(" ");
try {
await memo.ingestText(paperText, "paper-42", {
source: "doi:10.1000/example-42",
tags: ["project:retrieval-study", "source:paper-42"],
});
await memo.ingestText(reportText, "report-17", {
source: "report:17",
tags: ["project:retrieval-study", "source:report-17"],
});
const evidence = await reader.recall("evidence about retrieval quality", {
tags: ["project:retrieval-study"],
scope: "tagged",
limit: 12,
tokenBudget: 1400,
});
const synthesis = await llm.complete(
[{ role: "user", content: "Summarize the evidence and disagreements." }],
evidence.systemPrompt,
);
console.log(synthesis);
} finally {
await Promise.all([memo.close(), reader.close()]);
}Expected behavior
Each source produces independently traceable topics and memories.
Tagged recall can return relevant active facts from both authorized source sessions.
The synthesis prompt contains bounded fact blocks rather than entire source documents.
Conflicting extracted claims can remain visible until maintenance or application review classifies them.
What gets stored
Raw source text in its explicit source session.
Topic labels and historical summaries for source sections.
Atomic claims, insights, questions, tasks, or references.
Embedding vectors used for topic and memory similarity.
Source metadata and project tags on created graph records.
Citations and provenance
MemoGrafter preserves source metadata, but the application remains responsible for mapping recalled facts to authoritative citations and displaying them accurately. Do not ask the model to invent citation details from memory text.
Store canonical source IDs in application data and ingestion metadata.
Carry source IDs alongside recalled facts.
Open the original source before quoting or making a high-stakes claim.
Treat generated summaries as navigation aids, not primary evidence.
Inspect it in Studio
Open each source session and review its topic segmentation.
Confirm source metadata and project tags on topic and memory nodes.
Use Prompt Preview for the evidence query.
Inspect conflicting or superseded memory edges when sources disagree.
Compare included evidence with the original source before tuning thresholds.
Common mistakes
Ingesting every source into one undifferentiated session.
Using generated summaries as verbatim citations.
Increasing
limit without respecting the token budget.Ignoring source and tenant authorization during tagged recall.
Assuming two different claims are automatically resolved by recency.
Extensions
Add a source-review UI backed by graph snapshots.
Run crawler maintenance to annotate explicit updates and conflicts.
Graft selected research topics into a separate writing agent.
Evaluate retrieval precision against a labeled research-question set.