AI AgentsLLM AgentsAgent Architecture

LLM APIでAIエージェントを構築:アーキテクチャとコード

約1分

AIエージェントは、function calling付きチャットボットではありません。知覚し、推論し、行動し、学習するシステムです——自律的に、複数ステップを跨いで、行動間に持続する状態を持ちます。Anthropicの効果的なエージェント構築ガイドは、エージェントアーキテクチャパターンを理解する最良の出発点です。チャットボットは質問に答えます。エージェントは、あなたが飛行機に乗っている間にフライトを予約し、会議をリスケジュールし、チームのSlackを更新します。

2026年、誰もがエージェントを構築しています。多くが本番で壊れます——永遠にループし、間違ったツールを呼び、3ステップ前のことを忘れます。このガイドはそれらの失敗を防ぐアーキテクチャを扱います。ツール呼び出しループからメモリシステム、マルチエージェントオーケストレーションまで、すべてのセクションに動作するコードがあります。読み終わる頃には、フォークして拡張できる研究アシスタントエージェントが動いています。

AIエージェントを構成するもの——そしてしないもの

定義。 AIエージェントには3つの層があります:推論コア(LLM)、ツール層(API、データベース、コード実行)、メモリ層(短期会話、長期知識、作業状態)。単純なLLM呼び出しとの重要な違い:エージェントはループ内で自律的な決定をします。応答するだけではありません。計画し、行動し、結果を観察し、次に何をするか決定します。

3つの層:

User Query → Reasoning Core (LLM) → Decision → Tool Execution → Observation → Memory Update → Next Decision → ... → Final Response

エージェントが必要なとき vs 単純なLLM呼び出し。 エージェント:モデルが情報を収集し、アクションを実行し、結果に基づいて適応する必要がある多段階タスク。「このトピックを調査してレポートを書いて」——エージェント。「この記事を要約して」——単純呼び出し。「このエラーをデバッグして、ログを確認し、修正でPRを開いて」——エージェント。「このエラーメッセージを説明して」——単純呼び出し。

タスクが外部ツール使用なしで1回のAPI呼び出しで完了できるなら、エージェントは不要。複数のソースから情報を収集し、アクションを実行し、中間結果に基づいて決定する必要があるなら、エージェントが必要。決定木:1ステップ?——単純呼び出し。ツール付き複数ステップ?——エージェント。

ツール呼び出しループ:エージェントの手

コアエージェントループ。すべてのエージェントフレームワーク——LangChain、CrewAI、AutoGen、生のコード——はこれの何らかのバージョンを実装します。

import json
from openai import OpenAI

client = OpenAI(
    base_url="https://api.tokspan.com/v1",
    api_key="ts-your-key-here"
)

class Agent:
    def __init__(self, model: str, tools: list, max_iterations: int = 10):
        self.model = model
        self.tools = {t["function"]["name"]: t for t in tools}
        self.max_iterations = max_iterations
        self.memory = []  # Working memory —the agent's scratchpad

    def run(self, user_query: str) -> str:
        messages = [
            {"role": "system", "content": "You are a research assistant. Use tools to gather information, then synthesize a report."},
            {"role": "user", "content": user_query}
        ]

        for iteration in range(self.max_iterations):
            response = client.chat.completions.create(
                model=self.model,
                messages=messages,
                tools=list(self.tools.values()),
                tool_choice="auto"
            )

            msg = response.choices[0].message

            # Agent decided to respond with text —done
            if msg.content and not msg.tool_calls:
                return msg.content

            # Agent decided to call tools —execute and continue
            if msg.tool_calls:
                messages.append(msg)
                for tool_call in msg.tool_calls:
                    tool_name = tool_call.function.name
                    tool_args = json.loads(tool_call.function.arguments)
                    result = self._execute_tool(tool_name, tool_args)
                    messages.append({
                        "role": "tool",
                        "tool_call_id": tool_call.id,
                        "content": str(result)
                    })

        return "Agent reached maximum iterations without completing the task."

    def _execute_tool(self, name: str, args: dict):
        # In production: dispatch to actual functions
        print(f"Calling tool: {name}({args})")
        return f"Result from {name}"

ツール定義のベストプラクティス。 ツールの説明はプロンプトです——明確に書きましょう。各ツールを使うタイミングの例を含めます。パラメータを厳密に制約——自由テキスト文字列ではなく列挙型。ツールを冪等に——同じパラメータで同じツールを2回呼んでも同じ結果を生むべき。ツール実行が失敗したら、エラーメッセージをモデルに送り返します——異なるパラメータを試して回復できることがよくあります。

完全なクロスプロバイダーfunction calling比較——OpenAI vs Anthropic vs Google vs DeepSeek実装含む——は、クロスプロバイダーfunction callingガイドをご覧ください。

ループ内のエラー処理。 ツール実行が失敗——エラーをモデルに送り返す——モデルが決定:異なるパラメータで再試行、別のツールを試す、またはユーザーに知らせる。モデルはツールエラーからの回復に驚くほど優れています——ただしエラーを送り返した場合のみ。ツール失敗を黙って飲み込むと、不可解に失敗するエージェントが生まれます。

メモリシステム:記憶することを教える

メモリのないエージェントは金魚です——ステップ間のすべてを忘れます。3つのメモリタイプ、それぞれ特定の目的があります。

短期メモリ——会話履歴。 messages配列。ユーザーが言ったこと、エージェントがしたこと、ツールが返したこと。スライディングウィンドウとして管理——履歴がモデルのコンテキスト上限に近づいたら、最古のメッセージを削るか要約。要約トリガー:総トークンがコンテキストウィンドウの80%を超えたら、会話の最古の50%を単一のシステムメッセージに要約。

長期メモリ——ベクトルストア。 過去のやり取り、ユーザー設定、学んだ事実——ベクトルデータベースにエンベディングとして保存、現在のクエリとの類似度で取得。実装:重要なやり取りをそれぞれエンベッド——ChromaDBまたはPineconeに保存——新しいクエリごとに、最も類似した過去のやり取りを上位3〜5件取得——システムプロンプトにコンテキストとして含める。「エージェントが先週何を話したか知っている」と「エージェントが毎回会話をゼロから始める」の違いです。

作業メモリ——スクラッチパッド。 エージェントの現在の計画、中間結果、仮説——各ループ反復で更新されるJSONオブジェクトとして保存。エージェントは今何を達成しようとしているか?何を試したか?何を学んだか?スクラッチパッドはエージェントの「思考の流れ」——外部化され、ツール呼び出しを跨いで生き残り、デバッグ用に検査できます。

メモリアーキテクチャ。 3つのメモリすべてが各ループ反復でエージェントに供給されます:会話履歴(何が起きたか)+取得した長期メモリ(過去からの何が関連するか)+作業メモリ(今何をしているか)。LLMがこれらを次の決定に統合します。

マルチエージェントシステム:1つのエージェントでは足りないとき

15個のツールを持つ単一エージェントは下手な決定をします——選択肢が多すぎ、コンテキストが多すぎ、選択精度が劣化。解決策:各々が焦点を絞ったツールセットと明確な責任を持つ専門エージェント。

オーケストレーションパターン:

  • スーパーバイザー/ワーカー。 1つのオーケストレーターエージェントが専門ワーカーエージェントにタスクを割り当てます。スーパーバイザーは作業をしません——調整します。「このトピックを調査して」——スーパーバイザーが研究者エージェント、分析者エージェント、ライターエージェントに派遣——スーパーバイザーが結果をまとめます。
  • ピアツーピア討論。 2つのエージェントが決定の反対側を論じ、収束します。「このローンを承認すべきか?」——エージェントAが賛成、エージェントBが反対——両者が互いの議論をレビュー——共同推奨を作成。
  • シーケンシャルパイプライン。 エージェントAの出力がエージェントBの入力。「このコードベースを分析して」——コード分析者がレポートを出力——バグファインダーがレポートを使って問題を特定——修正生成器が解決策を提案。

マルチエージェント通信。 共有メッセージバスを使用——各エージェントが{from: "researcher", to: "analyst", content: "...", type: "report"}のような構造化メッセージとして出力を公開。これでエージェント相互作用グラフが観察・デバッグ可能に。問題が起きたとき、どのエージェントがどの出力をなぜ生成したかを正確に追跡できます。

マルチエージェントのコスト。 各エージェントが独自のLLM呼び出しをしています。3エージェントシステムは単一エージェントの3倍のAPI呼び出し。緩和:ワーカーエージェントには安いモデル(DeepSeek V4 Flash、$0.14/$0.28)、オーケストレーターにはフロンティアモデル(Claude Opus、GPT-5.5)を確保。オーケストレーターが高リスク決定をします。ワーカーは実行します。

今日デプロイできる具体的な3エージェント研究パイプラインがここにあります。研究者エージェントはGemini 3.1 Pro(入力$2.00/M)を、正確に2つのツール——ウェブ検索と文書取得——で使用し、ツール選択麻痺に陥りません。出力は構造化JSONブリーフ:{sources: [...], key_facts: [...], gaps: [...]}

ライターエージェントはGPT-5.5(入力$5.00/M)で、フォーマットツールのみを使ってそのブリーフを草稿に変換。レビューアーエージェントはClaude Opus 4.8(入力$5.00/M)で、各主張を元のソースと照合し、幻覚をフラグし、スコア付きレビューを返します:{score: 1-10, issues: [...], corrected_draft: "..."}。タスクあたりコストは$0.12〜0.35——研究者がトークンの約40%を消費、ライター約35%、レビューアー約25%。

メッセージバスはエージェント間で渡される単純なPython dict——フレームワーク不要。各遷移で{timestamp, from_agent, to_agent, payload_type, token_count}をログすれば、何かが壊れたときすべての引き継ぎを追跡できます。

エージェント失敗のデバッグ

エージェントは予測可能な方法で失敗します。最も一般的な3つの障害モード:無限ループ(ツールを呼ぶが決して収束しない)、間違ったツール選択(モデルが不適切なパラメータで無関係なツールを選ぶ)、コンテキストオーバーフロー(会話履歴がモデルのコンテキストウィンドウを超え、早期メッセージを黙って落とす)。それぞれに診断パターンがあります。

無限ループには、反復を検出するためにエージェントのアクションをログ——同じツールが同じパラメータで3回連続で呼ばれたら、エージェントは詰まっています。介入:システムメッセージを注入して「{tool}{args}で複数回呼びました。結果は変わりません。別のアプローチを試すか、これまでの結果を報告してください。」

間違ったツール選択には、各反復でツール名、パラメータ、結果をログ——パターンが見えます。query_databaseを呼ぶべきときにsearch_webを呼ぶエージェントは、モデルの問題ではなく書き直しが必要なツール説明を露呈します。

コンテキストオーバーフローには、APIのusageフィールドを使って各反復でtotal_tokensを追跡。トークンがコンテキスト上限の80%を超えたら——GPT-5.5で1M、Claude Opusで200K——次の反復前に最古の50%のメッセージを要約。最も一般的な開発者ミス:エージェントが無意味な出力を生成するまでresponse.usage.total_tokensをチェックせず、5反復前にコンテキストが黙って切り詰められたことに気づかない。

構造化ロギングは、あなたが持つ最も効果的な単一のデバッグツールです。最低限、反復ごとにログ:{iteration, model, tool_calls, tokens_used, latency_ms, error}。20回のエージェント実行後、どの障害モードが最も頻繁に噛みつくかを特定するのに十分なデータがあります。

パフォーマンス回帰にもすぐ気づきます——通常200msのツール呼び出しが突然2秒かかるのは、インシデントになる前のシグナルです。

どのエージェント役割にどのモデル?

エージェント役割最適モデル理由
OrchestratorGPT-5.5最も信頼性の高いツール使用、最良の並列ツール呼び出し
Code AgentClaude Opus 4.8最高のSWE-benchスコア、最良のアーキテクチャ推論
Research AgentGemini 3.1 Pro文書分析に最適な2Mコンテキスト、マルチモーダル
Cost-Efficient WorkerDeepSeek V4 Pro出力$0.44/Mで92%のHumanEval
Writer AgentGPT-5.5最良の散文品質と文体の幅

集約プラットフォームの利点:1つのAPIキーで5モデルすべてにアクセス。各エージェント役割を最適なモデルにルーティング。エージェントコードを変えずにモデルを変更。オーケストレーター、コードエージェント、研究者エージェント、ワーカーすべてが同じOpenAI SDK——異なるmodelパラメータだけ。

異なるタスクを異なるモデルにルーティングする——すべての本番エージェントシステムが使うパターン——のより深いアーキテクチャ議論は、1つのアプリで複数AIモデルを使うガイドをご覧ください。

FAQ

エージェントを構築するのにLangChainのようなフレームワークが必要ですか?

いいえ。コアエージェントループは約50行のPython——この記事のコードは完全に動作するエージェントです。フレームワークは便利さ(既製ツール、トレーシング、メモリバックエンド)と複雑さ(抽象化層、依存ツリー、バージョン間の破壊的変更)を追加します。素の状態から始めましょう。フレームワークが解決する具体的な問題があるときだけ追加。LangChainにすぐ飛びつく開発者はよく後悔します——エージェントを構築するよりフレームワークのデバッグに時間を費やします。

エージェントに最良のモデルは?

ツール使用の信頼性にはGPT-5.5——正しいツールを正しいパラメータで呼ぶのに最も一貫。信頼性より深さが重要な複雑な多段階推論にはClaude Opus。長文脈タスクにはGemini。コスト効率エージェントにはDeepSeek V4 Pro。多くの本番エージェントシステムは2〜3モデルを使用:信頼できるオーケストレーター(GPT-5.5)、複雑なステップ用の深い推論スペシャリスト(Claude Opus)、高量単純タスク用のコスト効率ワーカー(DeepSeek)。

エージェントが永遠にループするのを防ぐには?

3つの安全装置。max_iterationsを設定(ほとんどのタスクで10〜20が妥当)。タスク完了を追跡——エージェントの最後の3つのアクションが新しい情報を生み出さなかったら、詰まっています;終了して部分結果を返す。エージェントセッションあたりの予算上限——$0.50の支出制限が無限ループを$50の問題になる前に捕捉(支出上限とレート制限をガードレールとして設定する方法はキー管理と予算管理ガイドをご覧ください)。常にタイムアウト+優雅なフォールバック応答を。

AIエージェントの運用コストは?

単純エージェント(3〜5回のツール呼び出し):DeepSeek V4 Proでタスクあたり$0.05〜0.20。複雑なマルチエージェント(10〜20回):混在モデルでタスクあたり$0.50〜2.00。コストベースルーティングを使用:単純タスク——安いモデル、複雑タスク——フロンティアモデル。タスクあたりコストは他のインフラコストと同じように測定・最適化すべきです。

本番デプロイ前にエージェントの信頼性をテストするには?

エージェントの想定タスク範囲をカバーする20〜50の手動ラベル付きテストケースで評価ハーネスを構築。各ケースを5回実行——エージェント行動は非決定的なので、1回のパスは何も証明しません。2つの指標を測定:タスク完了率(エージェントは有効な出力を生成したか?)とツール選択精度(正しいツールを正しい順序で呼んだか?)。

完了率85%未満は、プロンプトかツール説明の改善が必要。マルチエージェントシステムには3つ目の指標を追加:引き継ぎの正確さ——各エージェントは上流エージェントから期待した入力形式を受け取ったか?1つの悪い引き継ぎが下流の失敗に連鎖します。

単一エージェント vs マルチエージェントシステムはいつ使う?

単一エージェントから始めましょう。3つの閾値のいずれかに当たったときだけ2つ目のエージェントを追加:ツールリストが8〜20関数を超える(OpenAIのfunction callingベンチマークによると、この数を超えるとツール選択精度が劣化)、タスクに明確に分離可能で異なる専門性が必要なサブタスクがある(調査 vs 執筆 vs レビュー)、独立した安全検証が必要(プライマリエージェントの出力をチェックするレビューアーエージェント)。

時期尚早のマルチエージェントアーキテクチャは、エージェント開発で最も一般的な過剰エンジニアリングのミス——単純ワークフローに比例する利益なしに、遅延、コスト、デバッグ複雑さを追加します。

ステップ1:この記事の50行エージェントループをコピーし、独自のツール定義に差し替え、max_iterationsを10に設定し、非重要内部タスク——失敗がインシデントではなく学習機会となる低リスクの何か——に対してデプロイ。ログを観察。どこで詰まるか見る。コンテキストを忘れたらメモリを追加。ツールリストが扱いにくくなったらマルチエージェントを追加。何が壊れるかを学ぶ唯一の方法は、何かを出荷して観察することです。

上記の50行エージェントループは動作する出発点です。各エージェント役割を最適なモデルに割り当てる準備ができたら——この記事前半のマッピング表がリファレンス——集約エンドポイントは文字列パラメータを編集するだけでエージェントごとにモデルを変更できます。プロバイダー別SDKなし、別々の課金関係なし。まず低リスクの内部タスクに対してループをデプロイし、ログを観察し、そこから反復してください。