4 min read

Agentic Technical Researcher

LangGraphTavilyDSPyFastAPIChromaDBLangfuse

Why I built this

LLMs hallucinate when asked to research. They fabricate citations, synthesize facts from thin air, and present opinion as evidence. I wanted to build a system that produces verifiable, sourced technical reports, the kind you’d trust enough to base engineering decisions on.

The key insight was decomposition: instead of one massive prompt that reasons and searches and writes, split the problem across specialized agents. A Planner generates search queries. A Reflector optimizes them. A Researcher executes them in parallel. A Synthesizer writes with inline citations. And a Critic, the most important piece, checks the report against the sources for hallucination, with the authority to send it back for revision.

The ChromaDB episodic memory was an unexpected win. After running hundreds of research jobs, I noticed common queries across runs. By short-circuiting the pipeline when a cached report exists (similarity >92%), we cut API costs by ~70% on repeated topics, turning a cost center into an efficiency gain.

Architecture

User Prompt → Planner (DSPy ChainOfThought)
           → Reflector (Query Optimizer)
           → Memory Retriever (ChromaDB)
                 — Cache Hit → Critic
                 — Cache Miss → Researcher (Tavily API, async parallel)
                             → Human Approval (Graph Interrupt)
                                   — Approved / Feedback → Synthesizer (Gemini Streaming)
                             → Critic (DSPy ChainOfThought)
                                   — Approved → Memory Writer (ChromaDB Persist) → End
                                   — Rejected → Guardrail (Revisions >= 3?)
                                         — Yes → End
                                         — No → back to Synthesizer

Key features

  1. Multi-agent orchestration — 8-node LangGraph state machine with conditional routing, cyclic revision loops, and native graph interrupts
  2. Programmatic prompts (DSPy) — Planner and Critic use DSPy ChainOfThought with typed Signatures, replacing brittle raw prompts with self-optimizing modules
  3. Episodic memory — ChromaDB vector store short-circuits repeated topics (>92% similarity), saving ~70% on API costs on common queries
  4. Human-in-the-loop — native LangGraph interrupts pause execution before synthesis; users review sources and can provide custom revision feedback
  5. Self-correction — DSPy Critic scores reports 1-10 and detects hallucination; routes back to synthesizer for revisions (max 3 loops)
  6. Async parallelizationasyncio.gather() executes all Tavily searches concurrently (~3x latency improvement)
  7. Full observability — Langfuse traces with custom scores (latency, tool success rate, critic revisions), structured logging with correlation IDs
  8. Four interfaces — CLI (research-agent), Streamlit UI, FastAPI REST API (SSE streaming), MCP Server (Claude Desktop integration)

Quick start

git clone https://github.com/YOURNAME/research-agent.git
cd research-agent

# With Docker (recommended)
docker compose up

# Or locally
pip install -e .
cp .env.example .env  # edit with your keys
research-agent research --topic "How does LangGraph state differ from standard memory?"

Visit http://localhost:8501 for the Streamlit UI, or http://localhost:8000/docs for Swagger API docs.

Environment variables

GEMINI_API_KEY=your_google_ai_studio_key
TAVILY_API_KEY=your_tavily_search_key
LANGFUSE_PUBLIC_KEY=     # optional – observability
LANGFUSE_SECRET_KEY=     # optional – observability
LANGFUSE_HOST=https://cloud.langfuse.com
LOG_LEVEL=INFO           # DEBUG, INFO, WARNING, ERROR

Performance

MetricValue
Avg. end-to-end latency~8s
Avg. latency (cached)~3s
Tool success rate>95%
API cost per run~$0.002
Test coverage66/66 passing
Supported Python3.11, 3.12

Tech stack

CategoryTechnology
OrchestrationLangGraph (state machine, checkpointing, interrupts)
LLM frameworkLangChain + DSPy
LLM providerGemini 3.1 Flash Lite Preview (OpenAI-compatible API)
Web searchTavily (async parallel)
Vector memoryChromaDB + SentenceTransformers (all-MiniLM-L6-v2)
ObservabilityLangfuse (traces, scores, dashboard)
BackendFastAPI + SSE streaming
FrontendStreamlit (3-phase UI)
InfrastructureDocker Compose, Render, GitHub Actions
Code qualityruff, mypy, pre-commit, pytest (66 tests)

Architecture decisions

Detailed, RFC-style Architecture Decision Records covering all major technology choices live in docs/adr/.

License

MIT

Back to top