u-ryo's blog

AIエージェントの調査報告は一次証拠ではない

AIエージェント (Claude Code) に調査を任せる働き方を、ここ半年ほど本格的にやっています。レガシーな業務システムの影響範囲調査みたいな、SQLとJavaを何百ファイルも掘る仕事は、複数のagentに並列で投げると探索コストが桁で下がります。便利です。便利なんですが、先日ひとつやらかしまして、その反省文です。

何が起きたか

バッチのSQLの結合経路を調べさせたときのことです。多段のJOINで、あるソートキー列が表から表へどう引き回されているかを追わせたところ、agentがこう報告してきました。

子テーブルのソートキーは親テーブルと直接は紐付いていません。間のマスタで名称一致を取り直した後の値を経由しています。単純な「親 = 子」の結合ではありません。

具体的で、自信ありげで、「一見そう見えるが実は違う」という玄人っぽい形をしています。そしてこの報告は、検証されないままチーム共有の影響範囲ドキュメントの「未確認事項」欄に載りました。白状すると、この調査は報告の受け取りからドキュメントへの記載まで含めてAI主導の流れで回していて、人間の私はその門を素通しさせています。つまり誤読したのもAI、載せたのもAIで、人間は見ていなかった

後日、レビューで指摘を受けて該当のMapper XMLを読み直したら、誤読でした。構造だけ抜き出すとこうです。

INNER JOIN m_group g
        ON g.grp_id  = base.grp_id
       AND g.sort_no = base.sort_no   -- ここで g.sort_no は base.sort_no に固定される
       AND g.name_1  = base.name_1
INNER JOIN t_detail d
        ON d.grp_id  = base.grp_id
       AND g.sort_no = d.sort_no      -- 見た目はマスタ経由。実質は base.sort_no = d.sort_no

g.sort_no = d.sort_no と書いてあると、いかにもマスタ g 由来の値で結合しているように見えます。でも上で g.sort_no = base.sort_no と縛られているので、これは base.sort_no = d.sort_no と同値です。マスタのJOINが実際にやっているのは階層の絞り込みと名称一致による行選択だけで、ソートキーの値は何も変えていない。5分読めば決着する話でした。

教訓

このとき自分のノートに書いた教訓が3つあります。

その1: AIの報告は一次証拠ではない。 特に「一見そう見えるが実は違う」という形の指摘は、自分で該当行を読むまで信じてはいけません。人間の部下の報告なら、自信のなさが文面ににじむものですが、LLMの文章は間違っているときも常に流暢で具体的です。「具体的で自信ありげ」をフィルタに使う長年の癖が、AI相手では効きません。もっともらしさと正しさが無相関の相手だ、と思って扱う必要があります。

その2: 「未確認事項」への格上げは、検証をサボることの言い換えになりうる。 未確認と書けば嘘にはならない、という安心感が罠でした。自分で5分読めば白黒つく話を、読者の宿題にしていたわけです。以来、未確認事項に書く前に「これは自分で確かめられるか?」を一度問うことにしています。

その3 (これはAIと無関係の普遍教訓): SQLのエイリアスは値の出所を隠す。 g.sort_no と書いてあっても g 由来の値とは限らない。等値条件で他の列に固定されていれば、それはただの別名です。エイリアスを目で追うのではなく、その列に効いている等値条件を全部集めてから考える — これはAIにも人間にも効く読み方だと思います。

それでもAIに調査を任せる

じゃあAIの調査は使えないのか、というと逆で、この一件の後もほぼ全ての調査をagentに任せています。探索の大半は正しく、コストは桁違いに安い — と、ここで「8〜9割は正しい」と書きかけて、出典のない数字だと気づいてやめました。体感です。本稿の教訓は、こういうところにまで効きます。変わったのは運用ルールで、

要するに「信頼するな」ではなく「検証できる形で報告させろ」が実務解でした。

ところで、この「最後の門番」も結構な負担です。次回は、その検証自体をAIにやらせる話 — 書いた本人の文脈を一切与えない別セッションのAIに、成果物を敵対的にレビューさせる運用 — を書きます。

(この連作は、AIエージェントを業務のレガシーシステム保守で半年ほど運用して溜まった実践則を、1本1則で書いていくものです)