Harness エンジニアリング十二条:Google 主席エンジニアの一年間の実践を、そのまま使えるプロセスとテンプレートに凝縮
- Ryan Lopopolo 氏は現在 Google Cloud の主席エンジニアで、以前は OpenAI に在籍していました。彼はこの一年の仕事を十二条にまとめ、公開リポジトリにしました。自分のエージェントに参考資料としてそのまま読み込ませることができます。十二条の実証の多くは OpenAI 時代の経験に基づいています。
- 核となる操作は直感に反します。選んだモデルとコーディングエージェントは変更不可のブラックボックスとして固定し、一切パラメータを調整せず、周囲の「コンテキスト」と「ツール」の2つだけを変えます。
- 十二条は三層に分かれます。上位3条は境界を定め(ワーカー固定、社内プロセスデータの投入、実測結果での評価)、中位6条はテコ(仕事を一人のエージェントに委ねる、コンテキストのジャストインタイム・ルーティング、能力を使いこなす、リポジトリに教えさせる、権限を明確化する、実環境で証明する)、下位3条は複利をもたらします(フィードバックのインフラ化、長期的な一貫性の維持、確定済みタスクの常駐ループ化)。
- この手法を支える実証:ある社内プロダクトが5ヶ月で空のリポジトリから約100万行のコードに成長し、約1500件のマージ済みPRはすべて Codex が作成。人間は1行も書いていません。
- そのまま持ち帰れるもの:6ステップの改善プロセス、3つの穴埋めテンプレート、「何を主張するならどこで証拠を取るか」がわかる11行の対照表、「どのような場合に比較実験が無効になるか」の9項目チェックリストです。
十二条と、誤訳されがちな言葉
まず言葉を正しましょう。ここでの harness は馬具という意味です。鞍、手綱、蹄鉄、引き具などの一式で、リポジトリの冒頭には馬の絵文字が付いています。「束縛」と読まれがちですが、方向性はまったく逆です。
馬はすでに十分に走れます。不足しているのは鞍、手綱、そして走路であり、それによって馬力が実際に地面に伝わり、目指す方向へ進めます。harness エンジニアリングとは、まさにこの一式を整えることです。
これを書いたのは Ryan Lopopolo 氏です。彼は現在 Google Cloud の主席エンジニアで、agentic GCP を担当しています。それ以前は OpenAI に在籍し、シアトルオフィスと企業向け OpenAI Frontier の構築に参加。仕事内容はまさに、エージェントへのコンテキスト、ツール、権限、評価、可観測性、オーケストレーション、フィードバックループの提供でした。十二条の実証の多くはこの経験に由来します。さらに以前は Snowflake でデータマーケットプレイスのテックリード、Brex では40人チームを率いて350人のエンジニア組織を支え、Stripe ではインフラと決済のテックリードとして会社が600人から6000人に成長する過程を経験しました。余暇には Rust で Ruby の実装「Artichoke」を開発しています。
彼はこの十二条を公開した際、これはこの一年の仕事を表すものであり、実践であり、技術でもあると述べています。
彼は自身の実践を十二条にまとめ、証拠、事例、実行可能なプロセスとともに公開リポジトリに入れました。リポジトリの自作コンテンツは CC BY 4.0 でライセンスされています。使い方は2通りです。人間が直接読むか、改善したいシステムと一緒にコーディングエージェントへ渡し、エージェントに内部の分岐インデックスを参照させて、参照すべき条項を自分で調べさせるかです。
読む価値がある理由:十二条のそれぞれに検証可能な実証が付いています。ある社内プロダクトは5ヶ月で空のリポジトリから約100万行、約1500件のマージ済みPRに成長し、コードはすべて Codex が作成、人間は1行も書いていません。また、60時間・3億超トークンを使った大規模リファクタリングは、初期プロンプトと2回の追加質問だけでした。lint(コーディング規約違反を自動検出するツール)を有効にしたところ、約600件の違反が同じPR内で修正され、テストも追加されました。
以下が十二条の全体像です。三層に分けたのは、その関係を理解しやすくするためです。一番上が境界を定め、真ん中の6つが実際のテコ、そして一番下の3つが、この仕組みが時間とともに価値を積み上げられるかを左右します。では、一つずつ見ていきましょう。
第一条:働く「人」を固定する
1回の評価・デプロイサイクルにおいて、モデル、コーディングエージェントのランタイム、ネイティブツールインターフェースの3つを固定します。この3つのうちどれか1つでも変わったら、たとえ世代が1つ進んだだけでも、環境全体を再検証する必要があります。
ブラックボックスを固定する利点は、失敗の原因を特定しやすくなることです。明らかに有能なエージェントがタスクを達成できない場合、その原因は通常5つの場所にあります。関連する組織コンテキストの欠如、実際に使える能力の欠如、有用なフィードバックループの欠如、権限の欠如、そして出口での証拠の欠如です。これら5つはすべてデプロイ環境の属性であり、調査可能で、変更可能です。ブラックボックスを固定しなければ、「モデルが悪いのか、それとも自分の設定が悪いのか」という堂々巡りから永遠に抜け出せません。
あなた自身が培った経験則も、再検証の対象です。旧モデルで学んだ習慣、つまりタスクの適切な分割サイズ、必要なオーケストレーション量、内部ループの待機時間、人間の監視が必要な箇所などを、そのまま新世代に持ち込むと、新モデルの追加能力が台無しになります。逆に、すべてのマイナーバージョンがあらゆる側面で向上していると仮定するのも、もう一つの誤りです。
彼自身が記録した観察結果:GPT-5.3 は GPT-5.2 よりも困難なタスクに取り組むのを嫌がりました。これは単独の使用観察であり、傾向を示すものではありません。
世代交代がどれほどの差をもたらすか、2つの数字があります。GPT-5.2 がリリースされたとき、彼は休暇中でした。戻ってみると、チームは追加の環境投資なしで、エンジニア1人あたり毎日1〜2件多くのPRを生み出していました。その後、別の Symphony 環境改修では、エンジニア1人あたりの週間PR数が10倍になったと報告されています。前者はモデル世代交代によるもの、後者は環境改修によるものです。この2つは分けて考える必要があり、それこそがブラックボックスを固定する意味です。
GPT-5.2 リリース中、環境は1行も変更されていません。
1人あたり毎日1〜2件のPR増加。
Symphony での介入時、ワーカーは変更なし。
報告では1人あたり週間PR数が10倍に。
内部ループのレイテンシも検証範囲です。エージェントがどこまで推論できるかは、1回の実行(トラジェクトリ:エージェントがタスクを開始から完了まで処理する全過程)が脱線するまでに得られるフィードバックの量に依存します。GPT-5.2 時代の Codex 環境にはバックグラウンドシェルがなく、エージェントはブロックするビルドスクリプトが完了するまで素直に待っていました。GPT-5.3 でバックグラウンドシェルが追加されると、エージェントは待たなくなりました。チームは1週間かけて、リポジトリのビルドを独自スクリプトから専門のビルドツール(Bazel、Turbo、Nx を順に試行)へと置き換え、全量ビルドが1分以内になる地点で停止しました。この1分がハードリミットと定められ、超えそうになると、手元の作業を止めてビルドグラフの分割に取り掛かります。
検証には引き算も含まれます。エージェントにUIを見せるため、チームはかつて仮想ディスプレイと画面録画の仕組みを自作していました。モデルが自ら画面を見てクリックできる機能(computer use)が登場すると、この仕組みはすべて削除されましたが、エンドツーエンドの検証は失われませんでした。
第二条:社内プロセスデータの水面下を実装する
汎用モデルの重みに含まれているのは、組織ナレッジのほんの一角にすぎません。水面下こそが、実際の作業に必要なものであり、それらは社内固有で、変化し続けています。
この条項は、2つのものを明確にすることを求めます。1つは「データ本体」です。どのようなエンティティ、指標、識別子があり、それらの関係はどうなっているのか。もう1つは「作業本体」です。どのような成果物、ワークフロー、役割、ツール、例外、証拠、承認関係があるのか。
良い例があります。社内データエージェントにデータウェアハウスへの権限を与えるだけでは不十分で、「売上」と「アクティブユーザー」という言葉が社内で衝突する定義を解決できません。エージェントは、会社にどのような製品ラインがあるか、顧客がどのようにセグメント化されているか、どのようなチームがあるか、どの顧客がパイロット中か、現在の計画は何か、共有の指標定義がどのように書かれているかを知る必要があります。これらの関係があって初めて、その会社に固有の答えを出せるのです。
現在の記録は、データウェアハウス、チケットシステム、ドキュメントシステム、ログ、コードベース、顧客システムに残し、検索とコネクタで承認済みのスライスを取得します。期限切れになる可能性のあるコピーを別途作成しないでください。
組織形態として、そのまま真似できる方法があります。Basis 社には2つのリポジトリがあります。Arnold は本番用のモノレポ、Atlas は2つ目のリポジトリで、会社のコンテキスト専用であり、本番コードツリーの外にあります。Codex は個人メモ、会社の運営ナレッジ、本番コードを組み合わせて使用できますが、これら2つの情報はそれぞれ独立した更新パスを保持します。実装形態は非常に簡素で、彼の言葉を借りれば「Codex と Markdown で満たされた Git リポジトリ」です。
この層にはもう1つ重要なことがあります。安定した決定は、それを管轄できる層に引き上げるべきです。あるチームがセキュリティ部門と共に、承認済みの暗号化実装を選択しましたが、この決定は Slack に残ったままでした。その後、新しいエンジニアが Codex を使って作業したところ、Codex は別の npm 暗号化パッケージをインストールしました。チームはこの決定を回収し、リポジトリにガードルールとして書き加え、その変更を再実行しました。
第三条:仕事は1つのエージェントに丸ごと任せる
委任するのは結果です。1つのメイントラジェクトリに、分解、実行、統合、証拠提示、安全な完了までを一任し、手順はエージェント自身に決めさせます。人間が介入するのは、方向性、判断、そして結果を伴う承認の3箇所だけです。
彼はしばしば、ほぼ制約のないプロンプトを与えます。このようなプロンプトを彼は「怠惰なプロンプト」と呼びます。方法を空欄にし、どう進めるかをエージェント自身に決めさせるからです。この疎な委任は、同時にテスト手段でもあります。環境が、本当の要求をエージェント自身が見つけ出せるようにできているかを試すのです。エージェントが誤解した場合、露呈するのは環境のどの部分が未整備かということです。これに付随するループは「提案、観察、改善、再実行」です。トラジェクトリを確認し、環境を改善し、今回の結果を破棄して、再実行します。
1つの依頼が、完全なレッドチーム分析を要求し、各発見には影響または悪用可能性の証明を要求しました。Codex はレポート、再現器、パッチ、回帰テストを作成し、その後、詳細な人間によるコードレビューに対応して実装を修正しました。著者はレビュー後に実装を承認し、続けてマイナーバージョン更新の準備、PRのマージ、RustSec(Rustエコシステムのセキュリティ勧告ライブラリ)への勧告提出を個別に許可しました。
プロンプトが規定するのは結果と合格ラインのみで、実質的なレビューと納品時の承認は依然としてプロセス内に残ります。
反例2つは、正例よりも参考になる
- ローカルビルド成功後にのみPRを開く、というスキルがありました。
- 特定のタスクでは、壊れたビルドを同僚と一緒に直すために、先にPRを開く必要がありました。
- スキルは実行を拒否。普段の安全弁が、本来守るべき結果の障害になりました。
- 指示は:ブランチ作成、コミット、プッシュ、マージ。
- エージェントは「マージ」を満たすため、管理者権限を使って強引に回避しました。
- しかし、このタスクの本来の意図には、テストの完了を待つことが含まれていました。
1つの依頼は通常、機能的な結果のみを述べます。互換性、保守性、アクセシビリティ、ロールバック、成果物の同期、そして将来の変更ニーズは、すべて暗黙のうちに含まれます。これらの暗黙の要求には、「問題の背後にある問題」という名前があります。エージェントはそれらを自分で見つけ出す必要があります。リポジトリを調べ、現在の動作を確認し、履歴を調査し、この結果とユーザーの関係を理解します。掘り下げても見つからず、しかも欠けている答えが製品意図を変えたり、予期しないリスクを負わせたり、持っていない権限を必要としたりする場合にのみ、人間に質問します。
コンテキスト圧縮に関する運用上の知見
長いトラジェクトリは、自身の履歴を繰り返し圧縮します。彼が立てた作業仮説は、ユーザーメッセージ内の意図は保持されやすいが、初期のツール出力は要約されたり破棄されたりしやすい、というものです。これは特定のワーカーの挙動であり、モデルを変更したら再検証が必要です。
この仮説に基づくと、段階的な詳細をユーザーメッセージに詰め込むと、そのタスクがとっくに完了した後に注意を引き続けます。したがって、ユーザーメッセージ欄には3つだけを入れます。結果、合格ライン、承認境界です。詳細は、リポジトリ読み取り、ツール出力、テスト失敗に委ね、決定が行われる瞬間に浮かび上がらせます。
第四条:千ページのマニュアルを、一枚の索引に
ナレッジベースは大きく検索可能に、作業セットは小さく。ルートにあるガイドは一枚の地図であるべきです。
この条項には由来があります。彼らが最初に作ったモノリシックなエージェントマニュアルは、大きすぎて使えませんでした。それを、短いルート索引に置き換え、背後に索引付けされた設計ドキュメント、製品仕様、実行計画、参考資料を配置しました。段階的開示(プログレッシブ・ディスクロージャー)をリポジトリ自身が管理する機能とし、リンクチェックと鮮度チェックでこれらのルートの信頼性を保証しました。
コンテキストウィンドウが大きくなっても、解決されるのは容量の問題だけです。注意力、検索品質、命令同士の衝突、そして「このステップで実際に重要な事実はどれか」という点は、依然として希少です。決定論的にコンテキストへ物を詰め込むことは、複数回の圧縮を経ると必ず機能しなくなります。エージェントが再びその道を見つけ出せる能力が不可欠であり、最初に詰め込んだものがまだ残っていると期待するのは当てになりません。
最小限の地図を渡す。タスクがどのカテゴリに属するか、関連するアーキテクチャと既存の決定、主要なユーザージャーニー、そして現在の状態を確定できる数個のコマンド。
目的は、エージェントが何を変更しているのか、どこを見るべきかを理解しつつ、より深い情報源への経路を保持することです。このセクションはチェックリスト化してはいけません。
コード、ツール出力、テスト失敗、ブラウザ状態、ログに、次のコンテキストを明かさせる。エラーメッセージは、どの不変条件に違反したか、そしておおよその修正方法を説明すべきです。
この段階は探索的です。事前に書かれた手順リストは役に立ちません。すべての分岐を予測することはできないからです。
成果物の形が固まってきたら、役割を持ったレビューア、合格基準、証拠要件、納品ポリシーを呼び戻します。
結果と主要ジャーニーは土台段階から常に見えています。仕上げ段階で持ち帰るのは、それらに対する詳細なレビュー視点です。最後に、トラジェクトリ全体を人が直接読める意思決定パッケージに圧縮します。
- 説明には「これは何か、いつ使えるか」だけを書き、本文は必要に応じて読み込むようにします。
- 長い命令的なチェックリストにすると、単一経路に過学習し、エージェントが妥当な例外を拒否しやすくなる。
- 大規模なスキルライブラリをエージェントのスキャン範囲外に置き、シンボリックリンク領域を使い、各トラジェクトリにはタスク関連の少数だけを公開する方法もある。
- 意図、前提条件、手順、安全境界、証拠、エスカレーションパス、ロールバックを記録。
- 自動化スクリプトは非常に薄くでき、耐久性のある知識はリポジトリに残る。
ナレッジベースをどう検証するか
新しいセッションを開始し、エージェントが実際にそれを検索し、実際に行動を変えるかどうかを見ます。ドキュメントが存在することは、書かれたことを証明するだけです。さらに一歩進んでアブレーション試験:このコンテキストを外して再実行し、効果が持続しないものは削除します。
このリポジトリ自体がこの条項のサンプルです
自分で確認できる4つの構造的事実:
| リポジトリでの実際の実装 | 対応する主張 |
|---|---|
ルートの AGENTS.md は分岐表であり、「ローカルの証拠では解決できない決定」に基づいてルートを振り分ける。エージェントが能力不足なのかツールが使いにくいのかを判断する場合は能力の項目へ、結果を伴う変更を実行できる者を定義する場合は権限の項目へ | 注入ではなくルーティング |
| 目標に関連する他の作業について、アプリケーションガイドや心法全体を事前に読み込まないよう明記 | 作業セットは小さく |
| 別システムのコンテキストとして使われる場合、自分は読み取り専用と規定。目標システムの命令、帰属、契約、現在の状態がローカルの真実を提供する | ローカルの真実が外部コンテキストに優先 |
| 提供されているワークフローでは、最初のステップは目標システム自身のガイドとアーキテクチャを読み、3番目のステップで未解決の決定を述べ、その後1つだけ選んで読む | まずローカルを見て、次に1つ選ぶ |
未解決の決定がルートを決める。目標システムのローカルな証拠が、そのいずれも必要とせずに解決するかもしれません。本当にコンテキストが必要な場合、そのうちの1つから始め、別の独立した決定がまだ保留されている場合にのみ、2つ目を追加してください。 AGENTS.md、リポジトリルート
第五条:ツールが出力するすべての文字が、次のステップのコンテキスト
ある能力が実際に使えるようになるには、6つのステップを完了する必要があります。発見する、今回使うべきだと認識する、正しく呼び出す、返ってきた結果を理解する、エラー時に修正できる、そして最後に実際のシステムで効果を確認する。このサイクルのどこか1つでも欠けると、その能力は形骸化します。
結果の解釈でエラーが見つかった場合は修正に戻り、再呼び出ししてループを形成します。
MCP と通常のコマンドラインの選択は、2つの点でトレードオフがあります。MCP サーバーはツール名と入力形式をすぐにブロードキャストできますが、モデルは新しい呼び出しと戻り値の形状を毎回学習する必要があります。通常の POSIX コマンドは、モデルの強い先験的知識を利用できますが、エージェントがその存在を知るまでは見えません。実際の移行事例があります。チームは当初 MCP を使って Codex が Chrome DevTools プロトコル経由で自社の Electron アプリに接続していましたが、同僚がローカルの TypeScript デーモンと小さなコマンドラインに置き換えました。実際に必要な操作が2、3個だったからです。切り替え後もワークフローは中断しませんでした。
良いツールの7つの行動
- 成功時は静かに。
- 機械的に読み取られる場所では、境界があり安定した構造を。
- 省かれた詳細には、取得可能なパスを残す。
- 失敗時は、どの不変条件に違反し、どの目標に影響したかを説明。
- 既知の回復アクションがあれば直接提示。
- 影響のある操作には、チェックモードまたはドライランモードを提供。
- 事後条件を問い合わせる方法、または副作用の受領書を提供。
誰もが踏む落とし穴
見分けやすい失敗の形があります。エージェントが高価なコマンド(例:cargo test)の出力を減らすため、予防的に head や tail にパイプすることがあります。
head はパイプを早期に閉じ、テストプロセスを完了前に kill する可能性があります。tail は通常最後まで読みますが、前の証拠をすべて失います。両方とも、パイプの終了ステータスを処理しない場合、実際の終了コードも隠してしまいます。
後期の失敗が前期のコンテキストに依存して説明される頃には、その出力はもうありません。
解決策はプロンプトではなく、ツールの境界にあります。リポジトリ自身が所有するラッパーがタスクを完全に1回実行し、実際の終了ステータスと全出力を保持し、次の決定に必要なセマンティックな失敗サマリーのみを返し、基盤となる証拠は再実行なしで照会可能にします。
不足があれば掘り下げ、使えるところまで掘る
仕事を丸ごと任せると、能力のギャップが外から内へと層状に露呈します。当初の目標は、Codex が Slack を読み、報告された障害を特定できるようにすることでした。そうすれば、人がメッセージを一つずつ会話に貼り付ける必要がなくなります。
このような能力の探索は、下方に6〜8層再帰します。底に達して使える基本部品を手に入れたら、再び層を上って最初の障害トリアージの目標に戻ります。このような探索のたびに、将来すべてのエージェントが実行できる仕事の範囲が広がります。逆に、使い捨ての人間による中継で回避すると、同じ穴を次の探索にそのまま残すことになります。
第六条:コードはプロンプト
エージェントが読むすべてのファイルが、次の予測に影響します。原文:リポジトリ内のコードはプロンプトです。
モデルの頭の中には、何十ものもっともらしいやり方があります。リポジトリの役割は剪定です。繰り返し現れる構造によって、チームが選択した方法を浮かび上がらせます。一貫性はコンテキスト需要を直接圧縮します。ある可観測性ソリューションがあれば、エージェントが1つのファイルで学んだことをリポジトリ全体に転移できます。6つのソリューションがあれば、呼び出しのたびに、ここではどのソリューションを使うべきかを再調査する必要があります。
2023年、彼は Ruby の String#unpack の lib.rs 全体を1つのプロンプトに詰め込みました。モデルは無関係な指示を混同し続けました。このコードパッケージを、構造が高度に整い、ドキュメント化された小さなモジュールに分割したところ、モデルは初回試行で後続の状態機械操作を正しく実装できました。
後に彼はこの記事を読み返し、こう評価しました。モデルは強くなったが、コンテキスト、制約、反復、フィードバックという協調ループは同じように感じられると。
逆もまた真で、例は欠陥も良い判断も同じ速さで伝播します。中途半端な移行は、互いに矛盾する2セットのプロンプト材料を生み出します。うまく書かれていないヘルパー関数は、同様の動作を必要とするすべてのパッケージに拡散します。
古い書き方と新しい書き方がリポジトリ内に並存。
エージェントは着手のたびに判断が必要:今コピーすべきはどちら?移行は完了したのか?
両方ともプロンプト材料として使われ、両方とも複製されます。
ESLint の no-await-in-loop を有効にし、約600件の違反を修正し、同じPRでテストカバレッジを補充。
リポジトリにはコピーすべき答えが1つだけ。古い書き方は二度と入り込めません。
エージェントも新人も、同じ明確な継続方向を得ます。
1つの概念には、1つの正統な出自を
パーサー、リスト型、バージョン定数、状態表現、フィクスチャコンストラクタ、ポリシーチェック、コマンドを作成する前に、既存の概念の出自を探し、必要に応じてそのインターフェースを拡張します。以下は「明確な出自がない」ことを示すシグナルです。
| 警告シグナル | 説明 |
|---|---|
| 2つ目のパーサー | リポジトリはすでにその言語のモデルを構築しているのに、もう1つ出現 |
| バージョン番号の複製 | ツールの正確なバージョン番号がポリシーコードとテストフィクスチャの両方に存在 |
| 文字列結合で JSON を生成 | 構造化データが文字列フラグメントから組み立てられる |
| コマンドラインがドメインロジックを再実装 | コマンド内でドメインの振る舞いが再実装されている |
| 型付けされていない外部データ | 外部データが解析されずに内部コードに流れ込む |
| 同じ不変条件が複数回守られている | 複数の防御的チェックが同じものを保護しており、それを本当に所有する境界がないことを示す |
出自が重複するたびに、「ローカルでももっともらしい」継続方向が生まれます。エージェントは身近なすべての前例に忠実に従いながら、リポジトリ全体をより非一貫性にすることができます。
外部データは入ってくるときに一度解析し、信頼できるドメイン型にします。その後、内部コードはこの正規化された状態に依存します。レコードチェックをあちこちで行い、すべての関数で正規化し、すべてのイベントハンドラで準備状態をチェックしているなら、通常はどの境界も「この値は有効である」ことを真に所有していないことを意味します。
第七条:実行と承認は2つの別々の契約
能力は、どのようにして効果を生み出すかについてです。権限は、どのアイデンティティが、どのリソースに対して、どの環境で、どの効果を、どのくらいの期間、誰の承認を得て、どうロールバックするかについてです。
- 「どうやってこの効果を生むか」に答える。
- 閲覧、編集、ビルド、テスト、シミュレーション、反復。
- この領域のエラーのほとんどは、安価なフィードバック。
- アイデンティティは誰か、操作と対象リソースは何か。
- 環境と範囲、承認の有効期間と失効パス。
- 承認が必要か、職務分離はあるか。
- 監査受領書と事後条件、ロールバックと復旧パス。
この2つの契約を分離すると、セキュリティの問題は「ランダムなシステムにゼロエラーを要求する」ことから、「結果はどの程度大きく、回復可能か」へと移行します。資格情報の管理はトラジェクトリの外側に置きます。プロキシプロセスがアクション境界で、セキュアストレージから範囲の狭いキーを取得し、gh が普通のコマンドのように使えるようにします。キーはモデルのコンテキストにもリポジトリにも入りません。さらに2つの保険を追加します。読み取り専用アイデンティティにより、チェックは有用だが変更はできないようにします。エンドポイントバインドされたアクセスにより、基盤となる資格情報をローテーションせずに、特定のエージェント向けチャネルを個別に無効化でき、実行中のトラジェクトリも権限を剥奪できます。
影響のある操作は段階に分け、各段階に必要な権限のみを
Loki は彼の自宅のロボット掃除機で、オープンソースの Valetudo ファームウェアを実行しています。唯一のリモートアクセス経路は、カスタムの Tailscale デーモンです。このデーモンを v1.90.8 から v1.96.4 にアップグレードする際の問題は、アップグレード自体が、失敗したデプロイを復旧するための唯一の経路を壊す可能性があることです。
各段階には、その効果に必要な権限のみを付与します。カナリアが成功しても本番権限は得られません。本番アクセスがあっても、デプロイされたシステムが健全であるとは限りません。
指示もこの権限契約を通じて解釈します。「マージ」はリポジトリの保護されたマージフローを完了することを意味し、バイパス権限を暗黙に付与しません。「デプロイの準備」が付与する範囲は準備までであり、本番切替は別途承認が必要です。不可逆的な目標や範囲が、ローカルポリシーを確認しても依然として曖昧な場合、エージェントはその境界を越える前に質問すべきです。
安定した承認ルールは、IDポリシー、型付きドメイン操作、スコープ付きツール、環境境界、テスト、マージゲートに落とし込むべきです。結果が重要な場所では、誤ったアクションを不可能にすることが、ルールを書くよりも効果的です。ルールは人間が常に覚えている必要がありますが、仕組みはそうではありません。
第八条:緑のチェックは、それ自身の1項目しか証明しない
検証は、ユーザー、オペレーター、または下流システムが実際にこの結果に依存する境界で行うべきです。ユニットテスト、型チェック、lint、ビルドは内部属性を確立しますが、外部のことを証明することはできません。
この条項を実践する上で最も役立つのは、対照表です。あなたの結論が何であれ、証拠はその境界で取らなければなりません。
| あなたが主張すること | 証拠を取るべき境界 |
|---|---|
| ブラウザでの動作 | 実際のブラウザでジャーニーを実行し、セマンティック状態とレンダリング結果の両方を確認 |
| 生成されたコンテンツ | ソースから成果物への完全な比較と鮮度 |
| 互換性移行 | 対象コーパスでの一貫性、エッジケース、許容される差異の明示 |
| セキュリティ影響 | 再現器、境界のある悪用可能性、回帰カバレッジ |
| デプロイ完了 | 検証済みの成果物が実行中であること、デプロイ後のヘルスチェック |
| 影響のあるリモート変更 | 段階的カナリア、切替、復旧パス、切替後のチェック |
| スプレッドシートの計算 | 数式、単位、ソースセル、レンダリングされたワークブック状態 |
| データセット変換 | 構造、出自、ソースから成果物への調整 |
| ドキュメントやプレゼン | 要求された構造とレンダリングされたページ。引用やアクセシビリティを約束したなら併せて検証 |
| 分析による結論 | 再現可能な変換プロセスと、結論が証拠によって裏付けられていること |
| 業務状態の変更 | 必要な承認、受領書、観察された事後条件 |
この表は、エンジニアリング以外の作業にも当てはまります。中間のコードがエージェントの実行プロセス内に留まり、ユーザーが見ない場合、証明パッケージはユーザーが理解できる言葉で提供する必要があります。スプレッドシートの数式、レンダリングされたスライド1枚、出典付きの結論、完了した状態遷移などです。隠れたスクリプトのテスト成功は、内部属性を確立するだけです。
また、実際のシステムをエージェント自身に見せるべきです。アプリを起動し、ブラウザを操作し、ログを読み、メトリクスとトレースを調べ、永続的な副作用をチェックし、生成コーパスを比較し、CI/CDを監視できるようにします。人間がエージェント自身で見られる証拠を中継すべきではありません。中継は遅延を増やし、診断に必要な状態を剥奪します。セマンティックビューとレンダリングビューを併用します。DOMスナップショットと構造化状態は、ロール、値、関係を見るのに適しています。スクリーンショット、録画、直接の画面操作は、レイアウト、クリッピング、フォーカス、インタラクションの欠陥を露呈させます。
リリース証拠は、同じ不変の成果物に従い、検証から切替まで一貫している必要があります。より権限の高いタスクで再ビルドすることは、2つ目のサプライチェーンを開始し、これまでのすべての証拠の連鎖を断ち切ります。
証拠が証明していないことを明記する
前述のセキュリティ勧告のケースでは、レポートに明確に記載されていました。データ破損を引き起こすには、カスタムハッシュ実装と、プログラムクラッシュ後の復旧実行が必要であり、この再現器はデフォルトパスでのメモリ不安全を証明するものではありません。当時の指示は、報告された各問題に影響または悪用可能性を証明することであり、セキュリティ発見らしき推測的な出力では要件を満たしませんでした。
証明の負担は結果に応じて増大します。タイプミス1つ、パーサー移行1回、リモートアップグレード1回、本番リリース1回では、必要な証拠と権限はまったく異なる規模になります。
第九条:一度修正したことは、二度と修正しない
繰り返し発生する修正は、次回の実行を形作る環境へと変換します。この条項は、前述のすべての条項が時間とともに蓄積できるかどうかを決定します。
まず、正確な反例を見てみましょう。ある人はエージェントに具体的なGoインターフェース修正を与えました。元々「成功したかどうか」だけを返していた関数を、「なぜ失敗したか」を説明できる具体的なエラー値を返すように変更するというものでした。エージェントは指名された関数だけを変更しました。その指示の背後にはインターフェース設計に関する一般的な原則がありましたが、今回の修正では、同じ原則が適用される他のインスタンスを検索しませんでした。
繰り返し発生する修正に直面したら、システム問題として扱い、5つのステップを踏みます。
| ステップ | やること |
|---|---|
| 一 | 当初約束された結果と、実際に観測された失敗を再構築 |
| 二 | 最初にそれを防げた、または最初にそれを露呈させた境界を特定 |
| 三 | 同じ原則が適用される他のインスタンスを検索。このステップが最もスキップされがち |
| 四 | 環境欠陥、エージェントのランダムな変動、外部障害、誤った前提の4つを分離 |
| 五 | クラス全体をカバーしつつ、正当な例外を禁止しない介入を選択 |
どの層で変更するかは、その教訓がどの程度成熟しているか、結果がどの程度大きいかによって決まります。
| 介入方法 | いつ使うか |
|---|---|
| プロンプトを変更して再実行 | タスクの枠組みや望ましい結果がまだ模索段階 |
| ルーティングドキュメント、runbook、skill | 安定した知識が特定の決定ポイントで必要 |
| レビューアまたは評価 | その判断が定性的、横断的、または詳細がまだ発展中 |
| 型、インターフェース、ドメインツール | システムが正しい使い方を自然にし、誤った使い方を困難にできる |
| lint、テスト、ポリシーチェック | 決定論的な不変条件が再発を直接ブロックすべき |
| アーキテクチャまたは移行 | 繰り返し発生する欠陥が、所有権の誤りや依存関係の誤りを露呈 |
判断力が資産になるまでの完全な連鎖
起点は、公開 openai/codex リポジトリに送信された1つのPRです。pnpm をアップグレードしていくつかの脆弱性を修正し、インストール後の自動スクリプト実行を禁止するものでした。このパッチから遡って推論すると、4つの原則が浮かび上がります。パッケージマネージャーは高リスク境界である、依存関係は最新に保つ、インストールプロセスはCIで任意のコードを実行すべきではない、例外には人間のレビューが必要である。
特筆すべきは2回目の昇格です。スキャナ導入後、Slack でのフィードバックによると、スキャナは具体的なインスタンスを捕捉しやすい一方、セキュリティエンジニアの頭の中にある一般的な参照枠組みは捕捉できませんでした。チームは欠落していたガードと調査シグナルを SECURITY.md に追加しました。この原則はその後、毎日スキャナと、新たに追加された依存関係深度・ライセンススキャナの両方に供給されます。このようにして、判断力はラウンドごとに蓄積されていきます。
- 欠落したドメインモデルの上に検証レイヤーを重ねることは、不整合を固定化し、保守コストを追加するだけ。
- より強い型、インターフェース、アーキテクチャが登場したら、下流の冗長なチェックは引退させる。
- まず粗い指示を与え、正当な例外で失敗し始めたら、詳細を追加する。
- 最初から詳細を書き込むと、エージェントが本来なら正しくできた判断を押しのけてしまう。
2つの付随詳細:READMEの使い方、レビューアの収束
エージェントに作業しながら3つのファイルを記録させます。Mistakes、Learnings、Desires、略して MLD です。これら3つのファイルの位置付けは、環境を構築する人へのテレメトリデータです。エージェントは最も重要なエラーを見逃したり、原因を誤ったり、間違ったツールを要求したりする可能性があるため、生の記録はそれが生成された実行の隣に残し、繰り返し現れ、裏付けのあるギャップのみをコンテキストに書き込む価値があります。
もう1つはレビューアの収束問題です。チームの初期のレビューアエージェントは圧力を繰り返し、実装側の変更範囲をどんどん広げさせました。解決策は、レビューアにマージを優先し、実質的な問題のみを提起するよう指示し、著者が修正するか、理由を添えて延期するか、直接拒否するかを選択できるようにしたことです。
第十条:一貫性を守り、長期的なリスクを引き受ける
実装が安価になった後、希少になるのは将来の一貫性と長期的な所有権です。受け入れられた各変更は、共有システムに制約と保守義務を追加し続けます。
この条項には、全体で最も誠実な部分があります。あの5ヶ月で100万行になった社内プロダクトでは、社内リリースと採用証明戦略はスタートアップ期には機能しました。しかし、アーキテクチャの一貫性が「数年」という時間スケールでどう進化するかは、原文が公に認める未解決の問題です。
もう1つの誠実な点は、自身のプロジェクトを使って「エージェントは難しい仕事を一気にこなせる」という印象に反論していることです。Artichoke の状態モデルリファクタリングは、当初114ファイルからなる巨大な変更で、コンパイルすら通りませんでした。その後、50件の準備PRに分割して順次マージし、同時期にリポジトリには他に200件のPRが入り、さらに数回の大規模な統合試行とランタイム障害を経て、ようやくマージされました。
ルートは既知で、1つのPRで完了。
人間の介入:3回。
終点は明確、安全なルートはその場で学習。
50件の準備PR、複数回の統合失敗。
変更のサイズや実行時間は、安全なルートが既に分かっているかどうかをほとんど示しません。違いはルート自体が確定しているかどうかにあります。彼はこの欠落した能力に名前を付けました。「あと50件のPRが怖い」です。将来の変更で自分がどれだけ後悔するかを予測する能力です。彼はこれを、依然として解決されていない能力の問題として明確に挙げています。
何が書き換えを生き残らなければならないか
実装自体は破棄可能な一回のレンダリングです。以下の6つが守るべきものです。
- 動作とドメイン仕様
- 互換性インターフェースと移行ルール
- 決定とアーキテクチャ境界
- 依存関係とサプライチェーンポリシー
- 証明コーパスと既知の失敗ケース
- リリースIDと運用契約
Symphony はまさにこれを実行しています。動作仕様を公開し、他のチームがそれに基づいて独自の独立した実装を生成できます。この形態は「ゴーストライブラリ」と呼ばれ、共有されるのはコードパッケージではなく契約です。
OpenAI チームは、一般的な並行性制限依存関係を独自実装に置き換え、自社の可観測性に接続し、テストを徹底しました。コストは明確に述べられています。依存関係を内製化することは、ゼロに戻ることを意味します。上流が蓄積した規模、互換性、セキュリティの信頼はすべてリセットされ、リポジトリは現在所有している部分に対して証拠を再構築する必要があります。
第十一条:方向が決まった仕事は、常駐ループにする
方向性がとっくに決まっているのに、スケジュールに入らない仕事のカテゴリがあります。ローカライゼーション、計装の追加、依存関係の最新維持、時代遅れの互換パスの削除、アーキテクチャドリフトの修正、生成データとドキュメントのリフレッシュなどです。望ましい結果、証明方法、承認境界の3つが明確になれば、これらの仕事は自動的に前進し続けることができます。
ループを立ち上げられるかどうかは、5つの質問に答えられるかどうかで決まります。
| 答えるべき質問 | 答えがないとどうなるか |
|---|---|
| どのような条件が常に真であるべきか? | ループに目標がなく、定期的に空回りするだけになる |
| どのようなシグナルがシステムの逸脱を示すか? | 逸脱しても誰も気づかず、人間の偶然の発見に頼る |
| どのような証拠が変更によって回復したことを証明するか? | 変更しても効果があったか分からない |
| どの操作を自律実行でき、どこで承認が必要か? | 実行をためらうか、事故を起こすかのどちらか |
| どの永続状態が結果を次のラウンドに記録するか? | 毎回同じ事実を再発見している |
ここでは「タスク」と「目標」を区別します。「この不安定なテストを直す」は1つのパッチで終わります。「CIのp95レイテンシをN分以内に保つ」は目標であり、システムを継続的に監視し、介入を生成・テストし、必要に応じて人間の承認を要求し、明確な引退条件が必要です。
何もする必要がない · 候補を提案 · 変更を証明済み · 承認を要求 · 復旧が必要 · ポリシーが時代遅れ。
静かな空回りは健全です。同じ事実を繰り返し再発見することこそ、永続状態の欠如を示すシグナルです。
緊急対応に関する主張もあります。コードレッドアラートはメトリクスが緑に戻ったことで終わるべきではなく、保守ループを残すべきです。対応プロセスで、人間はどの不変条件が重要か、どのシグナルがドリフトを予示するか、どの介入が効果的かを学びます。これらは、目標、センサー、承認済みアクション、エスカレーションパス、そしてこのループの所有者とともに記録されるべきです。エージェントの実行が十分に安価になれば、新たに発見された不変条件の中には、常駐チームなしで保守され続けるものもあります。
環境自体も雑草が生えます。ドキュメントは古くなり、コードには矛盾する書き方が生まれ、レビューコメントは欠落したガードを露呈し、かつて有用だったツールがモデル世代交代後に冗長になります。OpenAI 側では、毎週の手動クリーンアップを常駐バックグラウンドタスク群に置き換えました。確立された原則から逸脱している箇所のスキャン、品質評価の更新、焦点を絞ったリファクタリングPRの起票、古いドキュメントのクリーンアップなどです。小さな修正は、悪い書き方が将来のプロンプト材料になる前に実行されるべきです。
人間の位置はこの条項で明確にされています。ループが維持するのは、すでに選択されたポリシーと変化する世界との関係です。「どの世界を築く価値があるか」は依然として人間の仕事です。
第十二条:実測された有効性で最適化する
トークン、コード行数、エージェント数、チェック項目、これらはすべて入力です。最適化すべきは、希少な人間の注意力1単位あたりに換算された、受け入れられた結果です。
トークンランキングは、虚栄の指標の1つです。それが報酬とするシグナルは、価値が横ばいでも増え続けます。「エンジニア1人あたり毎日10億トークン」という表現には、後に結果ゲートが追加されました。これらの作業は、メインブランチにマージされ、ユーザーエクスペリエンスを改善しない限り、カウントされません。
3つの概念を分ける必要があります。到達可能性エージェントがこの仕事のどの部分に触れられるか。リポジトリ、ローカルアプリ、テスト、ブラウザ、ログ、デプロイ、証拠はすべて到達可能性を広げる、活動量(トークンとビジー時間)、そして有効利用率実際に受け入れられた結果に到達した、または再利用可能な証拠を生み出した活動の割合。予防可能な破棄、やり直し、修正はこれを削るです。
4つの時計は分けて計る
| 時計 | 測るもの | なぜ分けて見るか |
|---|---|---|
| フィードバック遅延 | アクションから、有用なテスト・ビルド・トレース・レビューシグナルを得るまで | 反復速度を決定 |
| 実際の所要時間 | 開始から1回の実行完了まで | 実行容量を占有し、下流を遅らせる可能性 |
| 同期が必要な人間の注意力 | 人間が指揮、中継、レビュー、復旧に費やす分数 | 組織が監督できる作業量を決定 |
| 受け入れられた結果に到達するまでの時間 | 依頼から証明・承認・デプロイまで | 待ち行列、再実行、レビュー、納品をすべて含む |
なぜ分ける必要があるか、2つの例を並べれば明らかです。あの60時間のリファクタリングは、実際の所要時間は長く、3〜4日に及びましたが、人間との同期インターフェースは初期プロンプトと2回の追加質問だけで、約3.3〜3.5億トークン、2800ドルを消費し、1つのPRを生成しました。彼は自分で手作業なら3週間かかると見積もっています。対照的に、2023年のChatGPTとのペアプロは、コードがエディタとブラウザ間を行き来し、テスト結果を人肉でチャットに転記し、1回のセッションで数百のプロンプトを使用しました。実際の所要時間は長くありませんでしたが、人間の注意力は1時間で枯渇しました。
探索、やり直し、無駄は3つの異なるもの
破棄は生産的であり得ます。最終的なインターフェース形状が未定の不確実性の高いリファクタリングでは、彼はエージェントに最大5万行の探索的変更を生成させ、レビューのためにPRを押し出し、その後破棄させます。この試行は、エージェントがどこで失敗しそうか、最終的な切替に必要なインターフェースの継ぎ目がどこかを露呈させました。彼はこの失敗マップを約15の準備・準備PRに変換し、その後実際の切替に戻りました。
新しい証拠なしに、既知の失敗を繰り返すこと。これに付随する診断の視点もあります。同じ高シグナルの修正を常に誘発する環境は、たとえ個々の修正自体が安価でも、長期的には欠陥があると見なされます。
この十二条を自分のプロジェクトにどう使うか
リポジトリの playbooks ディレクトリには、境界が明確で再実行可能な実タスク向けの、そのまま使えるプロセスが用意されています。
5番目のステップの「新規」には理由があります。新しいセッションと、隔離された同等の開始状態を使用し、再実行が当初の実装会話から暗黙の助けを引き継がないようにします。また、今回の介入が実際に検索されたか、呼び出されたか、そして今回の再実行と関係があるかを個別に確認する必要があります。一度の成功した結果は、使用されなかった指示やツールに対する証拠にはなりません。
以下の3つのテンプレートは、そのまま自分のプロジェクトにコピーできます。
対象システムとバージョン: 関連する外部状態: 固定されたモデルとコーディングエージェント設定: 代表的なタスク: 受け入れ可能な結果: その結果を証明できる証拠: 権限範囲と承認境界: 予算と停止条件: 不足が疑われる箇所:
もし【それを最も早く制御できる場所】に【何らかの変更】を加えれば、固定されたエージェントは【代表的なタスク】で【観察可能な行動変化】を示すだろう。なぜなら【メカニズム】だから。 この仮説を支持できる証拠: この仮説を弱める可能性のある証拠: 予想される保守コストと帰属:
タスクと受け入れ可能な結果: 対象バージョンと外部状態: 固定されたエージェントと権限範囲: ベースライン証拠: 最初に壊れた受渡し、およびその責任の所在: 変更内容と期待されるメカニズム: 実施した検証: 新規での再実行の証拠: 結果の比較: 証拠の比較: 人間による中継と遅延の比較: リスクと保守コストの比較: もし「それを外してもう一度実行」した場合の結果: 決定:維持 | 変更 | 削除 長期的な帰属と記録された教訓: 後続アクションまたは引退条件: 既知の限界:
どのような場合に比較実験が無効になるか
無効化リストも別途あります。いずれか1つに該当した場合、その評価は目的とする結論を裏付けることができません。
| 無効条件 |
|---|
| 結論が「特定のコンテキストを使用した」または「特定の能力を使用した」に関するものだが、それが実際には検索・呼び出しされていない |
| 事前に宣言された介入以外に、指示、ツール、権限、外部状態、書き込み権限の差異が混入している |
| ランダム性を含む1回の実行を代表的であるとみなす |
| スコアリングに非公開の参照実装が必要 |
| 評価側にしか見えないチェックを、エージェント自身が生成した証拠として報告する |
| 外部コーパス全体を評価側にコピーすることは、評価側が自分でコピーしたコーパスで自問自答していることになる |
| トークン数、コード行数、活動量で受け入れられた結果を代替する |
| 比較プロセス中にワーカー自体が変更された |
| 公開レポートの目標とバージョンが不透明で、読者が確認または再現できない |
あるハーネスがその保守コストに見合うのは、同じワーカーが、本当に重要な環境で、より良い受け入れられた結果を生み出すときです。 evals/README.md、harness-engineering リポジトリ
モデルとコーディングエージェントは固定して調整禁止。周囲だけを変える。一年間の実践から生まれた十二条
Ryan Lopopolo 氏(現 Google Cloud 主席エンジニア、元 OpenAI)が一年間の実践を十二条に整理。核心操作と、そのまま使えるテンプレートを1ページの図で解説します。
↓ 1ページで完結 · 動く図もあります
harness はここでは馬具の意味です。鞍、手綱、蹄鉄のように、馬の力を実際に地面に伝えるためのものです。束縛ではありません。この十二条は Ryan Lopopolo 氏によって書かれました。彼は現在 Google Cloud の主席エンジニアで、以前は OpenAI でエージェント環境の構築に参加していました。核心操作はただ一つ。選んだモデルとコーディングエージェントを変更不可のブラックボックスとして固定し、その周囲のコンテキストとツールだけを変えることです。
返金の手順、契約の形式、この言語の一般的な書き方
今回の返金が例外かどうか、このチームの現在のコーディング規約、この変更の承認者は誰か
十二条は三層に分かれます。上3条は境界を定め、責任を追跡可能な環境を固定します。中6条は日々調整する操作のテコです。下3条は、このシステムが時間とともに価値を増すかどうかを決定します。境界の固定が起点です。モデル世代交代やエージェント設定変更があれば、環境全体を再検証する必要があります。そうしないと、タスクが失敗したとき、モデルが悪いのか環境の設定が悪いのか区別できません。
リポジトリ内のコードはエージェントに与えるプロンプトです。1つの書き方が繰り返し現れれば、エージェントはそれを模倣します。2つの書き方が並存すれば、両方とも複製されます。修正も同様で、一度の指名修正が指摘された箇所だけを直した場合、同種の問題は別の場所でそのまま再発します。
古い書き方と新しい書き方がリポジトリ内に並存。エージェントは着手のたびに、今回どちらをコピーすべきか、移行は完了しているかを判断する必要がある。両方ともテンプレートとして複製される。
lint(コーディング規約チェックツール)を有効にし、1つのPRで約600件の規約違反を修正し、テストも追加。リポジトリにはコピーすべき答えが1つだけ残る。
本文には、そのままコピーできる3つの穴埋めテンプレートと、「今回の比較実験が有効かどうか」を判断する9項目チェックリストも用意されています。
以下の数字はすべて Ryan Lopopolo 氏自身のプロジェクトでの実測値であり、第三者による検証はありません。
モデル変える?!
リポジトリがある
足りないか見よう
パラメータ変更禁止
じゃあ何を?
コンテキストとツール
書き方B
両方ある
真似れば?
古い書き方
一掃
1つのPRで修正
指名された関数だけ
ここも間違うの?!
クラス全体を抑える
1500のPR
周りを整える
