mcpField
A
andon

andon

本地服务
github.com/gulmezeren2-byte数据与分析112 周前更新

关于 andon

andon 是面向分析人员和 AI Agent 的确定性验证命令行工具与 MCP 服务,可检查已完成的报告和工作簿。它通过算术将报告结果与源数据及内部一致性进行核对,不依赖另一个大模型。

主要功能

  1. 01将报告声明与源数据核对
  2. 02检查内部总计和百分比
  3. 03验证架构与 Excel 完整性
  4. 04标记需人工复核的合理性问题
  5. 05归类不同版本工作簿的变更

适用场景

  1. 01发送前验证 AI 起草的报告
  2. 02无需规格文件即可检查工作簿
  3. 03在 CI 或提交前设置报告检查关卡
  4. 04审查不同版本工作簿的变更类别

MCP 相关

可选的 MCP 服务向 MCP 客户端提供 `run`、`inspect` 和 `diff` 工具,并返回结构化验证结果。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"gulmezeren2-byte-andon": {
"command": "uvx",
"args": [
"andon-verify"
]
}
}
}
启动命令uvx andon-verify

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypiandon-verify0.6.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

andon

数字对不上时,立即拉停生产线。

CI PyPI Python License: MIT

andon 会重新核对已完成分析中的数字——无论是 AI Agent 刚起草的报告, 还是同事“快速更新”过的工作簿——并将其与原始数据及彼此进行核对。它使用算术运算,而非另一个大模型:对账、 内部一致性、架构契约和 Excel 工作簿完整性,都以精简的 YAML 规范记录下来,并通过退出码强制执行。

andon 在一份遭篡改的季度报告上拉停生产线

截图展示的是真实输出。运行示例位于 examples/quarterly-report/,由脚本生成,其中植入了我在实际报告工作中反复遇到的问题:从过期快照中获取的计数、手动覆盖的收入总额、合计为 101.2 的占比、数据刷新后无人更新的总计行、一个 #REF!,以及以文本形式存储的运费数字。

为什么要做这个

我是一名工业工程师,负责构建和运行运营报告——交付 KPI、 预测准确率、库存分析。过去两年里,我身边越来越多的报告初稿由 AI Agent 撰写。它们速度快、不知疲倦,却会自信地犯错,而且错误的方式连疲惫的人类都不会犯:筛选条件悄悄漏掉已取消的订单、合计几乎达到 100% 的百分比列、组成部分被编辑过三次却依然原封不动的总计行。

常见的做法是让第二个模型审查第一个模型。我认为这不是合适的工具。539 行数据是否确实合计为 257,060.48,不是主观问题,再强大的模型也无法让主观判断成为合适的验证手段。

制造业几十年前就解决了这个问题。在丰田生产线上,任何发现缺陷的工人都可以拉动一根绳子——andon——让生产线停下来,直到问题查明。对应的机器机制叫作 jidoka:机器检测到异常状况时会自动停止。这个工具就是电子表格和报告的这根绳子:在“分析已写好”和“分析已发送”之间设置一道小巧、确定性的关卡。

铁律

andon 的行为受到约束,因此更值得信任。以下规则由代码强制执行,而不只是写在这里:

  1. 只有算术检查能让构建失败。 启发式检查(分布偏移、 合理性边界)可以发出 REVIEW 标记;即使有缺陷的检查试图让引擎报 FAIL,引擎也不会允许。
  2. 绝不默默背书。 每份报告都会列出读取了什么、跳过了什么,以及哪些工作表从未检查(报告将此称为诚实区块)。PASS 仅涵盖列出的断言,不代表其他内容。
  3. 无法运行的检查会记录为发现项,而非通过。 文件缺失、范围无法读取、数字列中出现文本——运行会继续,检查会记为 ERROR,退出码也会非零。“未验证”绝不能被理解为“没问题”。
  4. 从设计上只读。 代码中不存在写入数据的路径。

安装

pip install andon-verify

PyPI 发行包名为 andon-verify(andon 这个名称已被占用);命令和导入名仍为 andon——andon run ...、import andon。 从源码安装:pip install git+https://github.com/gulmezeren2-byte/andon。

快速开始

指定数据和声明,让 andon 进行核对:

# andon.yaml
version: 1

sources:
  orders: data/orders.csv
  report: out/weekly.xlsx#Summary

checks:
  - name: no dropped orders
    reconcile.row_count:
      left:  { source: orders, where: "status != 'cancelled'" }
      right: { source: report, cell: B4 }

  - name: revenue adds up
    reconcile.sum:
      column: revenue
      left:  { source: orders, where: "status != 'cancelled'" }
      right: { source: report, cell: B6 }
      tolerance: 0.5%

  - name: totals row is honest
    internal.total_row:
      source: report
      parts: B10:B21
      total: B22
      tolerance: 0.01

  - name: workbook is mechanically sound
    excel.integrity:
      source: report
andon run andon.yaml            # human-readable verdict
andon run andon.yaml --json     # full machine-readable report
andon inspect out/weekly.xlsx   # integrity-scan a workbook, no spec needed
andon init                      # write a commented starter spec

也可以试试此仓库中的篡改示例:

git clone https://github.com/gulmezeren2-byte/andon
cd andon/examples/quarterly-report
andon run andon.yaml

检查内容

类别检查项回答的问题会失败吗?
reconcilerow_count、sum、aggregate、group_sum、keys报告与其来源数据一致吗?会
internaltotal_row、percent_sum、recompute报告与自身一致吗?会
schemacolumns、unique、not_null、allowed_values、date_continuity数据的结构是否符合大家的预期?会
excelintegrity工作簿在技术层面是否完好?(#REF!、值覆盖公式、数字存储为文本——包括 1.234,56 这种格式——隐藏行、外部链接)出现错误单元格时
plausibilitybounds、new_categories、mean_shift在任何人信任这些数据之前,是否应由人工查看?不会——最多标记为 REVIEW

完整参数参考及示例:docs/checks.md。

退出代码和 CI

退出代码是一项约定:

代码含义
0所有检查均已通过
1至少有一项 FAIL(使用 --strict 时,出现 REVIEW/ERROR/未运行任何检查也会返回此代码)
2没有失败项,但出现了 REVIEW 标记
3未验证任何内容——某项检查无法运行,或所有检查均已跳过
4规范本身有问题

作为 GitHub Action 使用——只需一行,判定结果就会显示在作业摘要中:

- uses: gulmezeren2-byte/andon@v1
  with:
    spec: reports/andon.yaml
    args: "--strict"

或者,在任何运行器中直接运行:

- run: pip install andon-verify
- run: andon run reports/andon.yaml --strict --md verdict.md   # --md → a PR-comment-ready verdict

作为 pre-commit 钩子使用

在有问题的报告离开你的机器之前,阻止提交:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/gulmezeren2-byte/andon
    rev: v0.6.2
    hooks:
      - id: andon
        args: ["reports/andon.yaml", "--strict"]

在 AI Agent 中使用 andon

andon 专为 Agent 驱动而构建,而不是用来包含 Agent:

  • --json 会输出包含稳定字段名称的完整报告;仅凭退出代码就足以做出是否放行的判断。
  • 错误消息会指出涉及的数据源、列和工作表,因此 Agent 可以自行修复规范,而不必猜测(“未找到列 'Revenue'。现有列为:region、share_pct、revenue”)。
  • skills/verify-with-andon/ 提供了适用于 Claude Code 和兼容运行环境的技能,用于教会 Agent 遵循规范:完成任何分析草稿后,编写规范、运行 andon 并报告判定结果——还包括一条规则:若要通过放宽容差使检查通过,必须明确声明,绝不能悄然更改。
  • MCP 服务。 运行 pip install 'andon-verify[mcp]' 并启动 andon-mcp,即可向任何支持 MCP 的运行时提供三个工具:run(执行规范)、inspect(不使用规范扫描工作簿完整性)和 diff(判定两个版本之间的更改)。Agent 获得的判定结果与人工看到的结构相同——而不是还需要再解析回来的文字说明。
// e.g. Claude Desktop / Claude Code mcp config
{ "mcpServers": { "andon": { "command": "andon-mcp" } } }

没有本地 Python?Dockerfile 可以构建相同的服务: docker build -t andon . && docker run --rm -i -v "$PWD:/work:ro" -w /work andon。

我的工作原则是:编写分析的 Agent 也要编写规范;只有当 andon run 返回 0,或人工确认了它标记的每一项问题后,分析和规范才算完成。

andon 不是什么

  • 不是数据质量平台。 Great Expectations 和 pandera 会在代码中、通常针对数据仓库,在流水线内部验证数据。andon 验证的是已完成产物中的声明——报告是否与其来源一致;并将 Excel 视为一等公民,因为在大多数公司,分析实际都在 Excel 中进行。
  • 不是大模型评估器。 它不会为模型输出打分,而是重新推导数字。
  • 不能替代阅读报告。 它能排除一类机械性错误,让人工审核能够专注于判断。

局限性,如实说明

  • 公式单元格需要缓存值。 andon 读取 Excel 上次计算的值。由某个库生成、且从未在 Excel/LibreOffice 中打开过的工作簿,其公式没有缓存值;andon 不会猜测,并会明确报告这一点。
  • where 筛选条件是 pandas query() 表达式。 它们功能强大,这意味着规范也可能包含与任何查询相同的错误。规范就是代码——应像审查代码一样审查它们。
  • 启发式检查有意允许误报。 因此它们不能导致构建失败。
  • 尚未测试中等规模文件以外的数据规模。 日常运营工作簿和 CSV(数十万行)都没问题;还没人针对 10 GB 的 parquet 文件做过基准测试。如果你测试了,请告诉我出了什么问题。
  • Parquet 数据源需要执行 pip install 'andon-verify[parquet]'。

CSV 编码、分隔符和数字标点格式

默认情况下,CSV 数据源按 utf-8 读取,并会去除 Excel 的 BOM,避免其污染第一列名称。如果文件不是 utf-8 编码——从 Excel 导出的土耳其语文件通常使用 ; 分隔符、cp1254 编码,并将金额写成 1.234,56——请将数据源指定为映射,而不是单独的路径:

sources:
  sales:
    path: data/satis.csv
    encoding: cp1254      # default: utf-8-sig
    delimiter: ";"        # default: ","
    decimal: ","          # default: "."
    thousands: "."        # default: none

如果编码有误,andon 会指出这一点,并说明可能的原因——它不会悄悄把列名乱码,然后再“验证”它们。

后两项比看上去更重要。不设置它们,1.234,56 就会被读取为文本,而文本列是数值检查无法检查的列。andon 会告诉你这一点,而不是通过检查——见下文——但声明标点格式,才能让该列可以接受检查。

无法读取数据时,检查会怎么处理

每份报告的结尾都有相同的一句话:PASS 并非对分析的主观判断,而是对这些声明进行的算术验证。 因此,检查必须区分粗心实现会混为一谈的两种情况:

  • “我比较了它们,结果没问题”——PASS。
  • “我没有可供比较的内容”——绝不会是 PASS。

因此,未找到数值的合理性检查会明确说明这一点,而不是报告有零个值超出范围:

REVIEW  bounds  no numeric values in tutar; nothing was compared against the bounds

如果一列中只有部分数据可读,判定结果会附带分母,因为关于成功解析的一半数据的陈述,并不等同于关于你提交的数据的陈述:

REVIEW  bounds  tutar stays within bounds, but only read 2 of 4 value(s) of tutar

每项此类检查都会在证据中报告 values_checked、values_total 和 values_skipped,因此覆盖情况也可由机器读取。pandas 在读取时转换为 NaN 的值——n/a、-、#N/A——与其他值一样计为跳过;它们在简单的强制转换计数中不可见,这正是它们过去会被忽略的原因。

根据数据仓库查询进行验证(DuckDB)

数据源可以是 SQL 查询,而不是文件——这样你就能根据 BI 工具读取的同一份数据核对报告,而不仅仅是根据 CSV。执行 pip install 'andon-verify[duckdb]' 后,在数据源前加上 duckdb: 前缀,DuckDB 就会运行该查询(可在查询中读取 CSV、parquet、JSON 和 .duckdb 文件;相对路径相对于规范解析):

sources:
  # the report's headline number
  report: out/q2.xlsx#Summary
  # the same number, straight from the raw data via SQL
  truth: "duckdb:SELECT SUM(revenue) AS rev FROM 'data/orders.parquet' WHERE status='shipped'"

checks:
  - name: revenue matches the warehouse
    reconcile.sum:
      column: rev
      left:  { source: truth }
      right: { source: report, cell: B6 }
      tolerance: 0.5%

对比两个工作簿版本

“有人编辑了工作簿——究竟改了什么?” 对 .xlsx 执行 git diff 只会得到一堆无用信息,而比较电子表格的工具会平铺显示每个变更的单元格。andon diff 会对每项变更进行分类,因此新的 #REF! 不会被重新设置格式的日期掩盖:

andon diff last-week.xlsx this-week.xlsx
andon diff v1.xlsx v2.xlsx --tolerance 0.5%   # hide numeric moves below 0.5%
andon diff v1.xlsx v2.xlsx --json             # machine-readable
cell        change      before → after
Summary!B9  new_error   43.8 → #REF!
Summary!B4  numeric     261,687.57 → 266,687.57  (+5000, +1.91%)

新的错误单元格会单独标出;数值变化会附带差值和百分比。 退出代码:0 = 没有实质性变化,1 = 出现新错误(或使用 --strict 时有任何变化),2 = 有变化但没有新错误。

路线图

自 0.1 版以来已发布:GitHub Action 和 pre-commit 钩子、DuckDB 数据源、andon diff、MCP 服务、CSV 编码和分隔符控制,以及 JSON/JSONL 数据源。

近期计划,按顺序排列:

  • 为数据表提供行级差异比较,而不只是逐单元格比较
  • --watch 模式:当数据源在磁盘上发生变化时,重新运行规范

暂无计划:仪表板、定时运行器,以及在验证器内部加入任何由大模型驱动的功能。 验证器将保持确定性;这正是重点所在。

本项目的构建方式

我负责设计检查项、确定语义并审查每一行代码;我大量使用 AI Agent(Claude Code)来提高实现速度,提交说明也如实注明了这一点。如果你对此介意,请先看看 tests/:测试套件会构建真实的 CSV 和 XLSX 测试数据,不使用模拟对象,而这就是约定。测试并不在意代码是谁输入的。

相关项目

  • opsaudit —— 同样的理念,但更进一层:运营分析会审计自身的数据,而不是盲目信任它们。andon 会根据数据源检查已完成的报告;opsaudit 则会计算指标,并内置诚实性检查。

更多由 Eren Gülmez 制作的工具。

许可证

MIT — Mehmet Eren Gülmez

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。