モデルを新しいものに差し替えたとき、返答をいくつか読んで「大丈夫そう」で済ませていませんか。私はそれで痛い目を見ました。
エージェントのモデルを3分の1のサイズのものに載せ替えて試したとき、返答は全部それらしく見えたのに、裏では cancel_subscription のツール呼び出しが消えていました。エージェントは「解約が完了しました」と言い続けていました。テキストのdiffではこれは見つかりません。言葉は正しくて、挙動が壊れていたからです。
それで whatbroke というCLIを作りました。2つの実行トレースを比較して、どのツール呼び出しが消えたか、引数がどう変わったか、コストとレイテンシがどれだけ動いたか、最終出力がどう変わったかを報告します。
リポジトリ: https://github.com/arthi-arumugam-git/whatbroke
インストール
npm install -g whatbroke-cli
npx でそのまま実行もできます。
使い方
- 変更前のエージェントでトレースを記録する
- 何かを変える(モデル、プロンプト、フレームワークのバージョン、なんでも)
- 同じシナリオでもう一度記録する
- diffを取る
whatbroke diff before.jsonl after.jsonl
トレースの記録はプロキシが一番手軽です。コードの変更はいりません。
whatbroke record --out traces/current.jsonl
OPENAI_BASE_URL=http://127.0.0.1:4141/v1 node my-agent.js
# または
ANTHROPIC_BASE_URL=http://127.0.0.1:4141 node my-agent.js
LLM呼び出し、ツール呼び出し、最終出力がすべてJSONLに記録されます。ストリーミングもそのまま通ります。
何が検出されるか
| 検出内容 | 重大度 |
|---|---|
| 実行が失敗するようになった、ツール呼び出しが消えた、出力が消えた | breaking |
| ツール引数の変化、新しいツール呼び出し、呼び出し順の変化、レイテンシやコストの悪化 | changed |
| モデルの変更、トークン数の大きな変動 | info |
breakingが出ると終了コード1になるので、そのままCIに入れられます。
- run: node run-agent-suite.js --out traces/current.jsonl
- run: npx whatbroke-cli diff traces/baseline.jsonl traces/current.jsonl --md >> "$GITHUB_STEP_SUMMARY"
エージェントは毎回同じ動きをしない問題
同じシナリオを3回ずつ記録して、run idに #1 #2 #3 を付けると、whatbrokeが全組み合わせを比較して各検出に発生率を付けます。
! issue_refund called with different args (amount) (6/9 run pairs)
変更前のサンプル同士でも起きている変動は「元からフレーキー」として格下げされます。残るのが本物のシグナルです。
既存トレースの取り込み
LangfuseやLangSmith、OpenTelemetry(GenAIセマンティック規約)のエクスポートがあれば、再記録せずに変換できます。
whatbroke import traces-export.json
evalとの違い
evalは各バージョンをルーブリックで採点します。whatbrokeは別の質問に答えます。この2つのバージョンの間で、ツール呼び出しレベルで正確に何が変わったのか、という質問です。ルーブリックを書く必要も、judge用のAPIコストもありません。
決定的でオフライン動作、APIキーも不要です。トレースはローカルの外に出ません。
英語版はこちらに書きました: https://dev.to/arthiarumugam/the-20-minute-check-i-run-before-swapping-an-agent-to-a-new-model-1kgi
日本語は翻訳ツールの力を借りています。おかしな表現があればコメントで教えてください。フィードバックやIssueも歓迎です。