優れたAI Agentの設計方法:アーキテクチャ原則から実践パターンまで
Software Spec、三層アーキテクチャ、LatentとDeterministicの境界、自己進化システムまでを扱う完全ガイド。2025〜2026年のAI coding agent分野における最先端の実践を深く読み解いています。
はじめに:AI Agent時代にエンジニアの役割は変わった
2025〜2026年、AI coding agentは質的な変化を遂げました。Claude Code、Codex CLI、Cursor、Kiroは、次の一行を補完するだけの自動補完ツールではなく、リポジトリ全体を理解し、複数ファイルを変更し、テストを実行して自律的に反復できるagentへ進化しました。GoogleのAddy Osmaniは、この新しい形を「AI-augmented software engineering」と定義しています。AIが自動化するのではなく、AIによって強化されたソフトウェアエンジニアリングです。
この区別は極めて重要です。開発者の役割は「コードを書く人」から「AIにコードを書かせる指揮者」へ変わりつつあります。 Andrew Ngは広く知られたslideで、その深い意味を指摘しました。AI codingが「構築」の段階を大幅に加速すると、プロダクトマネジメントが新たなボトルネックになります。 エンジニアは一日で三つのprototypeを作れても、PMのfeedbackが追いつきません。彼の結論はEngineer:PM比率が1:1へ近づき、自分で製品の方向を定義できる、つまりshape productできるエンジニア が非常に速く進むというものです。誰かを待たず、自分で「構築 → feedback → 反復」の完全なloopを回せるからです。
つまりAI時代で最も価値の高いエンジニアは、コードを最速で書く人ではなく、エンジニアと半分のPMを同時に担える人 です。その能力を支える技術的な媒体が、この記事の中心である 優れたAI agentシステムの設計方法 です。
1. Specから始める:自分とAIの間の「契約」
アーキテクチャを論じる前に、より基礎的な問いがあります。AIへ何を望んでいるか、どう伝えるのでしょうか。
1.1 Software SpecはPromptではない
AI coding agentの文脈におけるSoftware Specは、本質的にAIへ渡す「要件契約」です。何を求め、何を求めず、境界がどこにあるかを正確に記述し、最小限のやり取りで期待に最も近いコードを出力させます。
しかしSpecはpromptではありません。Promptは一つのメッセージで、送信後は会話履歴へ埋もれます。Specはリポジトリに固定され、セッションをまたいで存在し、プロジェクトとともに更新される 永続的でバージョン管理された文書 です。GitHubは2025年9月にSpec Kitをオープンソース化し、Spec-Driven Development(SDD)を正式に提案しました。AI agent時代には、specificationがcodeに代わってsource of truthになりつつある という明確な業界認識が形成されています。
1.2 Specがかつてないほど重要になった理由
AI coding agentは「非常に優秀な新人エンジニア」です。実行力が高く非常に速い一方、意図を自発的に推測しません。Specに空白があっても、AIは立ち止まって質問せず、自分で埋めることがあります。そして、その埋め方はしばしば意図と異なります。「ユーザー認証モジュールを書いて」と言えば、必要なのはAPI key認証だけなのに、JWT + OAuth2 + ソーシャルログイン一式を作るかもしれません。過剰設計がAIのデフォルトです。 Specが優れているほど、AIの出力は頭の中の完成像に近づきます。
さらに重要なのは、promptへ指示を入れすぎると、各指示に対するモデルの遵守率が大きく下がるという研究結果です。これは「指示の呪い」(Curse of Instructions)と呼ばれます。すべての要件を一つのメッセージへ積み上げることはできず、構造化され階層化されたspecで管理する必要があります。
1.3 良いSpecが扱う六領域
GitHubのAIチームが2,500件を超えるagents.mdを分析したところ、最も効果的なspecは六つの中核領域を扱っていました。Commands はflagと引数を含む完全な実行コマンドで、specの前半へ置きます。Testing は実行方法、framework、coverage要件。Project Structure は各directoryの用途を明示。Code Style は説明文三段落より実際のコード例一つが効果的。Git Workflow はbranch名やcommit message形式。Boundaries はagentが絶対に触れてはいけないものです。
「境界」は最も見落とされやすい一方、非常に効果的な制御です。AIが追加した不要なものを手直しするコストは、漏れた必要事項を追加で頼むコストより大きいからです。「現在のrequirements.txtにない依存関係を導入しない」という一文だけで、二時間の調査を省けるかもしれません。
1.4 Specのワークフロー:四段階のゲートモデル
GitHub Spec Kitは、実践で検証された四段階のワークフローを提案しています。各段階へ人によるチェックポイントを設け、その段階を検証してから次へ進みます。
Specify(意図の定義) → Plan(技術設計) → Tasks(タスク分解) → Implement(実行)
このゲート型ワークフローは「砂上の楼閣のコード」、つまり動くように見えても少し押すと崩れる脆弱なAI出力を防ぎます。何千行ものdiffをreviewする代わりに、特定の問題を解決する小さな変更を確認します。Agentは何を作るかをspec、どう作るかをplan、現在何をするかをtaskから理解します。
2. 三層アーキテクチャ:Fat Skills, Thin Harness, Deterministic Tooling
specの次は、AI agentシステム自体をどう設計するかという問いです。
優れたアーキテクチャの考え方は、AI agentシステムを三層へ分け、非常に簡潔な原則を示します。知能を上のskill層へ押し上げ、実行を下のdeterministic tool層へ押し下げ、中間のharnessを薄く保ちます。
2.1 下層:Deterministic Tooling(決定的ツール層)
下層は、アプリケーションが提供する決定的な能力です。QueryDB、ReadDoc、Search、Timeline、つまりSQL query、文書読み込み、検索実行、timeline取得などです。特徴は、同じ入力が必ず同じ出力を生むこと です。「知能」は不要で、正確に実行することだけが求められます。
この層は、従来のソフトウェアエンジニアに最もなじみがあります。Javaバックエンドの経験があるなら、以前に書いていたDAO層や基盤コード、つまりAPI呼び出し、データベースquery、ファイル操作に相当します。価値は信頼性と予測可能性にあります。
2.2 中間層:Thin Harness(薄い調整層)
中間層はLLMを実行する外側のプログラム、つまりClaude CodeやCodex CLIのようなツールの「殻」です。行うことは四つだけです。モデルをagentic loopで繰り返し実行する、ファイルを読み書きする、context windowを管理する、安全方針を実行する。 それだけです。
最小のagentic loopは、おおよそ次のような中核ロジックです。
ループ {
contextを収集(ユーザー入力 + system指示 + tool結果)
モデルを呼び出す
モデルがtoolを要求 → toolを実行し、ループを続ける
モデルが最終回答を返す → 出力して終了
}
この中核loopにcontext管理、安全方針、エラー処理を加えても、約200行のコードで実現できます。重要なのは、harnessがdomain知識(skillの責務)、具体的なtool実装(下層アプリケーションの責務)、業務判断(LLMのlatent spaceの責務)を 一切含まない ことです。
Javaバックエンドのアーキテクチャにたとえるなら、HarnessはSpring Boot framework自体です。DispatcherServletのrouting logicと業務コードを混ぜることはありません。frameworkが調整を行い、業務コードがlogicを担い、明確に分離されます。
アンチパターンは fat harness + thin skills です。40件を超えるtool definitionがcontext windowの半分を消費し、各MCP tool呼び出しに2〜5秒のnetwork round tripが発生し、REST APIの各endpointが個別toolとして包まれる場面があります。結果はtoken消費三倍、遅延三倍、失敗率三倍です。正しい方法は逆です。skillを太く、harnessを細く、toolを専門的かつ高速にします。
2.3 上層:Fat Skills(太い技能層)
上層はMarkdownで書いた操作手順であり、判断力、プロセス、domain知識 を符号化します。価値の90%がここにあるという主張です。
「太い」とはskillファイルが長いという意味ではなく、skillが持つ 知識密度 が高いことです。良いskillは、どの条件でどの判断をし、どの手順をたどり、どのdomain知識を使うかを詳細に符号化します。たとえばlast30days-skillのSKILL.mdには、複数platformの完全なデータ収集フローを記せます。各platformで使うAPI、query expansionの方法、結果の採点と並べ替え、出力形式などです。これはコードではなく自然言語の指示ですが、本当の専門知識を符号化しています。
2.4 このアーキテクチャが持つ最も優雅な性質
「このように設計すれば、モデルが進歩するたびにすべてのskillが自動的に向上し、deterministic層は完全な信頼性を保つ。」
skillは自然言語で判断logicを記すため、基盤モデルをSonnetからOpusへ、または次世代へ更新すると、skillに符号化した判断力が 自動的に向上します。 強いモデルは同じ指示をよりよく理解し実行でき、コードを一行も変える必要はありません。一方、下層のdeterministic toolはモデル変更の影響を受けません。上でどのモデルが動いても、SQL queryはSQL queryです。
システムの二つの半分は異なる方法で進化します。上層はモデルの進歩とともに自動で改善し、下層は完全な安定を保ちます。 組み合わせによって複利効果が生まれます。
従来のバックエンドへ正確にたとえると、Controller層(harness)は薄く調整だけを行い、Service層(skills)は太く業務logicと判断を担い、DAO層(deterministic tooling)は決定的なデータ操作を行います。構造は同型で、「業務logic」が「判断力」へ、「コード」が「自然言語の指示」へ変わっただけです。
3. Resolver:コンテキストのルーティングテーブル
skillとdomain知識が増えると、正しい時点で正しい知識をモデルへ読み込ませる方法が問題になります。これを解決するのが Resolver です。
3.1 中心概念
Resolverはcontextのrouting tableです。X型のタスクが現れたら、先にY文書を読み込みます。Skillはモデルに「どう行うか」を伝え、Resolverは「いつ何を読み込むか」を伝えます。 異なる層の概念です。
例として、開発者がpromptを変更するとします。resolverがなければ、そのまま本番へ出るかもしれません。resolverがあれば、モデルは先にdocs/EVALS.mdを読みます。そこには「prompt変更後にeval suiteを実行してscoreを比較し、精度が2%を超えて低下したらrollbackして調査する」と記されています。開発者自身がeval suiteの存在を知らなくても、resolverが正しい時点で正しいcontextを読み込みます。
3.2 Resolverが解決する根本的な矛盾
AI agentアーキテクチャには根本的な矛盾があります。モデルが多くを知るほどよい一方、context windowを埋めるほど性能が下がります。
現実の事例がよく示しています。ある開発者のCLAUDE.mdは20,000行へ膨らみました。遭遇したquirk、pattern、教訓をすべて入れたためです。結果としてモデルのattentionが劣化し、Claude Code自身が削減を提案しました。最終的にCLAUDE.mdを約200行へ減らし、各文書へのpointer、つまりindexだけを置き、resolverで必要なときに読み込むようにしました。
20,000行の知識は残っていますが、context windowを汚染しません。これは lazy loading です。アプリケーション起動時にデータベース全体をメモリへ読み込まず、必要な行だけをqueryします。Resolverはcontext windowに対するlazy loading機構です。
3.3 Claude Codeの組み込みResolver
Claude Codeには組み込みresolverがあります。各skillがdescription fieldを持ち、モデルがユーザーの意図とskill descriptionを自動で対応づけます。skillのcommand名を覚える必要はなく、description自体がresolverです。
ここから重要な設計原則が得られます。resolverの品質はdescriptionの品質に依存します。 「データ関連タスクを処理する」のように曖昧だと、不要なときに発火したり、必要なときに漏れたりします。Descriptionはresolverのrouting ruleであり、正しくrouteできるほど正確でなければなりません。
これはMCP Server開発のtool descriptionとまったく同じ問題です。MCP toolのdescriptionもresolverとして機能し、モデルはdescriptionからいつどのtoolを呼ぶか決めます。良いtool descriptionと良いskill descriptionを書く能力は、根底では同じです。
3.4 実践案:AGENTS.mdをインデックス+ルーターとして設計する
プロジェクトが増え、patternやgotchaが蓄積すると、CLAUDE.mdやAGENTS.mdは膨張します。早い段階で、知識百科ではなく、index+routeシステムとして設計します。
あるプロジェクトのAGENTS.mdには、「このプロジェクトの開発規約はdocs/AGENTS-project.mdを参照」と一行だけ書き、そのファイルへAPIのquirk、framework固有の処理、テスト戦略などを置けます。Agentはプロジェクトのタスクを扱うとき自動で読み、ほかのプロジェクトでは情報に邪魔されません。
正しい知識を、正しい時点で、正しい場所へ置きます。それ以外の時間は、貴重なattention budgetを消費させません。
4. 最も重要な設計判断:Latent vs. Deterministic
この記事から一つだけ覚えるなら、この概念です。
4.1 明確に引かなければならない線
AI agentシステムの各段階は、二つのどちらか一方にだけ属します。
Latent space(潜在空間) はLLMが得意な領域です。読む、理解する、判断する、統合する、patternを認識する。唯一の正解がなく、「知能」を必要とするタスクです。
Deterministic(決定的) は従来コードが得意な領域です。同じ入力が常に同じ出力を生みます。SQL query、コンパイル済みコード、算術、組み合わせ最適化などです。
両者の混同はagent設計で最も一般的な誤りです。
分かりやすい例として、LLMは8人の夕食会の座席を、性格と人間関係を考慮して決められます。小規模な判断問題であり、latent spaceが扱えます。しかし800人の座席を任せると、もっともらしく見えて完全に誤った案を作ります。800人の座席配置は本質的に組み合わせ最適化問題、つまりdeterministicであり、latent spaceへ無理に押し込まれたからです。
4.2 二方向の誤り
誤り1:deterministicな仕事をlatent spaceへ入れる。 たとえば二つの日付の間の日数をLLMへ計算させます。唯一の正解があり、一行のコードで正確に求められます。しかしLLMは正しいことも、誤ることも、一日ずれることもあります。本質的に「計算」ではなく、「もっともらしい数字を推測」しているからです。
誤り2:latent spaceの仕事をdeterministicにハードコードする。 たとえばif-elseとキーワード一致で、ユーザーの文が「苦情」か「提案」かを判断します。自然言語の表現は無限にあるため、脆弱でcoverageも低くなります。このタスクには意味理解が本質的に必要です。
最悪のシステムは両方の誤りに満ちています。LLMへ算術や正確な検索をさせる一方、ハードコードした規則で意味理解や内容統合を行います。最良のシステムは、この境界に対して容赦がありません。
「容赦なく(ruthless)」とは、分類判断に曖昧さや手抜きを許さないという意味です。開発者には惰性があります。すでにLLMと対話していれば、そのまま数値計算や形式変換も頼むのが便利に見えます。しかし手抜きの蓄積が、システムの不可靠性の原因です。優れたエンジニアは、Javaプロジェクトで「業務logicをControllerへ書かない」と守るように、この惰性へ抵抗します。これは頑固さではなく、エンジニアリングの規律です。
4.3 実践で境界を引く
Telegram botの記憶関連通知機能を例に、各段階がどちら側かを考えます。
第1段階:Mem0から新しい記憶と意味的に近い過去の記憶を検索する。 → Deterministic。 APIを呼び、queryを渡し、top-Kの結果を受け取ります。入力と出力が決まったAPI呼び出しであり、LLMの判断は不要です。
第2段階:検索した過去の記憶と新しい記憶の間に、意味のある関係があるか判断する。 → Latent space。 「意味のある関係」は意味理解を必要とします。表現がまったく違っても、同じ概念の別の側面を述べている可能性があります。
第3段階:関連する記憶の数と関連度scoreに基づき、通知するか決める。 → Deterministic。 「関連する記憶が2件以上、平均関連度が0.7を超えたら通知する」ならif文で十分です。LLMへ任せると毎回異なる判断をし、ユーザー体験を予測できなくなる可能性があります。
5. Diarization:LLMが持つ最も代替しにくい価値
latentとdeterministicの境界を明確にすると、自然な問いが生まれます。latent spaceの最も独自で代替できない能力は何でしょうか。答えは Diarization(総合的な抽出) です。
5.1 Diarizationとは何か
元は音声処理分野の用語(speaker diarization、話者分離)ですが、AI agentアーキテクチャでは新しい意味を持ちます。モデルが大量の分散した情報を読み、何十件、何百件もの文書から一ページの構造化された判断、つまり分析briefへ蒸留します。
中核となる主張は、SQL queryでは生成できず、RAG pipelineでも生成できない ということです。モデルは実際に読み、矛盾した情報を同時に保持し、いつ何が変化したかに気づき、構造化された洞察へ統合しなければなりません。データベースqueryとアナリストのbriefの違いです。
5.2 RAGがDiarizationを実行できない理由
よくある誤解を解消する必要があります。RAGも複数文書から情報を取り出して回答を生成するため、diarizationができると考える人がいます。しかし本質は異なります。
RAGの中心は 検索 です。queryが与えられると、最も関連する文書chunkを見つけ、モデルに回答を生成させます。「どの情報が質問と関連するか」を解決します。
Diarizationの中心は 総合判断 です。一つのqueryから検索するのではなく、あるentity、つまり人、プロジェクト、trendに関する情報をすべて読み、矛盾、変化の軌跡、暗黙のpatternを発見して、洞察のある分析を作ります。「これらの情報を合わせると何を意味するか」を解決します。
現実の例では、ある創業者が申請書で「AI agent向けのDatadog」、つまり可観測性toolを作っていると言いながら、GitHub commitの80%が課金moduleにあります。実際にはFinOps toolを作り、可観測性の外見で包んでいることを意味します。
この差を見つけるには、GitHub commit履歴、申請書、advisorとの会話記録という三種類の資料を同時に読み、頭の中で交差比較する必要があります。ベクトル検索は「FinOpsに関連する文書」を見つけられますが、「口で言っていることと手で作っていることが一致しない」とは判断できません。ここがdiarizationの専有領域です。
5.3 Diarizationの利用場面
このpatternは多くの場面へ移せます。ユーザー行動分析では、言うことと行うことの差を発見します。競合情報では、複数の情報源から本当の戦略方向を判断します。code reviewでは、PR全体を読んで一行ごとの検査ではなく、アーキテクチャ上の判断を行います。知識管理では、ユーザーの断片的な記憶から構造化された認知profileを作ります。
中核patternは常に同じです。検索(deterministic)→ 全資料を読む(latent)→ 総合判断(latent)→ 構造化した洞察を出力(deterministic)。 検索と出力はdeterministic、読解と判断はlatent spaceに属し、境界は明確です。
6. 学習するシステム:一度限りの作業から永久的な向上へ
これまでの五概念、spec、三層アーキテクチャ、resolver、latent vs. deterministic、diarizationは静的な設計原則です。組み合わせて 自己進化するclosed loop を作ると、システムは質的に変わります。
6.1 学習ループの設計
6,000人の参加者を、業界の親和性によるcluster、異業種間の「思いがけない出会い」、リアルタイムpairingなどで知的にgroupingするイベントmatchingシステムを考えます。
イベント後、/improve skillがNPS調査を読み、diarizationを実行します。低評価は個別の極端な事例が多いため分析せず、「まあまあ」という評価を特に分析します。 システムがあと少しで成功したのに完全には正しくなかった部分です。そこからpatternを抽出して新しい規則を提案し、matching skillファイルへ書き戻します。
参加者が「AIインフラストラクチャ」と言っていても
startupのコードの80%以上が課金関連なら:
→ AIインフラストラクチャではなくFinTechへ分類する。
同じgroupの二人がすでに知り合いなら:
→ 親密度にpenaltyを与え、新しい紹介を優先する。
規則は次回の実行から自動的に有効になります。Skillが自分自身を書き換えました。
最初のイベントでは「まあまあ」の評価が12%、次は4%でした。人がコードを書き直さなくてもシステムが改善しました。
6.2 ループの構造
学習loop全体は、実行 → feedback収集 → 「あと少し」の箇所を分析 → 新規則を抽出 → skillへ書き戻す → 次回実行時に自動使用 という構造です。
このloopでもlatent vs. deterministicの境界は明確です。NPS feedbackの分析、pattern抽出、新規則の提案はlatent spaceの仕事。規則をファイルへ書き、次回読み込む処理はdeterministicです。アーキテクチャ原則は各層で一貫します。
6.3 「同じことを二度頼まなければならないなら、あなたは失敗している」
この指示は、アーキテクチャの規律を正確に表現しています。
一度限りの作業は認められない。将来も必要になる作業を頼まれた場合、まず3〜10件のsampleを手作業で行い、結果を示す。承認されたらskillファイルとして固定する。自動実行すべきならscheduleへ接続する。
prompt engineeringのテクニックではなく、システム設計の思想です。作成する各skillは、システムへの永久的なupgradeです。 劣化も忘却もせず、睡眠中の午前3時にも動きます。次世代モデルが出ると、すべてのskillが即座に向上します。latent spaceの判断力は自動で改善し、deterministicな段階は完全な信頼性を保ちます。
実践上、AI coding agentでプロジェクトを開発中、同様の指示を繰り返していると気づいたら、「コードスタイルが規約に従うか確認する」「CHANGELOGを更新する」「テスト後に失敗原因をまとめる」などをskillファイル、またはAGENTS.mdの永続規則へ固定すべきです。固定するたび、システムは永久的に向上します。
7. 完全な思考モデル
これまでの概念をつなげると、優れたAI agentシステムの設計思考は次のようになります。
第1段階:Specで意図を定義する。 コードを書く前に、何を求め、何を求めず、制約が何かを明記します。Specは自分とAIの契約であり、システム全体のsource of truthです。
第2段階:Latent vs. Deterministicの線を引く。 システムの各段階を確認し、どちらに属するかを容赦なく判断します。判断力はLLM、正確性はコードへ渡し、曖昧さを許しません。
第3段階:三層アーキテクチャを作る。 知能をskill層へ押し上げます。自然言語で符号化した判断力とdomain知識です。実行をdeterministic tool層へ押し下げます。信頼できるAPI呼び出し、データベースquery、algorithmです。中間のharnessは薄く保ち、調整だけを行います。
第4段階:Resolverで知識の読み込みを管理する。 すべての知識を一つのファイルへ入れません。index+routeシステムを設計し、正しい知識を正しい時点で正しい場所へ置きます。
第5段階:DiarizationでLLMの独自価値を引き出す。 総合判断が必要な場所では、全資料を読み、矛盾を保持し、変化を発見し、洞察を生成させます。最も代替できない能力であり、SQLやRAGで置き換えないでください。
第6段階:学習ループを作る。 実行 → feedback収集 → 「あと少し」の箇所を分析 → 新規則を抽出 → skillへ書き戻します。システムを自己進化させ、各skillを永久的なupgradeにします。
六段階は線形pipelineではなく、継続して動く設計思考フレームワークです。各判断でこの枠組みに戻り、Specは明確か、段階は正しい側にあるか、知識を読み込む時点は正しいか、この機能をskillへ固定できるかを検証できます。
結論:AI時代のエンジニアに必要な中核能力
冒頭の問いへ戻ります。AI時代で最も価値の高いエンジニアは、どのような人でしょうか。
コードを最速で書く人ではありません。AIがすでに十倍に加速しました。価値が高いのは、明確なSpecで意図を定義し、latent vs. deterministicの境界を引いてアーキテクチャ判断を行い、AIの知能とコードの決定性を適切に分担させるシステムを設計し、自己進化する学習loopを作れる人 です。
共通する特徴は、「コードを書くこと」そのものではなく、コードに関する判断力 であることです。何を書くか、何を書かないか、何をAIへ渡すか、何をコードへ渡すか、何を規則として固定し、何を柔軟なまま保つかを判断します。
従来のバックエンド経験があれば、なじみのある能力です。Javaプロジェクトで「業務logicをControllerへ書かない」と守る規律と、AI agentシステムで「deterministicな仕事をlatent spaceへ入れない」と守る規律は、本質的に同じエンジニアリング素養です。関心事の分離、階層設計、正しい抽象層で正しいことを行うこと。 システムにLLMという新しい構成要素が増え、その責務の境界を正確に定める必要が生まれただけです。
一度構築し、永続的に実行する。システムは複利で成長します。
参考資料
- Addy Osmani, “How to write a good spec for AI agents”, January 2026
- Addy Osmani, “My LLM coding workflow going into 2026”, December 2025
- GitHub Blog, “Spec-driven development with AI”, September 2025
- GitHub Blog, “How to write a great agents.md: Lessons from over 2,500 repositories”, November 2025
- Martin Fowler (Birgitta Böckeler), “Understanding Spec-Driven-Development: Kiro, spec-kit, and Tessl”, 2025
- Kiro Documentation, “Specs”, 2026
- Andrew Ng, “Building at speed: The Product Management Bottleneck”, 2025