Skip to documentation
Docs navigation
Docs/Research assistant
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.ts

Step 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.