Go back

AIエージェントを一気に勉強してわかった設計の勘所とループエンジニアリング

Posted on:

最近、AIエージェントについてまとまった時間を割いて勉強しました。書籍『実践 AIエージェント開発』を読み、Developers Summitの登壇資料に目を通し、自分のZettelkastenに溜まっていた素材も棚卸ししました。ひとしきりインプットを終えて気づいたのは、自分が「エージェント」という言葉を、思っていたよりも雑に使っていたという事実です。

Claude CodeやCodexを毎日触っているので、感覚的にはわかっているつもりでした。ただ、いざ設計の話になると、モデル・ツール・メモリ・ループをどの順番で決めるべきか、自分の中に整理された軸がありませんでした。今回はその棚卸しの結果を、自分の言葉でまとめておきます。

エージェントは「オーケストレーション」を起点に考える

エージェントシステムの基本形は、ユーザーの入力をオーケストレーションが受け取り、モデル・ツール・メモリ・ナレッジベースへ処理を振り分ける構成です。複数のエージェントを連携させる方法は、大きく2つに整理できます。処理を別のエージェントへ委譲するRoutingパターンと、エージェントをツールとして呼び出すSupervisorパターンです。

固定ロジックのワークフローと自律的なエージェントは、対立するものではありません。両者を組み合わせた「Agentic Workflow」によって、柔軟性と予測可能性を両立できます。ここが最初の気づきでした。「エージェントらしさ」を自律性の高さだけで測っていましたが、実際には決定論的なワークフローをどれだけ賢く組み込めるかの勝負でもあります。

現場のLLM活用も、対話で推論を制御する協働型と、SkillsやテンプレートでAIに任せる委託型の2流派に収斂します。どちらが優れているという話ではなく、チームの経験量と現場特性で使い分けるものだと理解しました。

普段使っているClaude Codeも、この2パターンを併用しています。コード検索を任せるExploreのような探索特化のsubagentと、専門知識に特化したsubagentを、状況に応じて呼び分けています。呼び出す側が全体を統括し、個々の作業は専用のsubagentに投げる。これはSupervisorパターンそのものです。

ツールの粒度と段階的開示は同じ問題を解いている

ツールを外部システムに繋ぐ汎用プロトコルとしてMCP(Model Context Protocol)があります。従来のAPI呼び出しと違い、動的なコンテキストを推論プロセスへ直接注入できる点が強みです。

ここで悩ましいのがツールの粒度でした。プリミティブな操作を1つずつツール化する「シンプルなツール群」は柔軟性が高い一方、コンテキストを圧迫しやすくなります。ユースケース単位でまとめた「複雑な単一ツール」は挙動が一貫する一方、設計工数がかかります。

この構図は、Agent Skillsの設計原則とそっくりだと気づきました。Skillsの価値は新しい能力の追加ではなく、必要なときに必要な知識だけを読み込ませる段階的開示とルーティングにあります。ツールの粒度設計もSkillsの設計も、突き詰めると「コンテキストという有限のリソースをどう配分するか」という同じ問題を解いています。

手元の環境でも、この違いは実感しやすいです。Figma MCPは画面情報の取得やスクリーンショットなど、操作を細かく分けた「シンプルなツール群」型で、目的に応じて複数のツールを組み合わせる必要があります。一方でObsidian CLIは、ノート作成や検索といったユースケース単位でまとまった「複雑な単一ツール」型に近いです。同じMCPというプロトコルの上でも、設計思想の違うツールが混在しています。

学習はまずノンパラメトリックから試す

エージェントが経験から学習する手段は、モデルのパラメーターを変えるパラメトリック学習と、プロンプトやメモリ、検索コンテキストの調整で性能を改善するノンパラメトリック学習に分かれます。

ファインチューニングだけが「賢くする」手段だと思い込んでいましたが、モデルのパラメーターに手を入れずに記憶や検索の仕組みだけで性能を改善できる、という整理は素直に驚きました。コストと運用の柔軟性を考えれば、まずノンパラメトリックな改善で伸ばせるところまで伸ばし、それでも足りない部分だけファインチューニングを検討する順番が現実的です。ノンパラメトリック学習はメモリの設計と切り離せないので、学習の話は自然と記憶の話にもつながっていきます。

この整理を読んで、一番腑に落ちたのは自分が使っているClaude Codeのメモリ機能でした。ユーザーの好みや過去のフィードバックをMarkdownファイルに書き出し、次回以降の会話で読み込みます。モデルのパラメーターは何も変えていないのに、振る舞いだけが会話を重ねるごとに変わっていきます。

品質責任はハーネスへ、その先にあるループエンジニアリング

一連のインプットの中で、いちばん自分の実感と結びついたのがこのテーマでした。

モデルの性能そのものより、ツール呼び出しや検証の仕組みといった「モデルの外側」の作り込みが成果を左右します。これがハーネスの考え方です。lintや型検査、テストでAI出力を縛るだけでなく、着手前の質問やプレモーテムのように、人間の理解を強制する用途にも広がっています。

ループエンジニアリングは、この考え方を「継続的に回る系」へ拡張したものだと捉えています。生成は確率的なままでよく、コードを書いたAI自身に自己評価させるのではなく、作る役と採点する役を別のエージェントに分離し、品質責任をテスト実行やカバレッジ計測のような決定論的な評価系へ寄せます。これでループを何周させても、結果の揺れが収まっていきます。

ただし代償もあります。

  • 検証負債:誰も見ていない出力が積み上がる
  • 理解負債:自分が書いていないコードへの理解が追いつかなくなる
  • 認知的降伏:ループが安定して動くほど、出力に意見を持たなくなる
  • トークン暴走:コストが見積もりを超えやすい

どれも動いている最中は音を立てず、気づいた頃には手遅れになっているのが厄介なところです。

ループエンジニアリングについては書きたいことが多いので、この記事では概要にとどめ、前に書いた記事Orange Bookの要約で触れた内容を別記事でまとめて深掘りする予定にしています。

事例:自分のVaultをエージェントシステムとして組み直した

抽象的な整理だけでは実感が湧かないので、自分が運用しているObsidianのZettelkastenで、実際に何を変えたかを書いておきます。

以前は「素材を集めて、AIに聞けば答えてくれる」くらいの雑な運用でした。今回の勉強を踏まえて、役割ごとに3つのSkillへ分割し直しました。

  • kb-compile(編纂役):InboxやFleeting Notesという「raw」な素材を読み、繰り返し登場する概念をPermanent Notesという「wiki」に書き出す。生成する役
  • kb-report(図書館係):問いを受け取り、wikiだけを読んで回答をレポートとして書く。rawには直接触れない
  • kb-lint(健康診断役):wiki全体を週次でスキャンし、矛盾や重複、数値の不整合を洗い出す。生成した本人ではなく別の役として検証する

これは、記事の前半で書いたRoutingパターンや委託型の話そのものです。1つの万能Skillに全部やらせず、生成・参照・検証という役割ごとに委託先を分けています。

境界の引き方も意識して決めました。rawは読み取り専用にし、Claudeが勝手に削除やリネームをできないようにしています。レポートはwikiだけを引用し、rawを直接引用しません。これは人間が「何を作るべきか」を決め、AIに「正しく動くか」の検証を任せるという分業ラインを、フォルダ構造として固定した例です。

kb-lintは、ハーネスとループエンジニアリングの節で書いた「作る役と採点する役の分離」の実装でもあります。kb-compileが生成した内容を、kb-compile自身には評価させません。別のSkillであるkb-lintに棚卸しさせます。週次で回すこの仕組みには、最小構成のループに必要な4点がすでに揃っています。オートメーション(週次トリガー)、Skill(役割ごとの前提知識)、ステートファイル(issues.md)、ゲート(矛盾チェック)です。

人間に残るのは、判断と検証と境界設計

実装のコモディティ化が進むほど、「何を作るべきか」を見極める力と、「作られたものが正しく動くか」を検証する力の価値が上がります。仕様が閉じた領域はAIが担い、正解のない可変な領域は人間の担当として残る、という分業が進んでいきます。

作るコストが下がっても、検証・運用・保守にかかる維持コストは自然には下がりません。生成コストが下がるほど、工程間の受け渡しが相対的なボトルネックとして目立つようになります。ボトルネックは消えずに移動し続けるので、移った先に合わせてプロセスや組織、アーキテクチャを組み替え続ける姿勢が必要だ、という指摘には素直にうなずきました。

この記事の執筆も同じです。textlintで表記の誤りは機械的に検出できますし、事例の叩き台もAIが出せます。ただし、どの事例が読者に刺さるか、どこまで書けば十分かという最終判断は、結局自分がしています。検証は任せられても、境界線を引く判断は残ります。

まとめ

一気に勉強してみて、自分の中で一番変わったのは「エージェントを賢くする」という発想の解像度でした。モデルを強くする、プロンプトを工夫するという単一の手段ではありません。オーケストレーション・ツールの粒度・学習方法・ハーネス・ループという複数の層に分け、層ごとに別の設計判断をする話だとわかりました。

面白かったのは、この整理が本の中だけで終わらなかったことです。

  • Claude Codeのsubagentの使い分け
  • 普段触っているMCPツール群の粒度差
  • メモリ機能
  • 自分のVaultのkb-compile・kb-report・kb-lint

振り返れば、どれも同じ原則の実装でした。知らないうちに、自分はすでにこの設計原則の上で動いていたことになります。

とくにループエンジニアリングは、ハーネスのさらに上に位置する層として、今の自分の日常的な使い方に一番近いです。次はこのテーマだけを掘り下げた記事を書くつもりです。