Mole: A Deep-Research Agent With a Budget and a Boundary

A look at the architecture of Mole, a Go-based deep research agent that enforces strict budgets, quote checks, and local data boundaries over MCP.

I am skeptical of most deep-research agents. The usual recipe is a search API, a loop around a language model, and a cheerful final answer that hides how much of the work was guesswork. Give that loop enough budget and it can keep searching forever. Give it a few snippets and it can turn a weak connection into a confident claim.

Mole takes a different starting position. It treats the model as a worker that needs supervision, not as the system’s source of truth. It is written in Go, stores state in SQLite, and exposes the pipeline over MCP. It plans a question, searches and reads sources, extracts claims, checks quotes, builds a graph of relationships and disagreements, then writes a report.

That description is not what interests me most. Plenty of projects can describe a pipeline. What matters is where Mole puts hard boundaries around it. My view is that Mole has made several unusually good architectural choices, but it is also very easy to trust it for more than the code actually guarantees.

The best choice is the budget ledger. Mole reserves money before dispatching work and settles the reservation afterward. The check and the hold happen in the same database transaction, so concurrent workers cannot all look at the same stale balance and spend it at once. The append-only tool call ledger remains the source of truth, while the session total is updated in that transaction too.

This is the part I like. A budget is not just a number printed in a CLI flag. It is a resource that has to survive concurrency, retries, crashes, and partial work. Mole also keeps escrow for the final report and verification pass. Without that reserve, a research run could spend the entire allowance collecting claims and then have nothing left to explain what it found. That is a small design detail with a very practical consequence: stopping the research should still leave enough budget to produce an answer.

I would not call the ledger magic, though. Reservations are estimates, and the code can record an overshoot after the underlying call has already happened. That is still much better than charging after the fact, but it is a reason to inspect the estimator and provider pricing before treating a budget as an accounting guarantee. Mole has built the right control point. The control point still depends on the quality of the numbers fed into it.

The quote check is another good example of a useful, limited guarantee. When the model extracts a claim, it has to provide a quote. Mole looks for that quote in the source, first exactly and then with whitespace normalization. It stores the span from the source, not whatever cleaned-up wording the model returned. Short quotes are rejected, long quotes are capped, and the match records an offset in the original document.

That proves linkage. It proves that the source contains the words attached to the claim. It does not prove that the source is correct, that the quote is representative, or that the claim did not quietly stretch beyond the quoted sentence. I prefer this kind of honest boundary to the usual claim that citations make an answer trustworthy. A quote check catches fabricated support. It does not turn a bad source into a good one.

Mole’s MCP architecture is also more thoughtful than a single process that tries to do everything through stdio. The daemon owns the long-running session, database, credentials, and budget state. The MCP client calls research.report, gets a session ID, and polls research.status before asking for research.result. That async flow makes sense for research that can outlive the calling agent’s context.

The client-facing mole-mcp binary is deliberately boring. It forwards bytes between stdio and a Unix socket instead of parsing MCP frames itself. The daemon creates the socket inside a private directory, sets the socket to owner-only permissions, and checks the peer identity. The MCP configuration therefore contains a command, not an API key. This is a clean split: the editor gets a disposable shim, while the daemon keeps the state and the secrets.

I like the split because it matches the failure modes. A coding agent can lose its context without killing the research session, and a client does not need to understand Mole’s SQLite store. It also gives the daemon a place to enforce limits before a session starts. But this is not a zero-setup local appliance. You still need a search provider and an LLM provider, and the useful behavior depends on configuring both correctly. Brave or Tavily, Anthropic or an OpenAI-compatible endpoint, model choices, cheap model choices, timeouts, and provider-specific limits all become part of operating the tool.

That provider friction is not a flaw in the same category as a bad security boundary. A local tool has to get its model and search data from somewhere. Still, it changes who Mole is for. I would recommend it to an engineer who is comfortable owning a small research service, not to someone looking for a command that works after one install and one question. mole doctor helps, but it cannot remove the operational decisions.

The local-data path is where Mole makes its clearest privacy argument. The model can choose a hypothesis template and column names, but it does not write SQL or see raw rows. Mole renders the query, runs it through a read-only connector and SQL guard, applies an aggregation gate, and sends back an envelope of counts, moments, ranges, buckets, and statistical results. Free-text columns are withheld. The default bucket floor is five records, raw results above 5000 rows are refused, and the crossing is logged.

This is a real boundary, not a promise that the model will remember to be careful. The model cannot ask for a row and then hope a prompt tells it not to use one. At the same time, aggregates can still disclose information. Small groups, repeated questions, and carefully chosen filters can reveal more than a single summary suggests. I would trust this design more than a local-data feature that dumps CSV rows into a prompt, but I would not call it private without considering the inference attacks your data permits.

Toolkit mode exposes the most important tradeoff in the project. In autonomous mode, Mole owns the planning and reasoning loop. In toolkit mode, the host agent owns those decisions and Mole supplies search, fetching, quote checks, graph helpers, and local aggregation. This is useful if the host model is already covered by a subscription. It also changes the trust boundary.

Fetched text eventually lands in a prompt that Mole did not assemble. The source code is direct about the consequence: the prompt-injection fence becomes a convention rather than an enforcement point. Mole can wrap the document and send instructions about treating it as untrusted data, but it cannot control whether the host client preserves that boundary. Toolkit mode also caps Mole at 500 combined search/fetch calls per toolkit session, while it cannot see or bound the host model’s token usage.

This is where I stop trusting it as a complete agent safety system. Toolkit mode still gives you valuable deterministic pieces, especially quote verification and the local aggregation gate. But it is not autonomous mode with a different transport. The host model owns the part that decides what to believe and what to do next. Anyone presenting toolkit mode as full prompt-injection protection is skipping the most important line in the design.

So who should use Mole? Someone who wants an MCP-native research worker with explicit spending, durable sessions, inspectable claims, and a deliberate local-data boundary. Someone who prefers a smaller system that states its limits over a bigger agent that can spend forever. I would not use it as an oracle, and I would not let a toolkit host model make unreviewed decisions about hostile web content or sensitive aggregate results. I also would not install it for a casual one-off search unless I already had the providers configured.

Mole is interesting because its strongest ideas are not model tricks. They are boring controls: reserve before dispatch, keep escrow, preserve source linkage, separate the daemon from the shim, and make local data cross only as an audited aggregate. Those controls do not solve research correctness. They make the remaining uncertainty visible, which is a much better place to start.

The code is here: Mole on GitHub.

Older writing

Also read

Right-Sizing On-Device AI: A Look at Needle 2