🏠 ホーム ニュース 📖 解説記事 📚 トピック解説 🏷️ タグ一覧 ℹ️ About
🔍 記事を検索
カテゴリ
📡 RSSフィード
Follow
X (Twitter) 🧵 Threads
Quick Links
ニュース一覧 🏷️タグから探す
🧠Claude 🤖Agent 💬LLM 🔌MCP 🛠️Tool
Subscribe
📡 RSSフィード
ホーム explain 2026.04.13

Agent ハーネスは魔法ではない。実装例から学ぶ基本構造

🤖
Agent ハーネスは魔法ではない。実装例から学ぶ基本構造 - AIツール日本語解説 | AI Heartland
// なぜ使えるか

要点まとめ

背景と文脈

ここ数年、LLM を活用したエージェント型アプリケーションへの関心が急速に高まっています。OpenAI の Function Calling、Anthropic の Tool Use、その他多くの LLM プロバイダーが Agent 機能を提供するようになりました。しかし、これらのツール連携メカニズムは、外部からは「複雑な魔法」に見えることが多い。

Agent ハーネスとは、LLM がツール呼び出しを自律的に判断・実行し、その結果をループバックして推論を続けるための基盤インフラを指します。多くの商用フレームワーク(LangChain、AutoGen、CrewAI など)は、この Agent ハーネスを内部に持ちながら、実装詳細を隠蔽しています。

結果として、開発者は「なぜこう動くのか」「どこで何が起きているのか」を理解しないまま、API を呼び出すだけになりがちです。

なぜ実装例が重要か
Agent ハーネスの実装例が公開されることで、開発者は Agent の動作原理を「黒箱の中身を白箱にする」プロセスを通じて習得できます。これはフレームワークの選択判断や、トラブルシューティング、カスタマイズ時の自信につながります。

Theo が実装例を公開した背景には、このギャップを埋める狙いがあります。Agent の仕組みは決して不可解ではなく、シーケンシャルなロジックの組み合わせに過ぎないことを実証することで、エコシステム全体のリテラシー向上を促そうとしています。

詳しく見ていく

Agent ハーネスの最小単位構成

Agent ハーネスの動作は、本質的には以下の 4 ステップを何度も繰り返すループです。

  1. LLM にプロンプトを送信 - 現在のコンテキスト(ユーザー入力、過去の会話履歴、利用可能なツール定義)を含めて
  2. LLM の応答を解析 - ツール呼び出しが含まれているかを判定
  3. ツール実行 - 指定されたツールをパラメータ付きで実行し、結果を取得
  4. 結果をフィードバック - 実行結果を新たなコンテキストとして LLM に返す

最小限の Agent ハーネス実装は、以下のような Python コードで表現できます。

from typing import Any, Dict, List
import json

class SimpleAgentHarness:
    def __init__(self, llm_client, tools: Dict[str, callable]):
        self.llm_client = llm_client
        self.tools = tools
        self.messages = []
    
    def run(self, user_input: str, max_iterations: int = 10) -> str:
        self.messages.append({"role": "user", "content": user_input})
        
        for _ in range(max_iterations):
            # Step 1: LLM に送信
            response = self.llm_client.chat.completions.create(
                model="gpt-4",
                messages=self.messages,
                tools=self._build_tool_definitions(),
                tool_choice="auto"
            )
            
            # Step 2: 応答を解析
            if response.stop_reason == "end_turn":
                # ツール呼び出しなし - 終了
                final_message = response.choices[0].message.content
                return final_message
            
            # Step 3 & 4: ツール実行 → フィードバック
            self.messages.append(response.choices[0].message)
            
            for tool_call in response.choices[0].message.tool_calls:
                tool_name = tool_call.function.name
                tool_args = json.loads(tool_call.function.arguments)
                
                # ツール実行
                result = self.tools[tool_name](**tool_args)
                
                # 結果をメッセージに追加
                self.messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "content": str(result)
                })
        
        return "Max iterations reached"
    
    def _build_tool_definitions(self) -> List[Dict[str, Any]]:
        definitions = []
        for tool_name, tool_func in self.tools.items():
            definitions.append({
                "type": "function",
                "function": {
                    "name": tool_name,
                    "description": tool_func.__doc__,
                    "parameters": self._extract_parameters(tool_func)
                }
            })
        return definitions

このコードが示すように、Agent ハーネスの実装は「ループ + LLM API 呼び出し + 関数実行」のシンプルな組み合わせです。

Tool 定義とスキーマ管理

Tool 定義は、Agent が「どんなツールが使えるのか」を理解するためのスキーマです。OpenAI の Function Calling では、以下のような JSON スキーマで tool を定義します。

{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "与えられた都市の現在の天気情報を取得",
    "parameters": {
      "type": "object",
      "properties": {
        "location": {
          "type": "string",
          "description": "都市名"
        },
        "unit": {
          "type": "string",
          "enum": ["celsius", "fahrenheit"],
          "description": "温度単位"
        }
      },
      "required": ["location"]
    }
  }
}

このスキーマが LLM に渡されることで、LLM は「get_weather という関数があり、location パラメータが必須で、unit はオプション」ということを認識します。

Tool 定義の精度が Agent 精度を左右する
Tool の説明文が不正確・不明確だと、LLM が誤ったツール選択や不正なパラメータ値を生成する可能性が高まります。必ず実装と説明文の整合性を確保し、エッジケースや制約条件も明記してください。

ステート管理とメッセージ履歴

Agent ハーネスの重要な役割は、メッセージ履歴(コンテキストウィンドウ)を管理することです。Agent が推論を続けるためには、以下の情報が必要になります。

メッセージ履歴の管理例:

# 初期状態
messages = [
    {"role": "user", "content": "東京の天気を調べて、洗濯物を干せるか判断して"}
]

# LLM 応答(ツール呼び出しあり)
messages.append({
    "role": "assistant",
    "content": None,
    "tool_calls": [
        {
            "id": "call_001",
            "function": {"name": "get_weather", "arguments": "{\"location\": \"Tokyo\"}"},
            "type": "function"
        }
    ]
})

# Tool 実行結果
messages.append({
    "role": "tool",
    "tool_call_id": "call_001",
    "content": "東京: 気温 22°C、湿度 65%、曇り、降水確率 10%"
})

# LLM の最終応答(ループ終了)
messages.append({
    "role": "assistant",
    "content": "東京の天気は曇りで、降水確率が低いため、洗濯物を干すのに適しています。気温も過ごしやすい 22°C です。"
})

このメッセージ履歴を保持することで、Agent は複数ターンのやり取りを通じてコンテキストを保ち、より精密な判断ができるようになります。

ループ制御とエラーハンドリング

Agent ハーネスの実装では、無限ループ防止や例外処理が不可欠です。

def run_agent_with_safeguards(self, user_input: str) -> str:
    iteration_count = 0
    max_iterations = 10
    token_budget = 4000  # トークン使用量の上限
    total_tokens_used = 0
    
    while iteration_count < max_iterations:
        iteration_count += 1
        
        try:
            # LLM 呼び出し
            response = self.llm_client.chat.completions.create(
                model="gpt-4",
                messages=self.messages,
                tools=self._build_tool_definitions(),
                max_tokens=500  # 1 回の応答の最大トークン数
            )
            
            # トークン使用量を追跡
            total_tokens_used += response.usage.total_tokens
            if total_tokens_used > token_budget:
                return "Token budget exceeded. Agent halted."
            
            # Tool 呼び出しがない場合は終了
            if not response.choices[0].message.tool_calls:
                return response.choices[0].message.content
            
            # Tool 実行(タイムアウト付き)
            for tool_call in response.choices[0].message.tool_calls:
                try:
                    result = self._execute_tool_with_timeout(
                        tool_call, timeout=5
                    )
                    self.messages.append({
                        "role": "tool",
                        "tool_call_id": tool_call.id,
                        "content": str(result)
                    })
                except TimeoutError:
                    self.messages.append({
                        "role": "tool",
                        "tool_call_id": tool_call.id,
                        "content": "Tool execution timeout"
                    })
                except Exception as e:
                    self.messages.append({
                        "role": "tool",
                        "tool_call_id": tool_call.id,
                        "content": f"Tool execution error: {str(e)}"
                    })
        
        except Exception as e:
            return f"Agent error: {str(e)}"
    
    return "Maximum iterations reached"

実装時の落とし穴:無限ループとトークン枯渇。ツール実行結果が曖昧だと LLM が同じツールを何度も呼び出す可能性があり、トークン消費が急速に増加します。必ず反復回数とトークン上限の両方を設定しましょう。

アーキテクチャと仕組み

Agent ハーネスの全体フロー:

sequenceDiagram participant User as ユーザー participant Harness as Agentハーネス participant LLM as LLM participant Tools as Tool関数群 User->>Harness: ユーザー入力 Harness->>Harness: メッセージ履歴に追加 loop Agent Loop 最大N回 Harness->>LLM: メッセージとTool定義を送信 LLM->>LLM: 推論実行 alt Tool呼び出しあり LLM-->>Harness: Tool呼び出し指示 Harness->>Tools: Tool実行 Tools-->>Harness: 実行結果 Harness->>Harness: 結果をメッセージに追加 else Tool呼び出しなし LLM-->>Harness: 最終応答 Harness->>User: 結果を返却 end end

このシーケンス図から読み取れるように、Agent ハーネスは LLM と Tool 実行環境の仲介役 です。LLM の判断(Tool 呼び出し指示)を解析し、Tool を実行し、その結果を LLM にフィードバックするループを何度も回します。

内部構造図:

flowchart TB A["入力: ユーザーリクエスト"] --> B{"初回か
ループ中か"} B -->|初回| C["メッセージ履歴初期化"] C --> D["Tool 定義ビルド"] B -->|ループ中| D D --> E["LLM API 呼び出し"] E --> F{"Tool 呼び出し
あり?"} F -->|なし| G["最終応答を返却"] F -->|あり| H["Tool 呼び出し解析"] H --> I["Tool 実行"] I --> J{"実行成功?"} J -->|成功| K["結果をメッセージ追加"] J -->|失敗| L["エラーメッセージ追加"] K --> M{"反復上限
到達?"} L --> M M -->|いいえ| E M -->|はい| N["タイムアウト応答返却"] G --> O["出力: Agent の応答"] N --> O

他の選択肢との比較

Agent ハーネスの実装方法やフレームワークは複数あります。自分で実装する場合と既存フレームワークを使う場合のトレードオフを表にまとめました。

項目 自前実装(Theo スタイル) LangChain AutoGen CrewAI
学習曲線 低い(基本から始まる) 中~高(抽象度が高い) 高(マルチエージェント対応) 高(ロール分担の概念)
カスタマイズ性 最高(すべて自分で制御) 高(プラグイン拡張可) 中(フレームワーク依存) 中(スキーマ定義に制限)
実装時間 長い(イチから構築) 中(ボイラープレート削減) 短い(テンプレート豊富) 短い(構造化が進む)
デバッグ性 最高(すべてが見える) 中(ロギング機能あり) 中(Agent 間通信が複雑) 低(内部ロジックが隠蔽)
本番環境対応 工数あり(堅牢性確保が必要) 良い(成熟したコード) 良い(多数の本番事例) 良い(エンタープライズ向け)
推奨用途 学習・プロトタイプ・特殊要件 汎用 Agent・Chatbot マルチエージェント・議論型 組織・ワークフロー型
どの選択肢を選ぶか
Agent ハーネスの仕組みを理解したうえで、フレームワークを選ぶ方が賢明です。まずは自前実装で基本を掴み、その後、スケーラビリティやチーム開発の効率を考慮してフレームワークへの移行を検討するのが定石です。

実務への影響

エンジニアにとっての意味

Agent ハーネスの実装例が公開される意味は、開発者エンパワーメントです。これまで、Agent を使うには LangChain や OpenAI の API リファレンスに頼るしかありませんでした。しかし、実装例があると、以下のようなことが可能になります。

  1. トラブルシューティングが簡単に - 「なぜ Agent がこの判断をしたのか」を追跡できるようになり、問題箇所を特定しやすくなります。
  2. カスタマイズが自信を持ってできる - フレームワーク内の「魔法」を理解することで、独自の機能追加や最適化が怖くなくなります。
  3. 意思決定が合理的に - フレームワーク選択や実装方針を「理解に基づいて」決められるようになります。

実装パターンの標準化

実装例の公開により、コミュニティ内で Agent ハーネスの「ベストプラクティス」が浮き彫りになります。

これらが標準化されることで、新規プロジェクトの開発速度と品質が大幅に向上します。

セキュリティと信頼性の向上

Agent ハーネス実装時のセキュリティ考慮事項
自前実装では、以下の点を必ず確認してください。
• Tool パラメータのバリデーション(LLM が意図しない値を渡す可能性)
• Tool 実行のサンドボックス化(悪意のある Tool 呼び出しを防ぐ)
• API キーやシークレットの保護(メッセージ履歴に含まれないようにする)
• レート制限(Tool 呼び出し頻度の上限設定)

実装例から学ぶことで、セキュリティリスクを事前に察知し、設計段階で対策を組み込めます。

まとめ

Agent ハーネスは、複雑に見えても、実装レベルでは「LLM 呼び出し + Tool 実行 + ループ制御」の組み合わせに過ぎない。Theo が実装例を公開したことは、AI エンジニアコミュニティにとって大きな転機です。

これまで「ブラックボックスの魔法」と思われていた Agent の仕組みが、白箱化されることで、以下のことが実現します。

  1. 開発者の自信と理解が深まる
  2. フレームワークの選択が賢くなる
  3. カスタマイズや最適化がしやすくなる
  4. セキュリティリスクへの認識が向上する

今後の AI 開発では、「フレームワークに依存する」のではなく、「基本を理解したうえでフレームワークを活用する」という姿勢が標準になるでしょう。Theo の実装例は、その転換点を象徴しています。

参照ソース


この記事はAI関連コンテンツの解説記事です。

Follow
よくある質問
Agent ハーネスとは具体的に何ですか?
LLM がツール呼び出しを判断・実行し、その結果をループバックして推論を続けるための基盤インフラです。LLM API 呼び出し、ツール実行、メッセージ管理をループで繰り返す仕組みです。
なぜ Agent ハーネスの実装例が重要なのですか?
フレームワークの内部ロジックを理解することで、開発者は Agent の動作原理を習得でき、カスタマイズやトラブルシューティングが容易になるためです。
Agent ハーネスのループが無限になる場合、どう防ぎますか?
反復回数の上限(例:最大 10 回)とトークン予算の上限を設定し、どちらかに達したら強制終了するコードを実装します。
広告
X 🧵 Threads Facebook LINE B! はてブ
🔔 AI速報、毎日Xで配信中
Claude Code・MCP・AIエージェントの最新ニュースをいち早くお届け
@peaks2314 をフォロー
記事の信頼性について
AI Heartland エディトリアルポリシーに基づき作成
複数ソース照合
公式情報・報道等を突き合わせて確認
ファクトチェック済
ソースURLの内容を検証
参照ソース明記
記事末尾に引用元を掲載
Next Read →
🚨 Axios重大脆弱性CVE-2026-40175、CVSS 10.0。1.15.0以上へ即時アップグレード必須
関連記事
📘 Claude Cowork攻略OSS『claude-cowork-guide』徹底解説|28ワークフロー・70プロンプト集
Florian Bruniaux氏のClaude Cowork攻略OSS『claude-cowork-guide』を日本語で徹底解説。28ワークフロー・70プロンプト・11プラグインをCC BY-SA 4.0で集約した非公式バイブル。CTOCプロンプト式・請求書自動化・スケジュール実行まで実例で網羅する。
2026.04.14
📐 design.mdとは?AIエージェントに一貫UIを生成させるデザイン仕様書の書き方入門
design.mdはAIにUIを作らせる際の色・フォント・余白・コンポーネントをMarkdownで定義する新しい仕様フォーマット。Claude Code・Cursor・Google StitchなどのAIエージェントに一貫したデザインで出力させる書き方の最小テンプレート、運用ルール、失敗例まで解説。
2026.04.14
🤖 AI Engineering from Scratch:290時間でAIエンジニアになる実践型カリキュラム
線形代数から自律エージェント開発まで、20フェーズ・260以上のレッスンで実務レベルのAIスキルを習得。毎レッスンで再利用可能なツール・プロンプト・エージェントを産出する革新的な学習メディア。
2026.04.13
📊 last30days-skill完全ガイド|Reddit・X・YouTube横断AIリサーチスキルの使い方2026年版
GitHubスター21,000超のClaude Codeスキル「/last30days」完全解説。Reddit・X・YouTube・HNなど13ソースを並列検索しアップボート・Polymarketオッズでスコアリング、AIが一本の調査レポートに合成。ゼロ設定で5ソース即日利用可。
2026.04.13
Popular
#1 POPULAR
🔓 Claude Codeソースコード流出の全貌:npm混入で51万行公開、未公開機能KAIROSも発覚
Claude Codeのnpmパッケージからソースマップ経由で51万行のTypeScriptソースが流出。未公開プロジェクトKAIROSや107個のフィーチャーフラグが発覚した経緯・影響・対策を詳細に解説。
#2 POPULAR
🎨 awesome-design-md:DESIGN.mdでAIにUI生成させる方法【58ブランド対応】
DESIGN.mdをプロジェクトに置くだけでAIエージェントが一貫したUI生成を実現。Vercel・Stripe・Claudeなど58ブランドのデザイン仕様をnpx 1コマンドで導入する方法と、実際の出力差を検証した結果を解説。
#3 POPULAR
📊 TradingView MCP:Claude CodeからTradingViewを完全操作する78ツールのMCPサーバー
TradingView MCPはClaude CodeからTradingView Desktopを直接操作できる78ツール搭載のMCPサーバー。チャート分析、Pine Script開発、マルチペイン、アラート管理、リプレイ練習まで自然言語で実行。導入手順を解説
#4 POPULAR
⚡ Claude Code NO_FLICKER modeの使い方:ちらつき解消とマウス対応でターミナルUI刷新
Claude CodeのNO_FLICKER modeは環境変数1つで有効化できる新ターミナルレンダラー。ちらつき解消・マウスイベント対応・差分レンダリングの仕組みと設定方法を解説。今すぐ使い方を確認しましょう。
#5 POPULAR
☁️ Floci入門:LocalStack代替のAWSローカル開発環境【起動24ms・25サービス対応】
FlociはLocalStack無料版の代替となるGo製AWSエミュレータ。S3・DynamoDB・Lambda等25サービスを起動24ms・メモリ13MiBで再現。認証トークン不要、go installで即導入。LocalStackとの詳細比較と導入手順を解説。
#6 POPULAR
🔗 Claude Microsoft 365 連携ガイド:SharePoint・Outlook・Teams接続と活用例
ClaudeのMicrosoft 365コネクタを使えばSharePoint・OneDrive・Outlook・Teamsのデータを横断検索・分析できます。全プラン(Free含む)対応。設定手順・活用例・セキュリティ設定・よくあるトラブル対処を初心者向けに解説します。
#7 POPULAR
⚠️ Anthropic、Claude Codeで予想外の高速クォータ枯渇認める。キャッシュバグで料金10〜20倍
Claude Codeでプロンプトキャッシュを破壊する2つのバグが発見され、API利用料が10〜20倍に跳ね上がる問題が発生。Anthropicは「チームの最優先事項」と認める。Pro/Maxユーザーから月間の大半で使用不可との報告多数。
#8 POPULAR
🤖 Anthropic、常時稼働型AIエージェント「Conway」を極秘テスト。AIが自律デジタル分身へ進化
Anthropicが「常時稼働」型AIエージェント「Conway」を開発中。Webhookでイベント駆動、24時間365日自律稼働。同時にCoworkも非エンジニア向けに急速普及。AIの動作モデルが根本から変わる
#9 POPULAR
🦊 Claude Sonnet 5(claude-sonnet-5-20260401)リリース:SWE-bench 92%超えで開発者が知るべき全仕様
AnthropicがClaude Sonnet 5(claude-sonnet-5-20260401)を2026年4月1日リリース。SWE-bench 92.4%・GPQA 96.2%と全ベンチマーク首位。料金はSonnet 4.6と同額$3/$15のまま据え置き。API移行・性能比較・実用コード付きで解説。
#10 POPULAR
🕷️ Spider Rs:Rust製の高速Webクローラーで大規模サイトマッピングを実現
非同期処理とメモリ効率を活かしたRust製Webクローラー。サイト構造の自動解析、複数URLの並列処理、カスタマイズ可能なスクレイピングに対応。SEO分析やコンテンツ監査の自動化を検討する開発チームへ
← AI Engineering from Scratch:290時間でAIエンジニアになる実践型カリキュラム Axios重大脆弱性CVE-2026-40175、CVSS 10.0。1.15.0以上へ即時アップグレード必須 →