back to work

2025 — 2026

Agentic Research Assistant

A LangGraph agent that works out for itself whether a question needs live data, then reaches YouTube and Reddit through an MCP server it calls mid-conversation.

View source ↗
LangGraphFastMCPTool CallingAgentsSQLiteStreamlit

The problem

A chatbot that searches on every turn is slow and wasteful, because plenty of questions don't need anything fetched. A chatbot with no tools at all is stale. The part I wanted to get right was the decision in between: on this turn, does this question need live data, and if so, from where?

Architecture

tooldirectresultsstateUser TurnAgent NodeLangGraphConditional Edgetool or answer?FastMCP ServerYouTube ToolReddit ToolResponseSQLite Memorycheckpoint
  1. 01

    The graph puts the agent at the centre, with a conditional edge sending each turn either straight to a response or out to the tool node.

  2. 02

    YouTube and Reddit search sit behind a FastMCP server as MCP tools, rather than being hardcoded into the agent.

  3. 03

    Tool results come back into agent state, so the model reasons over what it fetched instead of just relaying it.

  4. 04

    Session memory is checkpointed to SQLite, so conversation context survives across turns.

Decisions that mattered

MCP as the tool boundary instead of in-process functions

Writing search as plain Python functions inside the agent is quicker, and it locks the capability into that one app. Putting it behind a FastMCP server makes the boundary a protocol instead: any MCP client can use the same YouTube and Reddit tools, and I can rewrite the agent without touching them. It's more setup than one project strictly needs, which is rather the point of doing it.

Let the model make the routing decision

The easy version is a keyword rule: if the question mentions Reddit, call Reddit. That falls over on anything indirect, like asking what people are complaining about. Handing the decision to the model through a conditional edge covers those cases, and it also skips the tool call when the answer is already sitting in context, so latency and API spend track what the turn actually needs.

Persistent state, not a message buffer

Follow-up questions in research usually depend on something retrieved two turns earlier. Checkpointing the graph state to SQLite means those resolve against everything gathered so far in the session, instead of starting from nothing each time.

Stack

Orchestration
LangGraphConditional EdgesState Checkpointing
Tools
FastMCPYouTube APIReddit API
Interface
StreamlitSQLite