ashineko

AIエージェントを開発の輪の中に置く — 仕様、計画、そして敵対的レビュー

一人のチームが19のツールを持つSaaSを出せた理由は、Claudeのエージェントをレールの上に載せたこと。そしてそのレールが、私ならそのまま出していた欠陥を捕まえてくれたこと。

2026 · ai

コミット
394
約3か月でmainに
設計仕様
50
コードより先にコミット
ハーネスページ
54
1機能につきHTML1枚
バックエンドのテスト
332
破壊的なリリースの前に

背景

MemberHubは19のツールを持つマルチテナントのSaaSで、ゼロから約3か月で立ち上がりました。最初のコミットが2026年4月9日、7月半ばの時点でmainに394コミット。エンジニアは一人です。コードのほとんどはAIエージェントが書き、私は決め、レビューし、運用しました。

レールの根拠はエージェント論ではなく、環境についての二つの事実です。一つ目、開発機がそのまま本番であること。作業ツリーが本番のトラフィックを、共有された本番のデータベース相手にさばいていて、失敗を吸収してくれるステージング層はありません。二つ目、このプロジェクトは本当に破壊的なことをすること。あるリリースでは760行のレンダリング用コンポーネントを削除し、稼働中のテーブルから約40のカラムを落としました。

だからこの手順は、モデルを信用するかどうかの話ではありません。昨日の記憶がなく、途中で質問することもできず、書かれたとおりに正確に動く有能な働き手に仕事を渡す前に、何を書き出しておかなければならないか、という話です。

作ったもの

パイプラインの形は決まっています。ブレインストーム、コミットされた設計仕様、実装計画、複数エージェントによる実装、敵対的レビュー、実ブラウザでの検証、そしてデプロイ。その成果物はコードの隣、同じリポジトリに置いてあります。日付入りの設計仕様が50、実装計画が25、運用ランブックが2、ブラウザ用のハーネスページが54。394コミットのうち74がドキュメントのコミットで、その多くは説明する当のコードより先に入っています。

  1. ブレインストーム
  2. 設計仕様
  3. 実装計画
  4. 複数エージェントで実装
  5. 敵対的レビュー
  6. 実ブラウザで検証
  7. デプロイ

仕様は、決定と一緒に「負けた選択肢」を書き残し、設計中に実際に確かめたことも書きます。ある仕様は「データ移行は不要」と結論した根拠として、まず本番を問い合わせて移行すべきものが何もなかったことを記しています。

計画は、人が斜め読みするためではなくエージェントのために書きます。行番号つきでファイルを名指しし、挿入するコードを持ち、各タスクの最後は「このタスクが触ったファイルだけをコミットせよ」で終わり、順番に走るタスクのあいだにはProduces/Consumesの契約を宣言します。そしてどの計画も冒頭に、この環境の危険を書いたGlobal Constraintsの節を持ちます。この箱は共有DBを持つ本番である。実装タスクはmigrateもcollectstaticもサービス再起動もデプロイもしてはならない。まとめてステージするな、同じツリーに私の書きかけの仕事が置いてあるのだから。

独立した作業は、ファイル単位で重ならない単位(バックエンド、コンポーネント、ロケールファイル)に分けて並行させます。分岐の前にAPIの契約を仕様の中で凍結してあるのが肝で、並行するエージェントが安全なのは、その間のインターフェースが事前に決まっているときだけです。実装の途中で発見されるようなものであってはいけません。

バンドラもJavaScriptのテストフレームワークもないので、検証はハーネスページの集まりです。1機能につきHTMLファイルが1枚、本物のモジュールを読み込み、本物のブラウザが返す結果の配列にアサーションを積み上げます。そのブラウザを操作するのはエージェント自身なので、結果は主張ではなく一次証拠になります。何かを「通った」と言う前に、結果の配列を貼ること。

そのうえで、まっさらな文脈を持つ別のエージェントが差分と仕様を受け取り、「この変更のどこが間違っているかを見つけろ」と言われます。

レビューが見つけた三つ
レビューが見つけた三つ

設計上の判断

横断する手順は、必ず一人が持つ。 バンドラがないので、変更したフロントのモジュールはキャッシュ回避のバージョンを上げる必要があります。ところが5体のエージェントがそれぞれコンポーネントを触ると、全員が「誰か別の子が上げるだろう」と無理もない推測をします。結果、誰も上げず、テストは通り、再訪した利用者が古いコードで新しいAPIを叩く。直し方は注意書きではなく所有権の規則でした。計画にはいらだちも一緒に書き込まれています。デプロイのタスクがキャッシュバスターを所有する、これは定番の教訓、実装者は必ず忘れる。

取り返しのつかない手順はオーケストレーターが握る。 実装エージェントはマイグレーションのファイルを生成してよいが、適用はしない。サービスの再起動もデプロイもせず、テンプレートも編集しません。テンプレートはソースから描画されるので、編集そのものが本番への変更だからです。破壊的な作業は、動いているコードが想定外のスキーマに出会う瞬間ができないように段階を分け、取り返しのつかないコマンドの直前には人間へ一行の予告が飛びます。

一行の変更にも全部の儀式を通す。 結局はスタイルを一つ受け渡すだけだった変更にも、却下した選択肢まで書いたコミット済みの仕様がつきました。軽い近道は検討したうえで却下しています。損得が非対称だからです。パイプラインの費用はエージェントの数分で、レビューを通っていない小さな変更が本番の箱の上で起こしうる損害には上限がありません。

うまくいかなかったこと

モデルが引退し、誰も教えてくれなかった。 このコードベースには言語モデルの呼び出し口が一つしかありません。四つのツールの「翻訳」ボタンの裏にある54行のヘルパーです。そこには日付つきのモデルのスナップショットが固定してあり、そのスナップショットが引退し、製品のAI翻訳が全部、上流の404を返すようになりました。こちらは何もデプロイしていません。約9日間、誰も気づきませんでした。翻訳は人が押したときだけ動く補助機能で、ヘルスチェックが叩く場所ではないからです。露見したのも、ストアの二言語エディタ、つまり四つ目の呼び出し元が、引退のあと初めての翻訳リクエストを送ったからでした。呼び出し口が一つだったおかげで、直すのはコミット一つで済みました。新しいモデルへの差し替え、応答の解析を「最初のブロック」ではなく「最初のテキストブロック」を取る形に直すこと、そして本番が何か月も動かしていた版に合わせてSDKの固定を直すこと。嘘をつく固定は、固定がないより悪い。まさにデバッグしている最中に、間違ったことを教えてくるからです。

数日前のコードを検証していたテスト。 キャッシュ回避のクエリ文字列が届くのは、テンプレートに書かれた入口のモジュールだけです。素のimportで読まれるものは素のURLのままキャッシュされ、ハーネスのURLに付けたパラメータはページを更新させてもその読み込み先までは更新させません。つまりブラウザは、数日前のモジュールを平然と「確認」できてしまう。修正後の偽の赤、もっと悪くすると修正前の偽の緑です。最初に計画へ書き込まれた対策 — 実行のたびに別のポートで配る — は手元では効きますが、配備済みのファイルには何もしません。実際に効く規則はもっと面倒でした。変更したモジュールをキャッシュを迂回して取り直し、そのうえでもう一度そのページへ移動する。ページが読み込まれたあとに温めても、そのページの読み込み先はもう直らないからです。いまはこれが全エージェントのプロンプトへ一字一句そのまま入っています。教わらなかったエージェントは、例外なく自力で痛い目を見て再発見したからです。ほとんど正しいだけの計画文は、古いコードの上に自信満々の緑を生みます。

修正そのものが次のバグだった。 あるレビューの回で、認証済みの利用者が自分の名前空間の外にあるストレージのキーに署名させられる経路が二つ見つかりました。その修正は図形データを歩き回るコードを足したのですが、そちらはツールごとの接頭辞ではなく全体の許可リストで検証していて、同じ種類の漏れを、今度は認証のいらない公開経路に持ち込みました。次の回のレビューがそれを捕まえます。修正のコミットが、閉じた指摘の番号を必ず引くようにしてあるのはこのためです。後から見る人が、前の修正が本当に効いたのかを確かめられます。

結果

証拠は履歴に残っています。ストレージまわりの移行一つに対して、4回のレビューを通じた21の修正コミット。どれも閉じた指摘の番号が付いています。カスタムドメインのレビューが足したテストが12件で、スイートは299件になりました。破壊的なリリースは、走らせる前に332件のバックエンドテストと255件のブラウザ側アサーションで確かめてあります。レビューの結果に言及するコミットの件名が11件。「クリーンなレビューだった」と書いてあるものも含めてです。

もっと大事なのは、レビューが「二人目のエンジニアがいる意味」に当たる種類のバグを捕まえたことです。テナント間の漏れ、Hostヘッダへの過信、二つのスケジュール実行が重なったときの二重送信、同時実行で衝突する注文番号、そして、すでに入っているデータより短くカラムを狭めるマイグレーション — 本番でしか現れようのない失敗です。

これは保証ではありませんし、書類にもそう書いてあります。これは規律です。次のエージェントと、次の私が読む場所に書き出してある、というだけのことです。