商业产业 Hacker News LLM 2026-08-14T18:52 正文 ok 1656 words

🔶 Show HN:Mole——面向终端的深度研究 Agent

英文标题:🔶 Show HN: Mole – Deep research agent for your terminal

Mole 是一款以 Go 编写、通过 MCP 暴露能力的终端深度研究 Agent,可拆解问题、搜索和阅读来源、提取并核验主张、发现矛盾,并生成带引用的回答。其核心特点是严格执行而非预估预算:模型调用前预留费用、调用后结算,测试语料中的预算超支率为 0%。Mole 还要求每条主张附带可在原始页面逐字验证的引文,并通过聚合结果和 SQL 模板机制,让本地 CSV、JSON 等数据无需离开机器即可参与分析。对于 Claude Code、Qwen Code 等订阅用户,toolkit mode 允许 Agent 使用自身模型推理,而由 Mole 提供检索、引文核验、数据聚合和图谱构建等确定性能力。
打开原文相关 3 · 机会 1
media1.0 MB media46.2 KB media128.9 KB

中文

Mole——一款通过 MCP 暴露能力的 Go 深度研究 Agent

一款具备强制预算、已验证引文,以及本地数据隐私边界的深度研究 Agent。

提出一个问题。mole 会将其拆解、搜索、阅读来源、提取主张,逐一根据其来源文本核查每条主张,在主张之间寻找矛盾,并撰写带引用的答案。每次模型调用都会在发生前从预算中预留额度、发生后完成结算,因此你设定的上限就是它实际触及的上限。

它以单个静态二进制文件形式运行在你的机器上,使用你自己的 API 密钥,并支持 MCP,因此编程 Agent 可以驱动它——既可以将问题交给 mole 并收集答案,也可以在 toolkit mode 中让 Agent 用自己的模型推理,同时由 mole 提供所有非模型调用的部分。

mole 正在研究一个问题:规划、39 条主张、发现两处矛盾、已花费 0.0149 美元


以下是 mole 能做到、而带网页搜索的聊天界面做不到的三件事。

预算是强制执行的,而不是预估的。 每次调用都会在执行前预留、执行后结算,并依据一个在数据库 schema 本身中具有非负约束的账本进行管理。--usd 0.50 意味着本次运行会在花费五十美分时停止。测试语料中测得的超支率为 0%。

每条主张都带有经过来源核验的引文。 如果一条主张的引文并未在其挖掘自的页面中逐字出现,该主张会在提取阶段被丢弃,无法进入最终答案。存活下来的主张之后仍可对照来源重新阅读;如果发现某条主张实际上不受来源支持,报告会将其标记为不受支持,而不是悄悄删除。

你的本地数据始终留在本地。 将 CSV 文件或文件夹交给 mole,它可以在内容不离开机器的情况下进行分析:模型选择假设模板和列名,mole 渲染并运行 SQL,且只允许聚合结果——计数、均值、检验结果、至少覆盖五条记录的分桶——返回给模型。mole crossings 会准确显示哪些内容离开了机器。


脚本安装 —— 支持 Linux 和 macOS、amd64 和 arm64:

curl -fsSL https://raw.githubusercontent.com/lajosdeme/mole/main/install.sh | sh

该脚本会下载适用于你所在平台的发布归档文件,根据随发布版本公布的校验和验证其 SHA-256,并将 mole 和 mole-mcp 安装到 ~/.local/bin(如果 /usr/local/bin 可写,则安装到该目录)。只有目标目录需要时才会使用 sudo,而 --dry-run 会展示它将执行的操作。如果你对将脚本通过管道传给 shell 感到不安——这是合理的——请先阅读脚本,或使用以下任一路径。

Homebrew —— macOS 和 Linux:

brew install lajosdeme/mole/mole

必须使用完整限定名:homebrew/core 中已有一个无关的 mole(macOS 清理工具),因此 brew install mole 始终会指向那个工具。两者都会安装名为 mole 的二进制文件,因此一次只能链接其中一个。

Arch Linux —— 通过 AUR:

yay -S mole-research-bin      # prebuilt release binaries
yay -S mole-research          # build from source

不是 mole:该名称以及 AUR 上的 mole-bin 属于一款 SSH 隧道工具,后者自 2020 年起便占用了这些名称。该软件包会安装 /usr/bin/mole 并声明冲突,因此 pacman 会提示你,而不是覆盖任何内容。

Debian 和 Ubuntu —— 从发布页面获取 .deb:

curl -fsSLO https://github.com/lajosdeme/mole/releases/latest/download/mole_amd64.deb
sudo dpkg -i mole_amd64.deb

相同平台也提供 .rpm 包。

从源代码安装 —— 需要 Go 1.25+:

go install github.com/lajosdeme/mole/cmd/mole@latest
go install github.com/lajosdeme/mole/cmd/mole-mcp@latest

或者克隆仓库后执行 make install;该方式会写入版本信息,因此 mole version 显示的是标签而非 dev。

所有路径安装的内容都相同:两个没有运行时依赖、以 CGO_ENABLED=0 构建的静态二进制文件。数据库为 SQLite,首次使用时会在你的 XDG 数据目录下创建。

你需要一个搜索提供商和一个模型提供商。密钥存储在 ~/.config/mole/config.json 中,文件权限为 0600——绝不放在可能泄露到进程列表中的环境变量中,也绝不放在 .mcp.json 中。

mole config set search.provider tavily          # or: brave
mole config set search.tavily-key tvly-...

mole config set llm.provider anthropic          # or: openai-compatible
mole config set llm.api-key sk-...
mole config set llm.model claude-sonnet-5
mole config set llm.cheap-model claude-haiku-4-5

mole doctor                                     # verify everything above

任何兼容 OpenAI 的端点都可以使用——DeepSeek、Ollama、llama.cpp、vLLM 或代理:

mole config set llm.provider openai-compatible
mole config set llm.base-url https://api.deepseek.com/v1
mole config set llm.model deepseek-chat

部署在 localhost 的模型定价为零,但 token 仍会被计数,因此 --tokens 可以限制完全无需金钱成本的自托管运行。


mole research "how much electricity does the bitcoin network use?" --usd 0.50
mole research "..." --tokens 200000            # token budget instead of dollars
mole research "..." --max-sources 8 --max-depth 3
mole research "..." --json                      # machine-readable result

预算是必填项,两种单位互斥。只有美元模式能为搜索调用定价;只有 token 模式能够约束 mole 不知道费率的模型。

mole ask <session-id> "what did the Cambridge estimate say?"

根据该会话已收集的主张作答。不进行新的搜索,除生成答案措辞所需的一次调用外,也不会产生新的支出。

构建数据集,而非散文回答

mole research "largest UK supermarket chains and their revenue" \
  --mode dataset \
  --schema 'company:text!,revenue:number=annual revenue in GBP,employees:number' \
  --usd 0.50

mole dataset <session-id> --format csv > chains.csv
mole dataset <session-id> --format json          # every value every source gave

! 标记用于识别一行记录的字段。行会通过模糊键跨来源合并,因此 Aldi 与 Aldi UK 会成为同一行,并附带两个来源。CSV 每个单元格只保存一个值,并对此作出说明——它包含来源数量,以及用于标出来源存在分歧字段的 contested 列。JSON 则保留每个存在分歧的值及其背后的来源。

mole connect add sales ./exports/sales.csv       # one file
mole connect add exports ./exports               # or a whole folder
mole research "how does spend differ between regions?" \
  --actors local_compute --usd 0.30

mole crossings <session-id>                      # what left the machine

支持 CSV、TSV、JSON 和 JSONL;不支持 Parquet。模型永远看不到任何一行数据,也永远不会编写 SQL——它只选择模板和列名,由 mole 渲染语句。

服务监听于私有目录中的 Unix socket,权限为 0600,并拒绝来自其他用户的连接。将客户端指向该 shim:

{
  "mcpServers": {
    "mole": { "command": "mole-mcp" }
  }
}

该文件中没有凭据——shim 会转发给持有凭据的守护进程。

使用你已经付费订阅的服务(toolkit mode)

上述安排中,mole 拥有模型:它使用你的 API 密钥进行规划、挖掘和写作,驱动它的编程 Agent 只是按下按钮。Toolkit mode 则反转了这种关系。Agent 的模型负责推理;mole 提供确定性的一半能力——而这正是值得拥有、且不在乎另一端是哪种模型的一半能力。

如果你在 Claude Code 或 Qwen Code 中使用订阅服务,你的模型 token 已经付费。这正是适合该模式的场景。

共有 14 个工具,每个均命名为 mole.<tool>,与 research.* 工具并列——该标志增加了一层能力接口,而不是替换已有接口:

类别 工具
session session_open, session_close
retrieval search, fetch —— 通过 mole 的 SSRF 防护、robots 处理和速率限制器
evidence verify_quote, claim_add, claims_list, citations
local data connect_list, aggregate —— 隐私边界保持不变
graph pairs_candidates, edge_add
dataset rows_add, dataset
mole sessions                # recent sessions and what they cost
mole trace <session-id>      # per-call cost and timing breakdown
mole stats --fetch           # why fetches failed, across sessions

question
   ↓  planner            将问题拆解为子问题,并随证据到来重新规划
   ↓  executor           每个 worker 一次处理一条线索,预留并结算预算
   ↓  actor              search → fetch → extract → mine claims
   ↓                     每条主张的引文均会对照来源进行核验
   ↓  verifier           配对相关主张、裁决并构建主张图谱
   ↓                     抽样将主张与其来源重新核对
   ↓  output             基于存活主张综合生成带引用的答案
answer

三种 actor 类型向同一个图谱提供数据。web 搜索并阅读网页。academic 查询 Crossref、OpenAlex、arXiv 和 PubMed,按 DOI 去重,并优先选择开放获取的全文。local_compute 对你登记的数据运行确定性 SQL,且绝不让任何一行数据到达模型。

Toolkit mode 使用相同机制,但箭头方向相反:Agent 决定要搜索什么、阅读什么,以及哪些主张彼此相关;mole 则执行引文核验、主张对检索、合并和 SQL 渲染。两种模式对每项能力共用同一份实现——数据集行使用相同的 AcceptRow,使用相同的聚合门控和词法检索器——因此 toolkit 图谱和自主模式图谱以同样的方式构建。


mole 会为自己的运行评分。mole eval <session-id> 会输出评分卡,任何无法计算的指标都会明确说明,而不是悄悄显示为零。

指标 结果
预算超支 0% —— 没有任何运行超过其上限
主张完整性 100% —— 每条存储的主张都带有来源和逐字引文
引用准确性 100% —— 每条引文都能在其所引用的来源中找到
依据来源确认率 80% —— 在对照来源重新阅读的主张中,得到确认的比例
矛盾识别精度 使用确认步骤时为 70%,不使用时为 51%
合并精度 / 召回率 构造的真实值基准上为 1.000 / 1.000

欢迎提交 Bug 报告和 issue。代码贡献需要通过 CLA——请参阅 CONTRIBUTING.md,其中说明了它的用途及其不能做到的事情。

维护者请参阅发布运行手册:RELEASING.md。

这个项目提出了一项大多数项目没有的实践要求:证伪你自己的修复。 完成修改后,撤销实现机制,并确认测试会失败。如果移除修复后测试仍然通过,它什么也证明不了;这个项目自身就曾发现有多个测试正是如此。

gofmt -l .      # must print nothing
go build ./...
go test ./...   # must be clean, and no new skips

Apache-2.0。参见 LICENSE 和 NOTICE。

English / 原文

Mole — a deep research agent in Go, exposed over MCP

A deep-research agent with an enforced budget, verified quotes, and a privacy boundary for local data.

Ask a question. mole decomposes it, searches, reads sources, extracts claims, checks each claim against the text it came from, looks for contradictions between them, and writes an answer with citations. Every model call is reserved against a budget before it happens and settled after, so the ceiling you set is the ceiling it hits.

It runs as a single static binary on your machine, uses your own API keys, and speaks MCP so a coding agent can drive it — either by handing mole a question and collecting the answer, or, in toolkit mode , by doing the reasoning with its own model while mole supplies the parts that are not model calls.

mole researching a question: planning, 39 claims, two contradictions found, $0.0149 spent


Three things mole does that a chat interface with web search does not.

The budget is enforced, not estimated. Every call is reserved before it is made and settled after, against a ledger with non-negative constraints in the database schema itself. --usd 0.50 means the run stops at fifty cents. Measured overshoot across the test corpus is 0%.

Every claim carries a quote, checked against the source. A claim whose quote does not appear verbatim in the page it was mined from is discarded at extraction, before it can reach an answer. Claims that survive can be re-read against their source afterwards, and one that turns out not to be supported is marked as such in the report rather than quietly dropped.

Your local data stays local. Point mole at a CSV or a folder and it will analyse it without the contents leaving your machine: the model chooses a hypothesis template and column names, mole renders and runs the SQL, and only aggregates — counts, means, test results, buckets covering at least five records — are allowed back. mole crossings shows you exactly what left.


Script — Linux and macOS, amd64 and arm64:

curl -fsSL https://raw.githubusercontent.com/lajosdeme/mole/main/install.sh | sh

Downloads the release archive for your platform, verifies its SHA-256 against the checksums published with the release, and installs mole and mole-mcp into ~/.local/bin (or /usr/local/bin if that is writable). It uses sudo only if the target directory needs it, and --dry-run shows what it would do. If piping a script into a shell makes you uneasy — reasonable — read it first, or use one of the paths below.

Homebrew — macOS and Linux:

brew install lajosdeme/mole/mole

Fully qualified, and it has to be: an unrelated mole (a macOS cleanup tool) is in homebrew/core, so brew install mole will always mean that one. Both install a binary called mole, so only one can be linked at a time.

Arch Linux — from the AUR:

yay -S mole-research-bin      # prebuilt release binaries
yay -S mole-research          # build from source

Not mole: that name and mole-bin on the AUR belong to an SSH tunnelling tool that has held them since 2020. The package installs /usr/bin/mole and declares the conflict, so pacman will tell you rather than overwrite anything.

Debian and Ubuntu — .deb from the releases page:

curl -fsSLO https://github.com/lajosdeme/mole/releases/latest/download/mole_amd64.deb
sudo dpkg -i mole_amd64.deb

An .rpm is published for the same platforms.

From source — needs Go 1.25+:

go install github.com/lajosdeme/mole/cmd/mole@latest
go install github.com/lajosdeme/mole/cmd/mole-mcp@latest

Or clone and make install, which stamps the version so mole version reports the tag rather than dev.

Every path installs the same thing: two static binaries with no runtime dependencies, built CGO_ENABLED=0. The database is SQLite, created on first use under your XDG data directory.

You need a search provider and a model provider. Keys live in ~/.config/mole/config.json, mode 0600 — never in environment variables that leak into process listings, and never in .mcp.json.

mole config set search.provider tavily          # or: brave
mole config set search.tavily-key tvly-...

mole config set llm.provider anthropic          # or: openai-compatible
mole config set llm.api-key sk-...
mole config set llm.model claude-sonnet-5
mole config set llm.cheap-model claude-haiku-4-5

mole doctor                                     # verify everything above

Any OpenAI-compatible endpoint works — DeepSeek, Ollama, llama.cpp, vLLM, a proxy:

mole config set llm.provider openai-compatible
mole config set llm.base-url https://api.deepseek.com/v1
mole config set llm.model deepseek-chat

A model served from localhost is priced at zero and still counted in tokens, so --tokens bounds a self-hosted run that costs no money at all.


mole research "how much electricity does the bitcoin network use?" --usd 0.50
mole research "..." --tokens 200000            # token budget instead of dollars
mole research "..." --max-sources 8 --max-depth 3
mole research "..." --json                      # machine-readable result

Budget is required, and the two units are mutually exclusive. Only dollar mode can price a search call; only token mode can bound a model whose rates mole does not know.

mole ask <session-id> "what did the Cambridge estimate say?"

Answers from the claims that session already collected. No new searching, no new spending beyond the one call to phrase the answer.

Build a dataset instead of prose

mole research "largest UK supermarket chains and their revenue" \
  --mode dataset \
  --schema 'company:text!,revenue:number=annual revenue in GBP,employees:number' \
  --usd 0.50

mole dataset <session-id> --format csv > chains.csv
mole dataset <session-id> --format json          # every value every source gave

! marks the field that identifies a row. Rows are merged across sources by fuzzy key, so Aldi and Aldi UK become one row with two sources. CSV holds one value per cell and says so — it carries a source count and a contested column naming the fields the sources disagree about. JSON carries every disagreeing value with the sources behind each.

mole connect add sales ./exports/sales.csv       # one file
mole connect add exports ./exports               # or a whole folder
mole research "how does spend differ between regions?" \
  --actors local_compute --usd 0.30

mole crossings <session-id>                      # what left the machine

CSV, TSV, JSON and JSONL are supported; Parquet is not. The model never sees a row and never writes SQL — it picks a template and column names, and mole renders the statement.

Listens on a unix socket, mode 0600, in a private directory, and refuses connections from any other user. Point a client at the shim:

{
  "mcpServers": {
    "mole": { "command": "mole-mcp" }
  }
}

No credentials in that file — the shim forwards to the daemon, which holds them.

Use the subscription you already pay for (toolkit mode)

The arrangement above has mole own the model: it plans, mines and writes with your API key, and the coding agent driving it is pressing a button. Toolkit mode inverts that. The agent's model does the reasoning; mole contributes the deterministic half — which is the half worth having, and the half that does not care whose model is on the other side of it.

If you are inside Claude Code or Qwen Code on a subscription, your model tokens are already paid for. This is the mode for that.

Fourteen tools, each named mole.<tool>, alongside the research.* tools — the flag adds a surface rather than replacing one:

|
---|---
session | session_open, session_close
retrieval | search, fetch — through mole's SSRF guard, robots handling and rate limiter
evidence | verify_quote, claim_add, claims_list, citations
local data | connect_list, aggregate — the privacy boundary, unchanged
graph | pairs_candidates, edge_add
dataset | rows_add, dataset

mole sessions                # recent sessions and what they cost
mole trace <session-id>      # per-call cost and timing breakdown
mole stats --fetch           # why fetches failed, across sessions

question
   ↓  planner            decompose into sub-questions, replan as evidence arrives
   ↓  executor           one lead at a time per worker, reserved and settled
   ↓  actor              search → fetch → extract → mine claims
   ↓                     every claim quote-checked against its source
   ↓  verifier           pair up related claims, adjudicate, build the claim graph
   ↓                     re-read a sample of claims against their sources
   ↓  output             synthesise from claims that survived, with citations
answer

Three actor types feed the same graph. web searches and reads pages. academic queries Crossref, OpenAlex, arXiv and PubMed, deduplicates by DOI and prefers open-access full text. local_compute runs deterministic SQL over data you registered and never lets a row reach the model.

Toolkit mode runs the same machinery with the arrows reversed: the agent decides what to search, what to read and which claims relate, and mole does the quote checking, the pair retrieval, the merging and the SQL rendering. Both modes share one copy of each — the same AcceptRow for dataset rows, the same aggregation gate, the same lexical retriever — so a toolkit graph and an autonomous one are built the same way.


mole grades its own runs. mole eval <session-id> prints a scorecard, and any metric it cannot compute says so instead of quietly reading zero.

|
---|---
budget overshoot | 0% — no run has exceeded its ceiling
claim integrity | 100% — every stored claim carries a source and a verbatim quote
citation accuracy | 100% — every quote found in the source it cites
grounding rate | 80% — of claims re-read against their source, confirmed
contradiction precision | 70% with the confirm pass, 51% without
merge precision / recall | 1.000 / 1.000 on constructed ground truth


Bug reports and issues are welcome. Code contributions go through a CLA — see CONTRIBUTING.md, which explains what it is for and what it cannot do.

Maintainers: the release runbook is RELEASING.md.

The one practice this project asks for that most do not: falsify your own fix. After a change, revert the mechanism and confirm the test fails. A test that passes with the fix removed proves nothing, and several of this project's own tests have been caught doing exactly that.

gofmt -l .      # must print nothing
go build ./...
go test ./...   # must be clean, and no new skips

Apache-2.0. See LICENSE and NOTICE.