Paul Jialiang Wu agentic-portfolio English 中文 Español 한국어✉️ 無料リスト
← ポートフォリオへ戻る

AI-Nativeシリーズ・エージェント型エンジニアリング

アプリはずっと「完了」と言い続けていた。だがそれは嘘だった。だから、アプリ自身に監査させることにした。

著者:Paul Jialiang Wu · agentic-portfolio-lovat.vercel.app · 2026-08-01

1分でわかる要点――この記事から得られること

AI共同開発者と作っているあるアプリが、ユーザーに「ログインリンクを送信しました!」と表示した――その裏にメール送信サービスは存在しなかった。バグを一つずつ潰していく代わりに、私たちは製品が交わすすべての約束(80個)を書き出し、そのうち20個に機械チェックを組み込んだ。正直なスコアボードは1日で緑6個から15個へと増え――そして監査役は、誰でも入り込める管理者用のドアを見つけ出した。うまくいった理由は、たった一つのルールに尽きる。すなわち、証拠なくして合格なし。

高齢者向け自叙伝アプリと、嘘をついた成功トースト、そしてモグラ叩きに終止符を打った主張台帳についての、build-in-publicな物語。約8分。

The app kept saying done — it was lying. A scoreboard going from 6 to 15 verified claims, with the lies it told on the left
誠実な監査の1日でわかったこと――アプリが交わしていた約束と、実際に証明できたことの対比。

嘘をついたトースト

私が開発しているのは新遗产传记(New Legacy Biography) — 高齢者に寄り添うAIインタビュアーが、孫世代が生前ついぞ思いつかない質問を投げかけ、その答えを本の各章に仕立てていくアプリだ。バグが単なる不便では済まない類の製品である。祖母が育った川のほとりの物語をソフトウェアが失えば、それは再ダウンロードの効かない何かを失ったことになる。

このプロジェクトでの共同開発者はAIエージェントだ。開発は速い。ユニットテストは全135件がグリーン。TypeScript strict modeもクリーン、Lintもエラーゼロ。ところが私が一般ユーザーになりすまし、メールリンクでログインを試みると、画面にはこう表示された。「登录链接已发送!」(訳:ログインリンクを送信しました!受信箱をご確認ください)

メールは一通も届かなかった。届くはずがなかったのだ。本番環境にはメールサービスがどこにも設定されていなかったからである。コードには誰も読まないサーバーログにメールアドレスを出力するだけの「開発用フォールバック」があり、それでいてユーザーには成功を報告していた。信頼していたゲートはすべてグリーンだったのに、製品は肝心のユーザーに嘘をついていたのだ。

さらに悪いことに、製品の核心である「家族を招待する」機能——親族が写真や音声メモを誕生日の思い出の本に寄せる機能——が生成する招待リンクは、こんな文字列で始まっていた。http://localhost:3000。私のデスクにしか存在しないコンピューターへのリンクだ。これを別の街に住む叔母に送ったところで、何も起こらない。しかも登録ページの唯一の導線が同じ幻のメール頼みだったため、しばらくの間、地球上の誰一人としてこの製品に新規登録できなかった——それでいてテストはすべてグリーンのままだった。

グリーンなテストが救いにならなかった理由

Edsger Dijkstra は1972年のTuring Award講演で、誰もが言いたがらない本質を突いていた。“program testing can be a very effective way to show the presence of bugs, but is hopelessly inadequate for showing their absence”(訳:プログラムのテストはバグの存在を示すには非常に有効な手段となりうるが、バグが存在しないことを示すにはまったく不十分である) [1]。それから54年、AI支援開発はこの警告を和らげるどころか、むしろ鋭さを増している。生成ツールは「完成しているように見える」コードを作るのが極めて得意だからだ。完成しているように見えるユニットテストが検証するのは関数であって、誰も検証していなかったのは約束.

だった。長年MLプロダクトを手がけてきた Hamel Husain も、同じ診断を現代の言葉で言い表している。“I’ve found that unsuccessful products almost always share a common root cause: a failure to create robust evaluation systems”(訳:うまくいかない製品にはほぼ例外なく共通の根本原因がある。それは、堅牢な評価システムを構築できていないことだ) [2]。彼の論のうち借用に値するのはこの部分だ——評価システムがなければ、一つの不具合を直しても別の不具合が浮かび上がるだけだ。彼はこれを「モグラ叩きゲーム」と呼んでいる。[2]。まさに私のその週がそれだった。メールの嘘を直せばlocalhostのリンクが見つかり、リンクを直せば音声入力が未デプロイのモデルファイルを必要としていることが判明する。誰もスコアをつけていなかったせいで、どのモグラも不意打ちだった。

発想の核:主張台帳という仕組み

アイデアの全体像はこうだ。この記事がなくても明日には再現できるくらいシンプルなものである。製品が交わすすべての約束——ボタン一つ、ナビ項目一つ、マーケティングの一文一文——は主張。機械チェックのない主張は、単なる噂だ。 というわけで:

  1. 主張をデータとして書き出す。 頭の中でも、ドキュメントの中でもなく、コードが読めるファイルの中に書く。私たちのファイルには「亲友无需注册可上传照片」(親族は登録なしで写真をアップロードできる)や「新用户可以完成注册」(新規ユーザーが実際に登録を完了できる)といった項目が並んでいる。
  2. 各主張には、ユーザーと同じ動きで検証する1つのチェックを与える。 実際のブラウザが本番サイトの実際のフォームに入力する。クッキーなしのリクエストが、叔母がやるのと同じ方法で招待リンクを開く。
  3. 2段階ではなく3段階で正直に採点する: PASS、FAIL、そしてNOT MEASURED。この3つ目の等級こそが要だ。チェックできなかった主張は除外され、こっそり合格扱いにされることはない。
  4. それをゲートにする。 ゲート対象の主張が失敗すれば、実行は怒って終了する。偽の✅より、正直な❌のほうがいい。
The claim ledger loop: promise becomes claim, claim gets a machine check against production, scored PASS / FAIL / NOT MEASURED, failures get fixed, the loop reruns
図で見る主張台帳。3つ目の等級——NOT MEASURED——が、残りの2つを正直に保っている。

1日の正直さがもたらしたもの

本番環境に対する最初のフルランでは、スコアは6件PASS、11件FAIL、3件NOT MEASURED——機械チェック対象20件の主張のうちだ。アプリの大半がガラクタだったからではない。何ヶ月もの間、誰もアプリに何も証明させていなかったからだ。その日の終わりには、15件PASS、そして残る各FAILには、漠然とした嫌な予感の代わりに、名前と範囲のついた解消策がついていた。

読む価値のある3つの発見:

パターンと反パターン

うまく機能したパターン:

痛い目を見たアンチパターン:

その仕組みには名前がある。生成系ツールは、もっともらしい完成度――つまり見た目だけ完成しているコードを作ることを最適化している。その目的関数のどこにも、メールが実在しなければならないという制約はない。だからこそ、偽の完成へ向かう圧力は道徳の問題ではなく構造の問題であり、対策もまた構造的でなければならない。

第一原理を一文にまとめるなら、証拠なきものにパスなし、である。

月曜日から使えるやり方

時間を区切って、具体的に進める。ひとつの作業セッションで完結する内容だ。

  1. (30分) 自社プロダクトのランディングページとナビゲーションを開き、そこで語られている約束を20個、そのままJSONファイルに書き出す。
  2. (2〜3時間) それぞれについて、ユーザーがするのと同じようにその約束を検証する、できるだけ単純なチェックを書く。ヘッドレスブラウザや curl を使い、対象は本番環境であって、ステージング環境が対象ではない。各claimに印をつけるgate: true/false.
  3. (10分) 実行する。PASS、FAIL、NOT MEASUREDを、チームの誰もが見られる正直な一覧表として公開する。
  4. 成功はただ一つの数字で測る、ゲート対象のFAILがゼロであること。そしてこの実行をCIに組み込み、静かに腐っていくことがないようにする。自信満々だったリリースを止めてくれた瞬間に、うまくいっていることが分かるはずだ。

我々のものはリポジトリの中にあり、eval/claims.json + eval/run.mjsとして置いてある——20個のclaim、1つのコマンド、正直な出力。このパターンは、私が常設の規律として保持しているOECループ(Observe → Evaluate → Control)の一適用例であり、観測可能性は評価に先立ち、制御フックのない評価はただのスコアボードにすぎない。

ソフトウェアだけの話ではない

この一件が起きたアプリはすでに稼働中だ。北京語で語りかけ、耳を傾けるAIインタビュアーが記憶をたどってキッチンにまで踏み込む——先週のあるテストインタビューでは、なつめと竜眼干しの香りがする記憶だった——そしてそれを章として書き起こす。さらに、「私の本はどこまで進んでいる?」という問いに実データから答える相棒エージェントも備えている。今週このアプリが手に入れたのは、どんな機能よりも珍しいものだ。自分自身について正直に語る習慣である。記録しようとずっと思っている親御さんの話があるなら、ここにある——そして、このアプリがまだ何をできて何をできないかを示すスコアボードは公開されている。それこそ、私が何かを売り込まれるときに望む形だ。


参考文献

  1. Dijkstra, E. W. (1972). The Humble Programmer(ACM Turing賞講演), EWD340: "program testing can be a very effective way to show the presence of bugs, but is hopelessly inadequate for showing their absence."(訳:プログラムテストはバグの存在を示すには非常に有効な手段になり得るが、その不在を示すには絶望的に不十分である) cs.utexas.edu/~EWD/transcriptions/EWD03xx/EWD340.html
  2. Husain, H. (2024). Your AI Product Needs Evals. "I've found that unsuccessful products almost always share a common root cause: a failure to create robust evaluation systems"(訳:うまくいかない製品には、ほぼ必ず共通の根本原因がある。それは、堅牢な評価システムを構築できていないことだ)。症状について:"Addressing one failure mode led to the emergence of others, resembling a game of whack-a-mole."(訳:ある不具合を直しても別の不具合が現れる、まるでモグラ叩きのようだった) hamel.dev/blog/posts/evals

AI-Nativeシリーズ、その他の記事

AI-Nativeシリーズの一篇。この記事のすべては、失敗も含めて公開された評価台帳から再現可能だ。証拠なくして合格なし。Publishボタンを押すのはあなただ。