0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

レビューエージェントには「どう操作したらそうなるか」を書かせるとよい

0
Posted at

この記事は AI エージェントと共同で書いています。構成は自分が行い、下書きをエージェントが出し、最終的な内容の確認と書き直しは自分で行っています。

レビューエージェントの失敗

エージェントに実装を依頼しました。しかし、1,000 行で終わるはずだった実装が、気づいたら 4,000 行を超えていました。

小さなコードの隣で、レビューロボットの指摘に従って実装ロボットが防御層を積み上げ、コードが塔のように膨らんでいる

原因となったのはレビューエージェントです。

私は個人プロジェクトで、開発を全自動化しています。Linear に issue を書くと、エージェントが実装して、その後に別のエージェントがレビューします。指摘があれば持ち帰って直してもう一度開発を行い、指摘がなければ issue を完了にします。

issue → 実装エージェント → 静的解析 → レビューエージェント (別プロセス)。指摘ありなら実装エージェントに戻り、指摘なしなら完了

このレビューエージェントを入れた後に、実装が暴走しました。

現実には起こらないエッジケースを直し始める

たとえば「タスクの期日が今日なら一覧の先頭に出す」という issue に対して、レビューエージェントはこういう指摘を返していました。

  • 攻撃者が DB に直接アクセスして期日に不正な値を書き込んだ場合の防御がない
  • 設定ファイルが手で壊されたときの復旧経路がない
  • 期日の取得中にネットワークが切れた場合のリトライがない

静かな自室で、レビューロボットが窓から侵入する泥棒やハンマーで壊される設定ファイル、切れたケーブルを想像している

攻撃者が DB に直接アクセスできる時点でセキュリティは崩壊していて、レビュー以前の問題です。そうなったらアプリの防御どころではないです。

でも実装エージェントは律儀に全部直します。指摘が出るたびに防御層が一枚増え、増えた層に対してまた指摘が出る。修正のたびにコードが増え続け、想定の 4 倍の実装になっていました。

原因ははっきりしていて、レビューエージェントの定義をエージェント自身に書かせたことです。頼めば「完璧なレビューエージェント」を定義してくれます。完璧なレビューは、どうでもいいことまで見ます。そしてレビューの網羅性は、そのまま実装量に変換されます。

なので、まずスコープを狭く書きました。

通常操作で再現する blocking / major の問題だけを扱う。非現実な手動での state 改ざん、通常生成されない不正入力、攻撃を前提にした多層防御は扱わない。

これで大きく減りました。ただ、これは対症療法なので、リストに書いていない種類の指摘はこれからも行われ続けます。リストを伸ばし続けるのは筋が悪い気がして、翌日「レビューエージェントの作り方の研究はあるか」を調べました。

調べているうちに、指摘の内容を制限するのではなく、指摘に証拠の形式を要求するという発想に出会いました。元になったのは準形式的推論という手法です。

ヒントにした準形式的推論

Ugare と Chandra が 2026 年 3 月の論文で提案している手法です。

arXiv:2603.01896, Shubham Ugare, Satish Chandra, 「Agentic Code Reasoning」

コードを実行せずに読んで意味を判断するエージェントは、自由に考えさせると根拠なしに推測します。別ファイルの同名関数を標準ライブラリと取り違える、エッジケースを見落とす、といったことが起きます。かといって Lean や Coq のような完全な形式検証は、実務のコードベースには重すぎます。

その中間として、自然言語のまま推論の過程を「証明書」のような型に押し込みます。この論文内の型は 5 段で構成されています。

  1. 関数トレース表: 調べた関数、ファイル、行番号、確認した動作
  2. データフロー: 重要な変数が関数間でどう伝わるか
  3. 証拠つきの主張: 主張ごとに裏付けのコード片や条件式
  4. 代替仮説の検証: 特定条件で主張と違う挙動がないかをコードで確かめる
  5. 結論: 1〜4 の証拠だけから導く

左は雲を浮かべて推測するロボット、中央は 5 つのチェック付きの証拠カードを掲げるロボット、右は歯車と錠前だらけの重い石板を持ち上げるロボット。中央が準形式的推論

肝は、話題を禁止するのではなく、主張に証拠の形式を要求することです。証拠を書けない主張は出せなくなる。この結果、論文ではパッチが等価かどうかの判定精度が 78% から 88% に、エージェントが生成したパッチでは 93% になったとあります。

ただ、全部やると出力が長くなりますし、レビュー結果を毎回人間が読む用途には重い。なので自分のプロジェクトでは、この手法をそのまま入れるのではなく、考え方だけを借りました。指摘 1 件ごとに「どう操作したらそうなるか」を必ず書かせる、それだけです。論文の 5 段で言えば 3 番の「証拠つきの主張」に近いものです。

「失敗シナリオを書けない指摘は出せない」にした

レビュー用のプロンプトに 1 行足しました。

各指摘には「入力または状態 → 実行経路 → 失敗結果」の具体的な失敗シナリオを必ず付ける。書けない候補は指摘にしない。

入力・経路・結果の 3 ブロックが矢印でつながったカードを、レビューロボットの手が開発者の手に渡している

これで「バグになりそう」「心配」だけの根拠のない指摘は出せません。

なぜ効くのかというと、さっきの「攻撃者が DB を書き換えたら」は、最初の「入力または状態」の欄が書けないからです。通常操作でその状態に至る経路がない。書こうとすると「攻撃者がサーバーに侵入して」から始まり、それは issue の要件違反ではないので、エージェントは自分で取り下げるしかない。

つまり、どう操作したらそうなるかを書かせることは、その指摘が現実に起きるかどうかをエージェント自身に考えさせることです。人間が「これは見るな」と禁止したのではなく、書く過程で自分で判断して捨てている。だから禁止のリストを増やさなくても出てきません。

逆に、指摘はこういう形になります。先ほどと同じ「期日が今日なら先頭に出す」の issue に対する、導入後のレビューです。

tasks/list.ts:42 [major] 日本時間の夜に作ったタスクが「今日」扱いにならない
失敗シナリオ: 期日が今日の 23:30 のタスクがある状態で 22:00 に一覧を開く → isToday が UTC の日付で比較する → 日本時間ではまだ今日なのに明日のタスクとして扱われ、先頭に出ない

これは普通に起こる可能性がある状況で、読んだ人間が直すべきかどうかをその場で判断できます。以前の指摘は「〜の場合の防御がない」のように、それがどういう操作で起きるのかが書かれておらず、直すべきかどうかを読んだ人間が判断できませんでした。

これ以降、レビューエージェントの指摘に納得できないことが少なくなりました。

まとめ

私がレビューエージェントを作るなら、最初にプロンプトに足すのはこの 1 行です。

各指摘には「入力または状態 → 実行経路 → 失敗結果」の具体的な失敗シナリオを必ず付ける。書けない候補は指摘にしない。

「報告しないリスト」を伸ばすより、証拠の形式を 1 つ要求するほうがよく効きました。

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?