AIエージェント・ハーネスエンジニアリング憲章
ハーネスとは、モデルをエージェントとして動作させるシステム全体 — エージェントループ、ツール表面、コンテキスト組み立て、ガードレール/認可、状態と耐久性、停止条件、評価、可観測性 — を指す。
エージェントの成果はモデルだけでは決まらない。同一モデルでもハーネス次第で成功率は大きく変わり(ハーネス感度)、ハーネス起因の性能差がモデル起因の差を上回ることが実証されている。ハーネスエンジニアリングとは、モデルの能力を最大限引き出しつつ、モデルに任せてはならない保証を決定的な機構で与える工学である。
0. コア公理
この公理は agent-harness-engineering / agent-native-project-design の2スキルへ意図的に同一内容で複製している(改訂時は両ファイルを同時に更新すること)。mastra-ai-architecture-rules の「設計の根本原則」とも整合するよう維持する。
- 判断にはモデルを使う。保証にはハーネスを使う。決定的な実行にはコードを使う。
- エージェント = モデル + ハーネス。同じモデルでもハーネスで成果は大きく変わる。 ハーネスは改善対象の第一級変数である。
- コアループは 「コンテキスト収集 → 行動 → 検証」。検証の設計が品質の上限を決める。
- 可能な限り単純な構成から始め、必要が実証されたときだけ複雑さを足す。 最も成功している実装は複雑なフレームワークではなく、シンプルで composable なパターンを使っている。
- コンテキストは有限資源である。ただし削減は品質確認の後に行う。 望む結果の尤度を最大化する最小の高シグナルトークン集合を目指すが、まず圧縮せずに渡して品質を担保できることを確認し、コンテキスト量が課題として顕在化してから対処する。payload ではなく reference を、transcript ではなく decision を保持する。
- 指示は助言(advisory)、コードとゲートは保証(deterministic)。 100%守られるべきものを指示(プロンプト)に置かない。
- 安全は監視より封じ込め。 境界(sandbox・権限)を先に定義し、境界越えだけを承認に上げる。既定は fail-closed。
- 停止条件・予算・エスカレーションはハーネスの一級市民である。 後付けにしない。
- モデルが賢くなるたびにハーネスを剪定する。 「以前は必要だった」は「今も必要」を意味しない。
- 失敗から学んだルールには理由を残す。 ハーネスはインシデント駆動で漸進強化する資産である。
適用優先順位: 特定ランタイムを採用済みのプロジェクトでは、そのランタイムの憲章(例: Mastra プロジェクトの mastra-ai-architecture-rules)が本スキルの一般則より優先する。同様に、リポジトリ内に人間管理の正本憲章・設計文書がある場合(例: l-shift の agent/AGENTS.md と agent/docs/ 配下の設計正本)は、その正本が本スキルより優先する。本スキルは、憲章がない領域の判断と、憲章そのものを設計・改訂するときの基盤を与える。本スキルとプロジェクト正本の矛盾に気づいた場合は、どちらかへ黙って合わせるのではなく、差分をユーザーへ提起すること。
1. ハーネス調達の意思決定
ハーネスは「自作か否か」の二値ではなく、抽象度の連続体から選ぶ:
生LLM API + 自前ループ → エージェントSDK(Claude Agent SDK / OpenAI Agents SDK 等) → 既製ハーネスの headless 利用(Claude Code / Codex CLI 等) → マネージド
判断手順:
- 既にランタイムを採用済みなら、そのランタイムの憲章に従うこと(Mastra なら mastra-ai-architecture-rules)。reuse > build。自作は最終手段である。
- 新規なら、以下の基準で「どの抽象度で降りるか」を workload ごとに選ぶこと:
| 判断基準 | 低抽象(生API/自前)に寄せる | 高抽象(SDK/既製ハーネス)に寄せる |
|---|---|---|
| エージェントにコンピュータ(ファイル・shell・コード実行)が必要か | 不要(会話・APIオーケストレーション型) | 必要(coding agent 系の継承価値が最大) |
| マルチテナント認可・独自の権限ゲートが必要か | 必要(ループへの介入点を自前で持つ) | 不要または単純 |
| サーバ常駐・pause/resume・永続実行が必要か | 必要(checkpoint 第一級の設計) | 不要(セッション完結) |
| コンテキスト組み立て・キャッシュ prefix の決定的制御がコストを支配するか | する | しない |
| ハーネス自体がプロダクトの差別化要素か | である | でない(「差別化しないハーネスは買え」) |
- どの調達形態でも、次の3つの所有権は手放さないこと:own your prompts / own your context window / own your control flow。既製ループの品質天井の主因は、プロンプト・コンテキスト・制御フローを隠すブラックボックス抽象である。
- 抽象を買ってよいかの判定テスト:「障害時に、実際にモデルへ送られたトークン列へ1ステップで到達できるか」。到達できない抽象は買わないこと。
- 自作の実コストは「作り直し回数」で見積もること。フロンティア実装ですら複数回のリビルドを経ている。反復に投資できる体制がなければ自作は成立しない。
詳細な比較表・移行トリガー条件: references/procurement.md
2. コアループ設計
エージェントループの実体は「プロンプト構築 → モデル呼び出し → ツール実行 → 履歴追加 → ツール呼び出しが止まったら終了」の while ループであり、これ以上複雑にしないことが既定である。
- モデル呼び出し層は「1回の推論のみ・ツールを実行しない・自己反復しない」。ループ制御・ツール実行はハーネス側の責務とし、この不変条件を契約テストで固定すること。SDK のコールバックにループ制御を紛れ込ませないこと。
- ツール実行の関門(Execution Gate)を一本化すること:解決 → 入力検証 → 認可 → 実行 → 結果正規化 が唯一の経路。バイパス経路を作らない。
- 幻覚ツール名・不正入力で run を落とさないこと。構造化エラーをモデルへ返し自己修正させる。エラーで自己修復させることは驚くほど機能する。ただし連続失敗(目安3回)で人間へエスカレーションし、エラースパイラルを防ぐこと。
- 停止条件を必ず持つこと:最大ステップ数、トークン/時間予算、明示的な final-output、doom loop 検出(同一ファイルへの微修正反復など)。
- 予算切れは raw エラーで終わらせず wrap-up turn で締めること:ツールなしの最後の1回で「達成・未完了・次の一手」を報告させる。wrap-up が失敗しても元エラーを上書きしないこと。
- プロンプトキャッシュ規律:静的コンテンツを prefix 先頭に、履歴は append-only、ツール定義は決定的順序。キャッシュヒット率は本番エージェントの最重要メトリクスであり、非決定的なシリアライズ1つで毎ターン全ミスになる。
3. コンテキスト工学
コンテキストには attention budget があり、長くなるほど劣化する(context rot)。劣化は崖ではなく勾配であり、エラーとしては現れず品質低下として静かに起きる。
- まず圧縮せずに渡すこと。 不要に圧縮・要約したコンテキストは品質を静かに損なう。生の検索結果・大きな表・文書であっても、まずそのまま渡して品質を担保できることを確認し、コンテキスト量が課題として顕在化してから圧縮・省略・compaction を導入する(公理5。mastra-ai-architecture-rules §7 と同旨)。
- 事前注入と Just-in-Time 取得のハイブリッドを既定とすること:毎回必要な静的方針は初回に前置し、本文・詳細はツールで実行時に取得させる。軽量識別子(パス・ID・リンク)を持たせ、必要時に読み込む。
- 環境は探索させず注入すること。エージェントが実行中にコンテキストで参照できないものは存在しないのと同じである。
- progressive disclosure:情報は「概要 → 本文 → 詳細参照」の階層で開示し、全量を事前投入しない。
- compaction 機構の導入自体は、コンテキスト逼迫が観測・実証されてからでよい(公理4)。導入する場合は非LLM圧縮を第一選択とするプログレッシブパイプラインにすること:古いツール結果のマスキング → 部分圧縮 → 構造化LLM要約。閾値駆動(目安70–90%)、ユーザー発話は省略禁止、暴走防止のサーキットブレーカーを持つ。
- 圧縮は必ず復元可能に設計すること:URL・ファイルパス・IDを残し、切り詰めた情報へ後から到達できるようにする。不可逆圧縮は「10ステップ後に必要になる情報」を失う。
- ファイルシステム(または外部ストア)を究極のメモリとすること。長時間タスクでは構造化メモ(計画・進捗・所見)を外部に書き出し、計画をコンテキスト末尾へ復唱(recitation)して目標ドリフトを防ぐ。
- 失敗はコンテキストに残すこと。エラー痕跡を見たモデルは同種アクションを避けるようになる。消毒された履歴は学習機会を奪う。
- 指示の層構造を持つ場合、グローバル層は per-run 指示でも無効化できないことを不変条件として固定すること。
コンテキスト失敗モード(poisoning / distraction / confusion / clash)と対策の詳細: references/context-engineering.md
4. ツール表面(ACI)設計
ツールはモデルに対するインターフェース(Agent-Computer Interface)であり、その質がモデルの実効能力を決める。ツール説明の精緻化だけで性能が大きく変わる。
- 外部APIを1:1でラップしないこと。エージェントのタスク単位に統合した少数のツールを設計する(例:
list_contactsよりsearch_contacts)。 - ツール数は絞ること。多すぎるツールは選択精度を下げる。減らして精度が上がった事例が繰り返し報告されている。
- 出力は token-efficient にすること:必要十分のみ返し、filter / pagination / truncation を設計する。意味のある識別子(名前・パス)を返し、無意味な UUID の羅列を避ける。ただし判断材料になりうる内容の事前要約・間引きは、§3「まず圧縮せずに渡す」に従い品質への影響を確認してから導入すること。filter / pagination はエージェント側が取捨選択できる形で提供する。
- エラーメッセージは修正指示として書くこと。エラーはモデルのコンテキストに入り、次の行動を決める。「何が悪いか」だけでなく「どう直すか」を返す。
- 実行途中でツールを動的に削除しないこと。定義の増減はキャッシュを壊し「消えたツールへの参照」を誘発する。制約はマスキング(そのターンで選ばせない)で行う。
- 大量のツールや大きな中間結果が必要な場合は、ツール群をコード API として提示し、コード実行で組み合わせさせるパターンを検討すること(モデルが見るのは明示的に返した値だけになり、トークンとプライバシーの両方を制御できる)。
5. ガードレールと認可
「エージェントが何をするかではなく、何ができるかを制御する」。
- 環境層が第一防衛線:sandbox・filesystem 境界・network egress 制御を先に設計する。モデル層の防御(プロンプト・分類器)は補助である。モデルは prompt injection に高確率で従うことを前提とせよ。
- sandbox は filesystem と network の両方を隔離すること。片方だけでは exfiltration か脱出の経路が残る。ドメイン allowlist は信頼境界にならない(許可済みドメイン経由の流出事例がある)。
- 逐次承認はスケールしない。人間は権限プロンプトの大半を素通し承認する(approval fatigue)。境界を事前定義し、境界越えのみを承認に上げること。sandbox は承認疲れを減らすためにある。
- LLM に権限判断を委ねないこと。「プロンプトで秘匿を指示する」はアンチパターン。認可は決定的コード(行レベル認可・Repository 契約・Execution Gate)が第一防衛線であり、検索前に適用する(Auth Before Retrieval — 取得してからフィルタするのではない)。
- 有効権限は Intersection、絶対に Union にしないこと:agent baseline ∩ 呼び出し元 ∩ 会話参加者の実権限。エージェントは会話者を超える権限で副作用を起こさない。deny > ask > allow の合成で「Union を構造的に作れない」実装にする。
- fail-closed を既定とすること:認可が未注入なら deny-all、設定不備は偽装せず明示エラー。「未設定が通すモード」を作らない。
- 承認(HITL)フローの不変条件:hard-deny は承認でもバイパス不可 / 承認者へ権限昇格しない(実行者の権限で再解決する)/ 認可値を run に固定(pin)しない / 終端状態への重複承認は冪等 no-op。
- 自作のセキュリティ部品を信用しないこと。「最も弱い層は自分で作った層」。OS プリミティブ・実績ある機構を優先する。
- 不可逆または高リスクなアクションは、型付き schema と approval gate を持つ明示的なツールとして定義し、リスク格付け(read-only/write・可逆性・権限・金銭影響)に応じてゲートを紐付けること。ブロックは deny-and-continue(拒否理由を返し代替を探させる)とする。
認可モデル・承認プロトコルの詳細: references/guardrails-authorization.md
6. 状態・耐久性・冪等性
- 耐久する正本(source of truth)は一つに決めること。会話ログと独立実行台帳の二重正本は整合維持コストを恒常的に生む。監査・分析は telemetry へ分離する。
- 実行状態(ステップ・リトライ・承認待ち)と業務状態を単一のイベント列に統合し、全状態をそこから導出可能にすること。エージェント=イベント列への stateless reducer と捉えると、checkpoint・resume・fork・デバッグが自明になる。
- state には reference / ID / summary のみを置くこと。大きな成果物はストレージに置き、参照だけ持つ。再計算可能なデータ・生のツール出力・チャット履歴のコピーを state に入れない。
- 副作用ツールには冪等性キーを供給すること(例:
runId:toolCallIdの決定論キー)。リトライ・再開・重複配信に対して「同一キー同一入力 → 同一結果、同一キー異入力 → 拒否」を契約として固定する。 - 失敗地点から再開できること。長時間エージェントの「ゼロから再実行」は設計欠陥である。checkpoint + backoff付きリトライ + 冪等性の3点セットで回復性を作る。
- 履歴の巻き戻し(rewind)を提供する場合は fork-first(非破壊)を既定とすること。
詳細: references/state-durability.md
7. 検証・評価・可観測性
検証ループがないエージェントは自走できない。 最頻の失敗モードは「自分の出力を読み返して良さそうと判断し、検証せず終了する」である。
- 実行可能なチェックを与えること:テスト・ビルド exit code・スキーマ検証・スクリーンショット比較。検証手段の優先順位は ルールベース > 視覚 > LLM-as-judge。
- 証拠主義:「ツールを実行した」≠「結果を観察した」。成功の主張ではなく証拠(コマンドと出力・トレース)を要求すること。検証できないものはシップしない。
- 評価(eval)は実際の失敗から採った少数タスク(目安20件)で始めること。数百件を待たない。トレースの読解・分類(error analysis)が「どの eval を作るか」を決める最重要工程である。
- 経路ではなく成果を採点すること。最終状態(DB状態・テスト通過)を検証し、ツール呼び出し順序を厳密規定しない。エージェントは設計者が想定しない正当解を見つける。
- 信頼性は pass^k で測ること。pass@1 が高くても反復信頼性は指数的に減衰する。業務組み込みには一貫性指標が必須。
- capability eval(低い合格率から登る)と regression eval(常時ほぼ100%を維持)を分離運用すること。
- eval スコアを transcript を読まずに信じないこと。スコア低下の原因が eval 側のバグであることは珍しくない。transcript サンプリング読解を制度化する。
- 可観測性は「観測欠落ゼロ + テレメトリで run を殺さない」:全失敗経路でイベントを emit し(落ちた run こそ trace が要る)、テレメトリ自体の失敗は縮退させて run を守る。秘匿情報は sanitize してから記録する。
- 決定論検証と実モデル検証の2層を持つこと:fake/決定論モデルで契約・不変条件を高速に固定し、実モデルで指示追従など確率的挙動を検証する。契約テストの silent skip(偽緑)を検出する仕組みまで含めて設計する。
詳細: references/evals-observability.md
8. マルチエージェント判断
マルチエージェントは最終手段である。 既定は single-threaded なエージェント + コンテキスト管理。
- 書き込みを伴う並列マルチエージェントは原則禁止。行動には暗黙の決定が埋め込まれ、完全なトレースを共有しない並列作業は矛盾した成果物を生む。
- サブエージェントの正しい用途は「役割分担」ではなく、read 系探索のコンテキスト隔離と並列化である。子は大量トークンを自分の窓に閉じ込め、親へは蒸留した要約のみ返す圧縮装置として使う。
- マルチエージェントの性能向上の実体はトークン消費の並列化であり、コストはチャット比で十数倍に達すると報告されている。並列分解可能な高価値タスクに限定すること。
- 委譲時は objective・出力形式・ツール指針・境界・工数上限を明示すること。「調べて」だけの委譲は重複作業と過剰探索を生む。タスク複雑度に応じた工数ルールを明文化する。
- サブエージェントの出力もツール結果と同様に tainted として扱うこと。無条件に高信頼で扱うことは新しい injection ベクタになる。
委譲プロトコル・出力契約・効果とコストの報告値: references/context-engineering.md
9. アンチパターン → 是正
| アンチパターン | なぜ失敗するか | 是正 |
|---|---|---|
| 自己確認で検証を終える | 「読み返して良さそう」は検証ではない | 実行可能チェック(テスト・ビルド・比較)を与える |
| プロンプトで権限・秘匿を制御する | モデルは injection に従う | 決定的な認可ゲート・sandbox に移す |
| 認可を Union で合成する | 権限昇格の穴が生まれる | Intersection + deny>ask>allow 合成 |
| 未設定が通す既定 | 設定漏れが即事故になる | fail-closed(deny-all / 明示エラー) |
| ツール全出力を state に保存する | state 肥大・snapshot 汚染 | reference / summary のみ保持 |
| 常時最大推論・無制限ループ | タイムアウト・コスト暴走で品質が下がる | 停止条件・予算・doom loop 検出を一級で持つ |
| 予算切れを raw エラーで返す | 途中成果が失われる | wrap-up turn で達成・未完了・次の一手を報告させる |
| ツールを乱立させる | 選択精度が下がる | タスク単位に統合し少数に絞る |
| 実行途中の動的ツール削除 | キャッシュ全滅・幻覚参照 | マスキングで制約する |
| 非決定的なプロンプト組み立て | キャッシュ全ミスでコスト増 | 静的 prefix・append-only・決定的順序 |
| 書き込み並列マルチエージェント | 暗黙の決定が衝突する | single-thread + サブエージェントは read 系隔離のみ |
| モデル更新後もハーネスを凍結する | 旧世代の補正が新モデルの上限になる | 世代ごとに剪定棚卸し(「強いモデルに替えて性能が上がるか」で検査) |
| ブラックボックス抽象への依存 | 品質天井・デバッグ不能 | own your prompts / context / control flow |
| ハーネス条件を揃えないモデル比較 | ハーネス差がモデル差を上回る | ハーネス固定で比較・条件を開示する |
| eval スコアだけ見て判断する | eval 側のバグ・想定外の正当解を見逃す | transcript 読解を制度化する |
| 自作セキュリティ部品 | 最も弱い層になる | OS プリミティブ・実績ある機構を使う |
10. 設計メモと最後の自己確認
非自明なハーネス実装・変更の前に、以下の見出しを持つ簡潔な設計メモを作成すること:
- 調達判断: どの抽象度を選んだか、既存ランタイムの再利用をなぜ選ばなかったか
- ループと停止条件: 最大ステップ・予算・doom loop 検出・wrap-up
- コンテキスト予算: 事前注入 / JIT の切り分け、compaction 方針
- ツール表面: ツール一覧と統合の根拠、エラー設計
- 認可モデル: 境界・Intersection 構成・fail-closed の確認・承認ゲートの位置
- 状態と耐久性: 正本の所在、state に置くもの/置かないもの、冪等性キー
- 検証と評価: 実行可能チェック、eval タスクの出所、transcript 読解の運用
- モデル能力向上時に削除できるもの: このハーネスのどの部分が「現行モデルの弱点補正」か
実装前に自問すること:
- この保証は本当にハーネスでなければ与えられないか。指示・ツール説明・schema の改善で済まないか
- このループ・ラッパー・ステップは、モデルの判断を模倣していないか
- 検証手段はあるか。ないならシップできる状態か
- 権限の既定は fail-closed か。Union になっている箇所はないか
- 次のモデル世代で、この機構は削除候補になるか
迷ったら、より少ない機構で同じ保証を与える設計を選ぶこと。