andon について
andonは、分析担当者やAIエージェントが完成したレポートやワークブックを検証する、決定論的なコマンドラインツール兼MCPサーバーです。別のLLMを使わず、算術によって結果を元データや内部整合性と照合します。
主な機能
- 01レポートの主張を元データと照合
- 02合計値や割合の内部整合性を確認
- 03スキーマとExcelの整合性を検証
- 04妥当性に関する要確認項目を提示
- 05ワークブックの版間の変更を分類
活用シーン
- 01AIが作成したレポートを送付前に検証
- 02仕様ファイルなしでワークブックを検査
- 03CIやコミット前のレポート検査を設定
- 04ワークブックの版間変更の分類を確認
MCP 対応
オプションのMCPサーバーは、MCPクライアントに `run`、`inspect`、`diff` ツールを提供し、構造化された検証結果を返します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
andon
数値が合わなければ、ラインを止めます。
andon は、完成した分析の数値を、元となったデータおよび数値同士の整合性と照らし合わせて再確認します。AI エージェントがたった今作成したレポートや、同僚が「ちょっと更新した」ワークブックを対象にします。別の LLM ではなく算術演算を使い、照合、内部整合性、スキーマ契約、Excel ワークブックの整合性を、小さな YAML 仕様に記述して終了コードでチェックします。
このスクリーンショットは実際の出力です。実行対象の例は
examples/quarterly-report/ にあります。実際のレポート業務で何度も遭遇してきた欠陥を仕込むスクリプトで用意されています。古いスナップショットから取得された件数、手入力で上書きされた売上合計、合計が101.2になるシェア、データ更新後も更新されなかった合計行、#REF!、そしてテキストとして保存された運賃の数値です。
このツールを作った理由
私は産業エンジニアです。配送 KPI、予測精度、在庫分析など、業務レポートの作成と運用を担当しています。ここ2年ほどで、身の回りのレポートの初稿のうち、AI エージェントが作成する割合が増えてきました。AI エージェントは高速で疲れ知らずですが、疲れた人間とは違う形で、自信満々に間違えます。キャンセル済みの注文をひそかに除外するフィルター、合計が100に近いだけのパーセント列、構成要素を3回編集した後も残っている合計行などです。
よくある対処法は、別のモデルに最初のモデルをレビューさせることです。私は、それは適切なツールではないと思います。539行の合計が本当に257,060.48になるかどうかは、意見の問題ではありません。どれほど優れたモデルでも、意見をその確認に適した道具に変えることはできません。
製造業は数十年前にこの問題を解決しました。トヨタの生産ラインでは、欠陥に気づいた作業者がコード、つまり andon を引き、問題の原因が明らかになるまでラインを止めます。機械に置き換えた仕組みである jidoka は、異常を検知すると自ら停止する機械です。このツールは、スプレッドシートやレポート向けのそのコードです。「分析を書き終えた」状態から「分析を送る」状態へ進む間に置く、小さく決定論的なゲートです。
絶対に守るルール
andon の動作は制約によって信頼しやすくなっています。以下のルールは、ここで約束するだけでなく、コードで強制されています。
- ビルドを失敗させるのは算術演算だけです。 分布の変化や妥当性の範囲といったヒューリスティックなチェックは REVIEW フラグを立てることがありますが、エンジンは FAIL にしません。バグのあるチェックがそうしようとしても同じです。
- 黙ってお墨付きを与えることはありません。 すべてのレポートには、読み取ったもの、スキップしたもの、未確認のままのワークシートが記載されます(レポートではこれを「honesty block」と呼びます)。PASS が保証するのは、列挙されたアサーションだけです。
- 実行できないチェックは、合格ではなく検出事項です。 ファイルがない、範囲を読み取れない、数値列にテキストが含まれるといった場合も処理は続行され、チェックは ERROR として記録され、終了コードはゼロ以外になります。「未検証」を「問題なし」と読める状態にしてはいけません。
- 設計上、読み取り専用です。 データを書き込むコードパスはありません。
インストール
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
チェック内容
| 分類 | チェック | 確認できること | FAIL になる可能性 |
|---|---|---|---|
reconcile | row_count、sum、aggregate、group_sum、keys | レポートは元データと一致していますか? | あり |
internal | total_row、percent_sum、recompute | レポート内で整合性が取れていますか? | あり |
schema | columns、unique、not_null、allowed_values、date_continuity | データの形式は、関係者が想定しているとおりですか? | あり |
excel | integrity | ワークブックに機械的な問題はありませんか?(#REF!、数式を値で上書き、テキストとして保存された数値(1.234,56 形式を含む)、非表示の行、外部リンク) | エラーセルがある場合 |
plausibility | bounds、new_categories、mean_shift | 誰かが信頼する前に、人が確認すべきですか? | いいえ — 最大でも REVIEW |
例を含むパラメーターの全リファレンス:docs/checks.md。
終了コードと CI
終了コードの意味は次のとおりです。
| code | 意味 |
|---|---|
| 0 | すべてのチェックに合格 |
| 1 | FAIL が1つ以上ある(--strict の場合は REVIEW/ERROR/チェック未実行でも該当) |
| 2 | FAIL はないが、REVIEW フラグが立った |
| 3 | 検証できた項目がない — チェックを実行できなかった、またはすべてのチェックがスキップされた |
| 4 | 仕様自体に問題がある |
GitHub Action として使えば、1行で設定でき、判定結果がジョブのサマリーに表示されます。
- 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 エージェントで andon を使う
andon はエージェントを内包するのではなく、エージェントに操作されることを前提に作られています。
--jsonは、安定したフィールド名を使った完全なレポートを出力します。実行可否の判断には終了コードだけで十分です。- エラーメッセージには、関係するソース、列、シートが示されるため、エージェントは推測することなく仕様を修正できます(「列 'Revenue' が見つかりません。列は次のとおりです:region、share_pct、revenue」)。
skills/verify-with-andon/には、Claude Code および互換性のあるハーネス向けのスキルが含まれています。このスキルは、分析を作成した後に仕様を書き、andon を実行し、判定結果を報告するという規律をエージェントに教えます。チェックに合格させるために許容範囲を緩める場合は、黙って変更せず、必ず明示するというルールも含まれています。- MCP サーバー。
pip install 'andon-verify[mcp]'を実行し、andon-mcpを起動すると、MCP 対応ランタイムで3つのツールを利用できます。run(仕様を実行)、inspect(仕様なしでワークブックの整合性をスキャン)、diff(2つのバージョン間の変更を分類)です。エージェントは、人間が受け取るものと同じ構造化された判定結果を得られます。解析し直さなければならない文章ではありません。
// 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。
私が実践しているルールは、分析を書いたエージェントが仕様も書き、andon run が終了コード 0 で終了するか、人間がすべてのフラグを確認して承認するまで、どちらも完了としないことです。
andon が対象としないもの
- データ品質プラットフォームではありません。 Great Expectations や pandera は、通常はデータウェアハウスに対して、コード内でパイプラインの中のデータを検証します。andon は、完成した成果物に含まれる主張、つまりレポートとそのソースの整合性を検証します。また、ほとんどの企業で実際に分析が行われる場である Excel を、主要な対象として扱います。
- LLM 評価ツールではありません。 モデルの出力を採点するのではなく、数値を再計算します。
- レポートを読む作業の代わりにはなりません。 機械的なミスを減らすことで、人によるレビューを判断に集中させます。
制限事項について正直に
- 数式セルにはキャッシュ値が必要です。 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 はそう伝え、原因として考えられるものを示します。列名を黙って文字化けさせてから「検証」することはありません。
最後の 2 つは、見た目以上に重要です。指定しないと 1.234,56 はテキストとして読み込まれ、テキスト列は数値チェックで調べられません。andon は合格とせず、そのことを報告します(後述)。ただし、列をチェック可能にするには、まず数値の表記方法を指定する必要があります。
データを読み取れない場合のチェックの動作
すべてのレポートの末尾には、同じ一文が表示されます。PASS は分析に対する意見ではなく、これらの主張に関する算術的な判定です。 そのため、チェックでは、不注意な実装が一緒に扱ってしまう次の 2 つを区別する必要があります。
- 「比較したところ、問題ありませんでした」 — PASS。
- 「比較するものがありませんでした」 — PASS にはなりません。
そのため、妥当性チェックで数値が見つからなかった場合は、値が境界の外に 0 件あったと報告するのではなく、その事実を伝えます。
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 クエリを指定できます。これにより、CSV だけでなく、BI ツールが読み込むものと同じデータに対してレポートを照合できます。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%
2 つのワークブックのバージョンを比較する
「誰かがワークブックを編集しました。実際に何が変わったのでしょうか?」.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モード:ソースがディスク上で変更されたときに仕様を再実行
予定していないもの:ダッシュボード、スケジュール実行機能、検証ツール内での LLM 活用全般。 検証ツールは決定論的なままです。それが重要なのです。
このプロジェクトの開発方法
チェック項目を設計し、セマンティクスを決め、すべての行をレビューします。実装を速めるために AI エージェント(Claude Code)を多用しており、コミットのトレーラーにもその旨を記載しています。それが気になる場合は、まず tests/ をご覧ください。テストスイートはモックを使わず、実際の CSV と XLSX のフィクスチャを構築しており、これが仕様です。テストは誰がコードを書いたかを問いません。
関連プロジェクト
- opsaudit — 同じ着想を一段上のレベルで実現します。自らの数値を信頼するのではなく、監査するオペレーション分析ツールです。
andonは完成したレポートをそのソースと照合します。opsauditは誠実性チェックを組み込んだうえで指標を算出します。
Eren Gülmez によるその他のツール。
ライセンス
MIT — Mehmet Eren Gülmez
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。