0. TL;DR(要約)
「The Claude Code You Don't Know: Architecture, Governance, and Engineering Practices」を執筆した後、Agent の基盤レイヤーに対する理解が十分でないことに気づきました。チームが Agent ベースのビジネスソリューションを展開してきた豊富な経験も踏まえ、体系的なレビューの必要性を感じました。そこで、資料、オープンソースの実装、そして自身のコードを見直し、この記事をまとめました。
この記事では、Agent アーキテクチャの中でもエンジニアリングの成果に最も影響を与える部分に焦点を当てます。具体的には、制御フロー、コンテキストエンジニアリング、ツール設計、メモリ、マルチエージェント組織、評価、トレーシング、セキュリティです。最後に、OpenClaw の実装を用いて、これらの設計原則を統合します。
整理する中で、いくつかの結論は当初の想定とは異なるものでした。高価なモデルによる改善効果は予想よりも小さいことが多く、代わりに Harness(ハーネス)と検証テストの品質が成功率に与える影響の方が大きいこと。Agent の動作をデバッグする際は、まずツール定義を確認すべきで、ツール選択ミスのほとんどは不正確な説明に起因すること。さらに、評価システム自体の問題は、Agent のバグよりも発見が難しいことです。Agent のコードをいくら調整してもうまくいかない場合、答えはこれらの領域にあるかもしれません。
1. Agent ループの基本動作
Agent ループのコア実装ロジックは、抽象化すると 20 行未満のコードになります。
1const messages: MessageParam[] = [{ role: "user", content: userInput }];23while (true) {4 const response = await client.messages.create({5 model: "claude-opus-4-6",6 max_tokens: 8096,7 tools: toolDefinitions,8 messages,9 });1011 if (response.stop_reason === "tool_use") {12 const toolResults = await Promise.all(13 response.content14 .filter((b) => b.type === "tool_use")15 .map(async (b) => ({16 type: "tool_result" as const,17 tool_use_id: b.id,18 content: await executeTool(b.name, b.input),19 }))20 );21 messages.push({ role: "assistant", content: response.content });22 messages.push({ role: "user", content: toolResults });23 } else {24 return response.content.find((b) => b.type === "text")?.text ?? "";25 }26}
対応する制御フローは以下の通りです。モデルがプレーンテキストを返すまで、知覚(Perception)→ 判断(Decision)→ 行動(Action)→ フィードバック(Feedback)のサイクルが継続します。

多くの Agent 実装や公式 SDK を見てきましたが、構造は似ています。ループ自体は非常に安定しています。最小限の実装から、サブエージェント、コンテキスト圧縮、スキル読み込みをサポートするまで、メインループが変更されることはほとんどありません。新しい機能は通常、ループの内部を変更するのではなく、ループの外側にレイヤーとして追加されます。
新しい機能は主に 3 つの方法で統合されます。ツールセットとハンドラの拡張、システムプロンプト構造の調整、状態のファイルやデータベースへの外部化です。ループ本体を巨大なステートマシンにしてはいけません。モデルは推論を担当し、外部システムは状態と境界を担当します。この役割分担が確立されれば、コアループのロジックを頻繁に調整する必要はほとんどありません。
ワークフローと Agent の違いは何か?
Anthropic は明確に区別しています。実行パスがコードに事前に記述されているシステムはワークフロー、LLM が動的に次のステップを決定するシステムは Agent です。核心的な違いは、誰が制御権を持つかです。実際には、Agent と称する製品の多くはワークフローに近いですが、どちらが本質的に優れているわけではありません。重要なのは、タスクに適したソリューションを見つけることです。

図で見るとより直感的に理解できます。

5 つの一般的な制御パターン
ほとんどの AI システムは、分解するとこれら 5 つのパターンの組み合わせです。多くのシナリオでは、完全な Agent の自律性は必要なく、これらのパターンのいくつかを組み合わせるだけで十分です。鍵となるのは、どの設計がタスクに適合するかです。
- プロンプトチェイニング(Prompt Chaining): タスクを順次ステップに分割し、各 LLM ステップが前の出力を処理します。コードチェックポイントを追加できます。生成後の翻訳や、アウトライン作成後の本文執筆など、線形プロセスに適しています。
- ルーティング(Routing): 入力を分類し、専門化されたプロセスに振り分けます。簡単な質問は軽量モデルへ、複雑な質問は高性能モデルへ。テクニカルサポートと請求照会では異なるロジックを使用します。
- 並列化(Parallelization): 2 つのバリエーションがあります。セクショニング(Sectioning、タスクを独立したサブタスクに分割)とボーティング(Voting、同じタスクを複数回実行してコンセンサスを得る)。リスクの高い意思決定や複数の視点が必要な場合に適しています。
- オーケストレーター・ワーカー(Orchestrator-Workers): 中央の LLM がタスクを動的に分解し、ワーカー LLM に委任して、結果を統合します。これは、nanobot の spawn ツールや learn-claude-code のサブエージェントモードのプロトタイプです。
- 評価者・最適化(Evaluator-Optimizer): 生成器が出力を生成し、評価者が基準を満たすまでループでフィードバックを提供します。翻訳やクリエイティブライティングなど、品質基準をコードで正確に定義することが難しいタスクに適しています。

これらのパターンは、制御フローを構築する方法を解決します。次に、よりエンジニアリングに焦点を当てた質問を見てみましょう。なぜシステムは安定して動作するのでしょうか?
2. Harness がモデルよりも重要な理由
Harness とは、Agent の周りに構築されたテスト、検証、制約のためのインフラストラクチャを指します。Harness には、少なくとも 4 つの部分が含まれます。受け入れ基準、実行境界、フィードバック信号、フォールバック方法です。
モデルも重要ですが、これらの周辺のエンジニアリング条件が、システムが安定して動作するかどうかを決定することがよくあります。この判断は、コーディングのように検証が容易なタスクで最も当てはまりますが、オープンリサーチや多ラウンド交渉のような検証が弱いタスクでは、モデルの上限の方が依然として重要です。
OpenAI の Agent ファースト開発プラクティス
3 人のエンジニアが 5 ヶ月間で約 1,500 件の PR と 100 万行のコードを記述しました。これは従来の開発速度の 10 倍です。この速度はモデルの性能だけでなく、正しいエンジニアリング上の判断によるものです。
- Agent が見えないコンテンツは存在しない: 知識はコードベース自体に存在する必要があります。外部のドキュメントは実行中の Agent からは見えません。AGENTS.md は約 100 行のインデックスとして維持し、詳細は docs ディレクトリに分割してオンデマンドで参照できるようにします。
- コードで制約し、文書化しない: ドキュメント内の規範は無視されがちです。Linter、型システム、CI ルールにエンコードされた制約は実行可能です。アーキテクチャのレイヤー化は、手動レビューではなく、カスタム Linter によって機械的に強制されます。
- エンドツーエンドの自律的なタスク完了: 状態の確認、バグの再現、修正の実装、アプリの検証駆動、PR の作成、レビューの処理、マージまで、チェーン全体に人間の介入は不要です。Agent はログ、メトリクス、トレースを積極的に確認します。
- マージの摩擦を最小限に抑える: 断続的なテストの失敗は、進行を妨げるのではなく、リトライで処理します。高スループット環境では、手動レビューを待つコストは、小さなエラーを修正するコストよりも高いことがよくあります。コーディング規律は消えたわけではなく、手動レビューから機械実行の制約へと移行しました。

アプリは、ログ、メトリクス、トレースを Vector 経由で Victoria ストレージレイヤーに配布します。これは LogQL、PromQL、TraceQL インターフェースに対応します。Codex はこれらのインターフェースを通じてクエリ、相関、推論を行います。変更後、アプリを再起動し、ワークロードを再実行して、結果を Codex にフィードバックします。UI ジャーニーも入力として使用されます。このオブザーバビリティスタックはタスクごとに作成され、完了時に破棄されます。Agent はエラーを通知されるのを待つのではなく、システム状態をクエリして修正を検証します。
Harness に関する重要な結論は何か?

図は、タスクの明確さと検証の自動化を使用して、タスクを 4 つの状態に分類しています。右上(明確な目標、自動化された検証)は Agent にとって理想的なゾーンです。左上(明確なタスクだが手動レビュー)は人間のレビュー速度によって制限されます。右下(自動化されたフィードバックだが曖昧な目標)は、間違った方向への効率的な移動につながります。左下(両方とも欠如)は Agent を役立たずにします。
Harness の役割は、タスクを右上の状態に押し上げ、正誤が人間の目ではなく、機械実行可能な基準で判断されるようにすることです。
3. コンテキストエンジニアリングが安定性を決定する理由
Transformer のアテンション計算量は O(n²) です。コンテキストが長くなるほど、重要なシグナルがノイズに埋もれやすくなります。よくある障害モードは「コンテキストロート(Context Rot)」で、無関係なコンテンツがコンテキストを支配し、Agent の意思決定品質が低下します。モデルの能力不足に見える問題の多くは、実際にはコンテキストの整理が不十分なことが原因です。
なぜコンテキストをレイヤー化するのか?
問題は通常、ウィンドウが十分に長くないことではなく、情報密度が適切でないことです。毎回ほとんど使用しないアイテムをロードしたり、安定したルールと動的な状態を混在させたりすると、モデルが有用な情報に気づきにくくなります。

解決策は、情報を頻度と安定性でレイヤー化することです。
- 永続レイヤー(Permanent Layer): アイデンティティ、プロジェクト規約、絶対的な禁止事項。すべてのセッションで保持しなければならないコンテンツ。短く、厳格で、実行可能に保ちます。
- オンデマンドローディング(On-Demand Loading): スキルとドメイン知識。記述子は永続的に保持しますが、完全なコンテンツはトリガーされた場合のみ注入します。
- ランタイムインジェクション(Runtime Injection): 現在時刻、チャンネル ID、ユーザー設定などの動的情報。必要に応じてラウンドごとに注入します。
- メモリレイヤー(Memory Layer): セッションをまたいだ経験を MEMORY.md に書き込みます。システムプロンプトに直接含めず、必要なときにのみ読み込みます。
- システムレイヤー(System Layer): 決定論的ロジックのためのフックやコードルール。コンテキストから完全に除外します。
決定論的ロジックをコンテキストに入れないでください。 フック、コードルール、ツール制約で表現できるものはすべて、外部システムで処理する必要があります。
3 つの一般的な圧縮戦略
- スライディングウィンドウ(Sliding Window): 古いメッセージを破棄します。低コストですが、初期のコンテキストが失われます。短いチャットに適しています。
- LLM サマリー(LLM Summary): モデルが要約を生成します。中程度のコストで、詳細は失われますが、決定事項は保持されます。長いタスクに適しています。
- ツール結果置換(Tool Result Replacement): 生の出力をプレースホルダーに置き換えます。低コストで、ツールを多用するタスクに適しています。
スライディングウィンドウは最も簡単ですが、初期の背景情報が失われます。高度な LLM サマリーでは「ブランチ要約」を使用し、アーキテクチャ上の決定、未完了のタスク、主要な制約を明示的に保持します。ツール置換では、micro_compact が毎ラウンド古いツール出力を置き換え、auto_compact はコンテキストがしきい値を超えたときにトリガーされます。
プロンプトキャッシングによる冗長オーバーヘッドの削減
LLM 推論は、各トークンの Key-Value ペアを計算します。プレフィックスが以前のリクエストと完全に一致する場合、キャッシュから読み取られます。キャッシングには完全なプレフィックス一致が必要です。キャッシュフレンドリーな設計は安定性を中心とします。システムプロンプト、ツール定義、長いドキュメントは安定しており、キャッシュに適しています。動的情報(時刻、入力、ツール結果)は最後に配置する必要があります。
これはコンテキストのレイヤー化に関連しています。永続レイヤーが安定しているほど、キャッシュヒット率は高くなり、限界コストは低くなります。「短く安定している」ことは、トークンを節約するためだけでなく、キャッシュを保護するためでもあります。スキルの遅延読み込みも、安定したプレフィックスの後にコンテンツを追加することで役立ちます。直感に反する点として、安定した大きなシステムプロンプトは、頻繁に変更される小さなプロンプトよりも安価になる可能性があります。これは、後続の読み取りに対する 90% の割引が、最初の書き込みコストを上回るためです。
なぜスキルをオンデマンドでロードするのか?
スキルは効果的なパターンです。システムプロンプトにはインデックスのみを保持し、完全な知識は必要に応じてロードします。
1const systemPrompt = `2利用可能なスキル:3- deploy: 本番環境への完全なデプロイプロセス4- code-review: コードレビューチェックリスト5- git-workflow: ブランチ戦略と PR 規範6`;78async function executeLoadSkill(name: string): Promise<string> {9 return fs.readFile(`./skills/${name}.md`, "utf-8");10}
スキルの説明は、トークンの肥大化を避けるために短くし、ルーティング条件として機能させる必要があります。いつ使用するか、いつ使用しないか、出力は何かを説明します。「Use when / Don't use when」を否定的な例とともに使用します。ルーティングの失敗の多くは、モデルの能力ではなく、境界が不明確であることに起因します。システムプロンプトではルールを明確にします。各応答の前に available_skills をスキャンし、一致した場合は特定の SKILL.md をロードし、一度にロードするのは 1 つだけとします。

データは明確です。否定的な例がない場合、精度は 73% から 53% に低下します。追加すると 85% に上昇し、応答時間は 18.1% 短縮されます。否定的な例が鍵です。
スキル記述子には 2 つの落とし穴があります。1 つ目は語数です。すべてのスキルに長い説明を付けると、合計が大きくなります。2 つ目は精度です。「バックエンドを手伝う」は曖昧すぎます。効果的な記述子は、機能の紹介ではなく、ルーティング条件です。「何ができるか」よりも「いつ使うか」が重要です。
数量を制御します。永続的なプロンプトには高頻度のスキルのみを保持します。低頻度のスキルは手動で導入するか、ドキュメントとして保持します。典型的なアンチパターンは、数百行のマニュアルをスキルに詰め込むことや、1 つのスキルでレビュー、デプロイ、デバッグなど、あまりにも多くの異なるタスクをカバーすることです。
圧縮で最も失われやすいものは何か?
最も一般的な問題は、要約が長すぎることではなく、保持の優先順位が間違っていることです。LLM は、再取得可能と思われる情報を削除することがよくあります。ツール出力が最初に削除されますが、関連するアーキテクチャ上の決定や障害パスも一緒に消えてしまうことがよくあります。CLAUDE.md で保持の優先順位を明示的に定義します。
1### 圧縮指示: 重要な情報を保持する方法2優先順位:31. アーキテクチャ上の決定(要約しない)42. 変更されたファイルと主要な変更点53. 検証ステータス(合格/不合格)64. 未解決の TODO とロールバックノート75. ツール出力(削除可、合格/不合格の結論のみ保持)
もう 1 つの落とし穴は、識別子を変更しないことです。UUID、ハッシュ、IP、ファイル名は正確に保持する必要があります。コミットハッシュの 1 文字の間違いが、後続のツール呼び出しを壊します。
ファイルシステムが優れたコンテキストインターフェースである理由
Cursor はこれを「動的コンテキスト発見(Dynamic Context Discovery)」と呼んでいます。デフォルトでは少なく提供し、必要なときに読み取ります。ファイルシステムは自然なインターフェースです。ツール呼び出しは巨大な JSON を返すことがよくありますが、それをコンテキストに詰め込む代わりに、ファイルに書き込みます。Agent は grep や rg を使用して必要に応じて読み取ることができます。これにより、コンテキストがクリーンに保たれ、開発者も読み取り可能です。
Cursor は MCP ツールでこれを検証しました。ツールの説明をフォルダに同期します。Agent はデフォルトでツール名のみを表示し、必要に応じて定義をクエリします。A/B テストでは、これにより総トークン消費量が 46.9% 削減されました。
これは長時間タスクの圧縮にも有効です。履歴を破棄する代わりに、完全なチャットログをファイルに保存し、要約内でそのパスを参照します。Agent が詳細を必要とする場合、ファイルから取得できるため、圧縮は非可逆ですがトレース可能な操作になります。
4. ツール設計が Agent の能力を決定する
コンテキストはモデルが見るものを決定し、ツールはモデルができることを決定します。品質は量に勝ります。わずか 5 つの MCP サーバーでも、定義に約 55,000 トークンかかる可能性があり、チャットが始まる前から 200K コンテキストの約 30% を消費します。ツールが多すぎると、モデルの注意が散漫になります。
ほとんどのツールの問題は、数が少なすぎることではなく、間違ったツールを選択すること、説明が理解できないこと、または役に立たないデータを返すことです。

ツール設計の進化
ツール設計は 3 つの段階を経てきました。初期は、既存の API をそのままツールとしてラップしていました。その後、選択ミスはツールがエンジニア向けに設計されており、Agent 向けではないことが多いことがわかりました。
第 1 世代: API ラッピング: 各エンドポイントが 1 つのツールです。粒度が細かすぎます。Agent は 1 つの目標のために複数のツールを調整する必要があります。
第 2 世代: ACI(Agent-Computer Interface): ツールは低レベルの API ではなく、Agent の目標に対応します。create_file と set_permissions を提供する代わりに、create_script(path, content, executable) を提供します。
第 3 世代: 高度なツール使用法: 発見と呼び出しの最適化。
- ツール検索(Tool Search): すべての定義を一度に詰め込みません。Agent は
search_toolsを介して定義を見つけます。コンテキスト保持率は 95% に達します。 - プログラムによるツール呼び出し(Programmatic Tool Calling): モデルにコードを使用して複数の呼び出しを調整させます。中間結果は LLM コンテキストではなく、実行環境に残ります。トークンは 150,000 から 2,000 に削減できます。
- ツール使用例(Tool Use Examples): 各ツールに 1〜5 の実際の例を提供します。JSON Schema は型を記述しますが、例は使用方法を示します。精度は 72% から 90% に向上する可能性があります。
ACI ツール設計原則
ツール設計は Agent に直接影響します。「呼び出せるか」だけでなく、「間違って呼び出された場合に自己修正できるか」が重要です。
悪い設計は、パラメータが曖昧で、エラーが修正不可能です。良い設計は betaZodTool を使用して定義と実装をバインドし、Zod を使用してフォーマット制約と構造化されたエラー提案を行います。
1const updateTool = betaZodTool({2 name: "update_yuque_post",3 description: "Yuque 投稿の内容を更新します。新規投稿は作成しません。",4 inputSchema: z.object({5 post_id: z.string().describe("Yuque 投稿 ID、'12345678' のような数値文字列"),6 title: z.string().optional().describe("投稿タイトル、変更がない場合は省略"),7 content_markdown: z.string().describe("Markdown 本文"),8 }),9 run: async (input) => {10 const post = await getPost(input.post_id);11 if (!post) throw new ToolError("投稿 ID が存在しません", {12 error_code: "POST_NOT_FOUND",13 suggestion: "有効な post_id を取得するには、最初に list_yuque_posts を呼び出してください。",14 });15 return await updatePost(input.post_id, input.title, input.content_markdown);16 },17});

悪い設計は、何をするかだけを説明し、いつ使用するかを説明しません。優れた ACI 設計は、明確な境界と構造化されたエラーを持ち、Agent が正しく選択し、障害を迅速に修正するのに役立ちます。まずツールをデバッグしてください。ほとんどのエラーは、モデルの能力ではなく、説明にあります。
なぜツールメッセージを分離するのか?
フレームワークは内部イベント(圧縮、通知)を生成します。これらはセッション履歴には含めるべきですが、LLM に送信すべきではありません。トークンを浪費し、モデルを混乱させるからです。解決策は 2 つのメッセージタイプです。アプリケーションレイヤー用の AgentMessage(カスタムフィールド付き)と、LLM 用の標準 Message(user、assistant、tool_result)です。
5. メモリシステムの設計
Agent にはネイティブな時間的連続性がありません。セッションが終了するとコンテキストはクリアされます。セッションをまたいだ一貫性を実現するには、メモリレイヤーを後付けではなく、インフラストラクチャとして設計する必要があります。
4 種類のメモリはどこに存在するのか?
解決する問題によって分類されます。
- コンテキストウィンドウ(ワーキングメモリ): 現在のタスクに必要な最小限の情報。トークンが限られているため、管理が必要です。
- スキル(手続き的メモリ): 物事のやり方(ワークフロー、規範)。オンデマンドでロードされます。
- JSONL セッション履歴(エピソード記憶): 何が起こったか。ディスクに永続化され、検索可能です。
- MEMORY.md(意味記憶): Agent によって書き込まれる安定した事実。システムプロンプトに注入されます。

MEMORY.md とスキルはどのように連携するのか
核心は、重要な事実を保持しながら、コンテンツ量を制御することです。
ChatGPT の 4 層メモリ: シンプルな構造。セッションメタデータ(永続化されない)、ユーザーメモリ(約 33 の事実、永続化/注入)、会話サマリー(約 15 の最近のサマリー、永続化)、現在のセッション(スライディングウィンドウ)。
OpenClaw ハイブリッド検索: 日次ログ(memory/YYYY-MM-DD.md)、厳選された事実のための MEMORY.md、およびハイブリッド検索(70% ベクトル類似度 + 30% キーワード)を使用する memory_search。ほとんどの Agent にとって、構造化された Markdown とキーワード検索で、デバッグ容易性とコストの点で十分です。
メモリ統合のトリガーとロールバック

tokenUsage / maxTokens >= 0.5 になったら、統合をトリガーします。メッセージを要約し、MEMORY.md に追加し、インデックスを更新します。失敗した場合は、生のメッセージをアーカイブに書き込みます。プロセスは元に戻せる必要があります。生データを削除するのではなく、ポインタを移動します。
6. Agent の自律性を段階的に高める
自律性には 3 つのインフラストラクチャが必要です。セッションをまたいだ再開、セッション内の進捗制約、低速タスクのためのバックグラウンド I/O です。
長時間タスクをセッション間で継続する方法
長時間タスクは、セッションが完了前に終了すると失敗します。安定したアプローチは、初期化 Agent(Initializer Agent) と コーディング Agent(Coding Agent) を使用することです。Initializer は一度実行され、feature-list.json、init.sh、claude-progress.txt を作成します。その後、Coding Agent が複数のセッションで実行され、これらのファイルから再開し、1 つの機能を実装し、テストを実行し、進捗ファイルを更新します。これにより、タスクは外部状態になります。

進捗はコンテキストではなく、ファイルに保持します。構造には JSON を使用します。タスクは、feature-list.json 内のすべての機能が passes: true になったときにのみ完了します。
なぜタスク状態を明示的に書き込むのか?
外部アンカーがないと、Agent は漂流するか、早期に終了します。状態を外部制御オブジェクトとして記録します。
1{2 "tasks": [3 {"id": "1", "desc": "設定を読み込む", "status": "completed"},4 {"id": "2", "desc": "スキーマを変更する", "status": "in_progress"}5 ]6}
制約: 一度に in_progress は 1 つだけです。各ステップの後に状態を更新します。
バックグラウンド I/O の統合
低速 I/O(ファイル操作、ネットワーク)はメインループをブロックするべきではありません。低速なサブプロセスをバックグラウンドスレッドに配置し、次の LLM 呼び出しの前に通知キューを介して結果を注入します。これは、複雑な非同期ランタイムよりも保守が容易です。
7. マルチエージェントシステムの組織化
マルチエージェントシステムのエンジニアリングは、分離と協調に関するものです。
ディレクターモード(Director Mode): 同期。人間が 1 つの Agent と密接にやり取りします。セッションが終了するとコンテキストは失われます。
コーディネーターモード(Coordinator Mode): 非同期委任。人間が目標を設定し、Agent が並行して作業し、人間が出力をレビューします。出力は永続的な成果物(PR、ブランチ)になります。

オーケストレーターは並行して動作するサブエージェントを管理し、JSONL インボックスプロトコルを介して通信し、Worktree を使用して分離を実現します。

サブエージェントは何に適しているか?
検索や試行錯誤は、メイン Agent のコンテキストを汚染するべきではありません。メイン Agent は結論のみを必要とします。
1const result = await runAgentLoop(task, { messages: [] });2return summarize(result); // メインコンテキストはこの行のみを見る
なぜ協調をプロトコルとして記述するのか?
自然言語による協調は、Agent が約束を忘れると失敗します。構造化されたプロトコルを使用します。
1{ request_id, from_agent, to_agent, content, status: 'pending', timestamp }
クラッシュリカバリのために、追記専用の JSONL インボックスを使用します。協調の前に、まず分離です。

マルチエージェントシステムでは幻覚が増幅される
エラーは Agent 間で連鎖します。相互検証(Cross-validation)は、独立した Agent または外部フィードバック(テスト、コンパイラ)に結論を判断させることで、この連鎖を断ち切ります。

8. Agent の評価方法
評価には、テストケース、スコアリング基準、自動検証が必要です。

従来のシングルターン評価(プロンプト -> 応答)は不十分です。Agent の評価にはツールと環境が必要です。スコアリングは、Agent が言ったことだけでなく、環境で何が起こったかに基づきます。

重要な概念: タスク(Task)、トライアル(Trial)、採点者(Grader)。トランスクリプト(Transcript、実行ログ) と 成果(Outcome、最終状態)。両方が必要です。Agent は「チケットを予約しました」と言うかもしれませんが(トランスクリプト)、データベースレコードの作成に失敗する可能性があります(成果)。
評価ステータスとメトリクス
多くのチームは今でも手動レビューや LLM ジャッジに依存しています。一般的なメトリクス: Pass@k(理論的に可能か?)と Pass^k(本番環境で安定しているか?)。これらを混同しないでください。

3 種類のグレーダー
- コードグレーダー: 文字列マッチング、ユニットテスト。最も確実。
- モデルグレーダー: 基準に基づく LLM ジャッジ。意味的な品質に適している。
- 人間グレーダー: 専門家によるレビュー。遅いがベースラインを確立する。
ゼロから評価システムを構築する
実際の失敗事例 20~50 件から始めます。テストが互いに影響を与えないよう環境を分離します。ポジティブケースとネガティブケースの両方を含めます。2 人の専門家があるケースで意見が分かれた場合、基準がまだ明確ではありません。
エージェントを修正する前に評価を修正する
スコアが低下した場合は、まず評価システムを確認します。環境の問題(メモリ制限、グレーダーのバグ)はモデルの劣化のように見えます。

9. 実行プロセスのトレーシング
トレースがなければ、障害を再現できません。APM メトリクス(レイテンシ、エラー率)だけでは不十分です。推論チェーンが必要です。
トレースに記録すべきものは?
完全なプロンプト、マルチラウンドのメッセージ、ツール呼び出し/引数/戻り値、思考チェーン、最終出力、トークン、レイテンシ。
2 層の可観測性
- 手動サンプリング: エラーやネガティブフィードバックのルールベースのサンプリングで障害パターンを見つける。
- LLM 自動評価: 手動層をキャリブレーションベースラインとして使用し、トレースを完全にカバーする。

基盤としてのイベントストリーム
tool_start、tool_end、turn_end でイベントを発行します。ダウンストリームシステム(ログ、UI、評価)は、コアループコードを変更せずにこれらのイベントを消費します。

10. OpenClaw でエージェントを展開する
OpenClaw は 5 つの分離されたレイヤーを使用します: Gateway、Channel Adapters、Pi Agent(コアループ)、Toolsets(ACI 設計)、Context/Memory。

メッセージバスの分離
メッセージバスはチャネルとエージェントを分離します。チャネルは I/O のみを処理し、エージェントは処理のみを担当します。
システムプロンプトの階層化
SOUL.md はアイデンティティと完了基準を定義します。プロンプトは階層化されています: ランタイム情報 -> アイデンティティ -> メモリ -> スキル -> 動的インジェクション。

セキュリティ境界を最優先に
機能を追加する前に、以下を確立します: ユーザーホワイトリスト、ワークスペースの分離(パスチェック)、監査ログ。
プロンプトインジェクション対策: 外部コンテンツを信頼できないものとして扱います。ソース-シンク分離を使用します。エージェントに不要なツールを与えないでください。機密性の高いアクションには明示的な人間の確認を要求します。
プロバイダーフォールバック: 1 つが失敗した場合、自動的にプロバイダーを切り替えます(Anthropic -> OpenAI)。
11. よくあるアンチパターン
- システムプロンプトを知識ベースとして使用する(長すぎる)。
- ツールの乱立(エージェントが間違ったツールを選択する)。
- 検証ループの欠如。
- 境界のないマルチエージェントシステム。
- メモリ統合の欠如(20 ラウンド後に品質が低下する)。
- 評価システムの欠如。
- 時期尚早なマルチエージェントの複雑化。
- 機械的な制約ではなく期待に依存する。
12. 結論
- エージェントの中核は安定したループであり、新機能は外部化すべきである。
- ハーネスはモデルよりも収束を決定する。
- コンテキストエンジニアリングは「コンテキスト腐敗」を防ぐ。
- ACI ツール設計は目標とエラー修正に焦点を当てる。
- メモリは階層化されている(作業記憶、手続き記憶、エピソード記憶、意味記憶)。
- 長時間のタスクは外部化された状態とファイルに依存する。
- マルチエージェントシステムにはプロトコルと分離が必要。
- 評価: Pass@k は能力、Pass^k は品質。
- トレーシングはデバッグの前提条件である。
- 安定したエージェントは、分離やセキュリティ境界などのエンジニアリングの詳細に依存する。





