Get in touch about this project
Hero image slot — reserved at 640 × 351, not yet published.

Institutional research is assembly work: pull the filings, pull the market data, pull the news, reconcile what disagrees, then write the note. Munshot is an agent that does the assembly — ten-plus sources behind one tool protocol, a fifteen-node graph deciding what to call and in what order, and an API that streams the work back while the run is still going.

  • 90%Research workflow timeStated as a 90% collapse in research workflow time. The baseline it is measured against is not described. Method, denominator and measurement window unspecified. · as of 1 Aug 2025
  • 99.5%Operational fault toleranceStated as 99.5% operational fault-tolerance. The source does not define the denominator or what counts as recovered. Method, denominator and measurement window unspecified. · as of 1 Aug 2025
  • 15Decision graph nodesNodes in the LangGraph decision graph, carrying more than twenty state keys between them. · as of 1 Aug 2025
  • 10+Tools behind one protocolCapabilities exposed through the MCP-compliant tool server: a vector store, a general model, a search API and five proprietary financial data sources. · as of 1 Aug 2025

The problem

Ten data sources are ten failure modes. One research question touches a vector index, a web search, a general-purpose model and five proprietary financial data APIs, each with its own schema, its own limits and its own idea of a valid response. Chained naively, the whole run stops at the first payload that will not parse.

A long agent run is indistinguishable from a broken one. If the backend answers only once every tool has returned, a slow synthesis looks exactly like a hang, and the service still has to hold many of those runs open at the same time without one blocking call taking a worker down with it.

The system

One tool protocol, one state graph, one streaming surface.

What it is made of

  • An MCP-compliant tool server putting more than ten tools behind one contract — a vector store, a general model, a search API and five proprietary financial data sources — so the agent never sees a vendor client library.
  • A LangGraph reasoning engine: a fifteen-node decision graph carrying more than twenty state keys, sequencing tool calls, holding memory across steps and deciding when the question has been answered.
  • Error recovery inside the graph itself — retry paths for transient tool failures, fallback parsing when a provider returns something the schema rejects — so a bad payload degrades one branch instead of ending the run.
  • A FastAPI backend on non-blocking asyncio with JWT-secured routes and streaming JSON, so a client renders agent progress as it happens rather than after the run completes.

My role

I was the founding AI engineer, and the agent was my surface across six months: the tool server, the reasoning engine sitting on it, the service that exposes both, and the validation layer holding them together. The slowest part was not the graph. It was the boundary work — Pydantic models and validated fields with custom validators on every API boundary and every agent state transition — so a provider's schema drift surfaces as a typed error at the edge rather than as an unexplained failure deep inside the graph.

The decisions

One protocol in front of ten tools. Every capability went behind a custom MCP-compliant tool server, so the graph calls one uniform interface. Calling each provider's client directly from the graph nodes is quicker for the first two tools and worse for every one after. Adding or swapping a data source became a tool-server change instead of a graph change. The cost is a hop: every tool call now crosses a protocol boundary and gets serialised and validated on both sides of it.

Recovery belongs inside the graph, not around it. Failure handling was pushed into the decision graph so a run continues on a degraded branch rather than unwinding. Wrapping the whole run in an outer retry throws away work already paid for and re-spends every tool call that had already succeeded. It also means an answer can be assembled from a degraded branch and still be reported as a clean success.

The outcome

By the end of the six months the agent was serving the production endpoints under concurrent load, with the numbers above attached to it. Those are self-reported figures rather than audited ones, and the honest reading of them is narrow: the agent assembles a multi-source first pass far faster than the manual process, and it finishes runs a naive pipeline would have dropped. None of them says whether the note at the end is right.

What is unresolved

Fallback parsing is a quality tax that nobody is billed for. When a provider's payload fails validation and the fallback path salvages it, the run still reports success, and nothing in the output separates a figure that came from a clean parse from one that came from a rescue — so the fault-tolerance number reads as reliability when part of it is really tolerated degradation. The validation layer has the same shape of limit: typed fields guarantee that a number is a number, and guarantee nothing about whether it is the correct number or a stale one. Both gaps point at the same missing piece. Everything measured here is time and reliability; there is no evaluation of the research output itself, which is the only thing an analyst actually cares about.