---
title: "エージェントループとは？止まる条件とSDK別の反復上限を実測で解説【2026年10月】"
url: "https://www.issoh.co.jp/tech/details/13602/"
published: 2026-07-13
updated: 2026-10-09
categories: ["AIエージェント・MCP"]
publisher: "株式会社一創"
---

# エージェントループとは？止まる条件とSDK別の反復上限を実測で解説【2026年10月】

エージェントループとは、LLMが状況を観測し、次の行動を推論し、ツールを呼んで行動し、その結果をまた観測する、という1周を目標に届くまで繰り返す制御構造です。1回の応答で答えを返す使い方と違い、行動の結果を次の入力に取り込むので、途中で状況が変わっても手を選び直せます。この記事では、1周の中身とReActとの関係、ループを止める信号の読み方、OpenAI Agents SDK・LangGraph・Claude Agent SDKの反復上限の既定値（2026年10月9日時点の最新版のソースで確認し、OpenAI Agents SDKとLangGraphは模擬ループで実行検証）、3つの歯止めを入れた最小コードまでを扱います。

## まとめ：エージェントループの継続判定と停止条件

エージェントループの本体はLLMではなく、LLMを呼び出し、返ってきた行動を実行し、結果を履歴に積んで再びLLMを呼ぶ外側の反復処理です。続けるか止めるかは、APIが返す停止理由（Anthropic Messages APIなら `stop_reason` が `tool_use` か `end_turn` か）で機械的に判定します。

止め方はフレームワークに任せきりにできません。2026年10月時点の最新版で実測すると、OpenAI Agents SDK 0.23.1はモデル呼び出し10回で `MaxTurnsExceeded` を送出する一方、LangGraph 1.2.14の既定上限は10007ステップで、終了条件の無いグラフは止まるまでに約5,000回モデルを呼べてしまいます。Claude Agent SDKの `max_turns` は既定で無指定です。最大反復回数・トークン（費用）上限・完了判定の3つを自分のコードで明示するのが、本番に載せる最低条件です。なお `end_turn` はモデルが応答を終えた合図で、依頼した作業が達成されたかの保証ではありません。

## エージェントループの1周で起きること：観測・推論・行動と状態の受け渡し

### 1周の4段階と、周をまたいで残るメッセージ履歴

1周は次の順で進みます。

1. 観測：ユーザーの依頼、または前の周で実行したツールの結果を入力として受け取る
2. 推論：LLMが目標と使えるツールの定義を見て、次の行動（ツール名と引数）か最終回答を出す
3. 行動：アプリケーション側のコードが指定されたツールを実際に実行する
4. 結果の書き戻し：ツールの戻り値やエラーを履歴に追加し、1に戻る

LLM自体は呼び出しのたびに記憶を持ち越しません。周をまたいで状態を運ぶのはメッセージ履歴です。Anthropic Messages APIのようにアプリケーションが履歴を毎回送り直す方式では、アシスタントの応答（`tool_use` ブロックを含む）をそのまま履歴へ追加し、次のユーザーメッセージで同じIDを指す `tool_result` を返します。`tool_use` ブロックを落として送ると対応が崩れ、次の呼び出しがエラーになります。

履歴は周を重ねるほど長くなり、入力トークンが毎周増えます（OpenAIのResponses APIの `previous_response_id` のように、履歴をサーバー側に持たせて再送を省く方式もあります）。待ち時間も伸びやすくなりますが、プロンプトキャッシュが効けば毎周増えるとは限りません。長いタスクで要約や古いツール結果の削除が必要になるのはこのためで、何を残すかの設計は[エージェントメモリとは？短期記憶と長期記憶の設計・実装判断を実装者向けに解説【2026年版】](/tech/details/16053/)で扱っています。

### ReActループとの関係：推論と行動の交互実行とツール呼び出しの形式

「ReActループ」は、エージェントループを思考（Thought）・行動（Action）・観察（Observation）の3要素で回す具体形です。Yaoらの論文（[arXiv 2210.03629](https://arxiv.org/abs/2210.03629)、ICLR 2023）は、推論と行動を交互に出させる方式で、対話型の意思決定ベンチマークALFWorldとWebShopにおいて模倣学習・強化学習の手法を成功率で絶対値34ポイント・10ポイント上回ったと報告しています（文脈内の例示は1〜2個）。

2026年のAPIでは、行動の表現をモデル提供元の関数呼び出し（tool use）が担うので、Actionをテキストで書かせて正規表現で解析する元の形式を自前で組む必要はほぼありません。推論と行動を交互に回す構造そのものは変わりません。推論過程の取得方法はモデルとAPIの仕様によって異なります。ログにはツール名・引数・結果を残し、必要に応じてAPIが提供する推論要約や判断理由の説明を追加します。ReActの書式・論文の実験結果・他手法との選び分けは[ReActパターンとは？思考と行動を交互に回す仕組みと採用判断を実装目線で解説](/tech/details/16312/)にまとめています。

## エージェントループを止める信号：APIの停止理由とSDKの反復上限

### Messages APIのstop\_reasonによる継続・終了の分岐

ループの継続判定は、応答本文の文言ではなくAPIが返す停止理由で行います。Anthropic Messages APIの `stop_reason` は、Python SDK 1.12.1の型定義で次の7値です。

| stop\_reason                     | 意味           | ループでの扱い        |
| -------------------------------- | ------------ | -------------- |
| tool\_use                        | ツール呼び出しを要求   | ツールを実行して継続     |
| end\_turn                        | 応答を自然に終えた    | 終了（目標達成は別途検証）  |
| pause\_turn                      | サーバーツールの反復上限 | 応答を送り返して継続     |
| max\_tokens                      | 出力上限で切れた     | 打ち切りか上限を上げて再実行 |
| stop\_sequence                   | 停止文字列に到達     | 用途に応じて判定       |
| refusal                          | 応答を拒否        | 終了して原因を記録      |
| model\_context\_window\_exceeded | コンテキスト窓が満杯   | 切れた応答として終了     |

見落としやすいのが `pause_turn` です。公式ドキュメント[Stop reasons and fallback](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons)によると、Web検索などサーバー側で実行されるツールのループには1リクエストあたり既定10回の反復上限があり、そこで止まると `pause_turn` が返ります。自前で実行するツールの待ちでは `pause_turn` にならず必ず `tool_use` になる、とも明記されています。サーバーツールを使うなら、ループの分岐に `pause_turn` を入れないと、検索の途中で処理が終わったように見えます。

### SDK別の反復上限の既定値と、上限超過時に起きること

フレームワークに載せると、ループ本体と上限はSDKが持ちます。既定値は製品ごとに桁が違うので、PyPIの最新版（2026年10月9日時点の[openai-agents 0.23.1](https://pypi.org/project/openai-agents/0.23.1/)・[langgraph 1.2.14](https://pypi.org/project/langgraph/1.2.14/)・[claude-agent-sdk 0.2.165](https://pypi.org/project/claude-agent-sdk/0.2.165/)）のソースを確認し、OpenAI Agents SDKとLangGraphは止まらないループを実際に回して挙動を測りました。

| SDK（版）                   | 上限の設定            | 既定値       | 超過時                         |
| ------------------------ | ---------------- | --------- | --------------------------- |
| OpenAI Agents SDK 0.23.1 | max\_turns       | 10        | MaxTurnsExceeded            |
| LangGraph 1.2.14         | recursion\_limit | 10007     | GraphRecursionError         |
| Claude Agent SDK 0.2.165 | max\_turns       | None（無指定） | error\_max\_turns の結果       |
| Claude Agent SDK 0.2.165 | max\_budget\_usd | None（無指定） | error\_max\_budget\_usd の結果 |

OpenAI Agents SDKでは1ターンを「ツール呼び出しを含む1回のモデル呼び出し」と定義しています。毎回ツールを要求し続ける模擬モデルで実行すると、既定のままでモデル10回・ツール10回の実行後に「Max turns (10) exceeded」で止まりました。`max_turns=None` で上限を外せるほか、`error_handlers` の `max_turns` キーで例外の代わりに独自の結果を返すこともできます。

Claude Agent SDKは上限を書かなければ回数でも金額でも止まりません。結果メッセージの `terminal_reason` に終了理由（`completed`・`max_turns` など）が入るので、ログには必ずこの値を残します。

### LangGraph 1.0.6で既定の反復上限が25から10000へ上がった影響

LangGraphの既定の `recursion_limit` は長く25でした。PyPIの版ごとのソースを確認すると、1.0.5（2025年12月12日公開）までは25、1.0.6（2026年1月12日公開）で10000、1.1.4（2026年3月31日公開）以降は10007です。[1.0.6のリリースノート](https://github.com/langchain-ai/langgraph/releases/tag/1.0.6)には「fix: change default recursion limit（[#6676](https://github.com/langchain-ai/langgraph/pull/6676)）」の1行で載っていますが、パッチ版の修正扱いのため、上限の桁が400倍になったことに気づきにくい変更です。

agentノードとtoolsノードを終了条件なしで往復させるグラフで測ると、`recursion_limit=25` では25ステップで `GraphRecursionError` になり、既定のままでは10007ステップ目まで走ってから止まりました。手元の検証環境（Python 3.12・Intel Mac・各1回）での所要時間は0.05秒と8.20秒で、ノードは数値を足すだけの処理です。秒数は環境で変わるので、比べるべきは停止までのステップ数です。LLM呼び出しとツール実行が交互に1ステップずつ進む構成なら、止まるまでにモデル呼び出しは約5,000回です。「既定で25ステップに制限される」と書かれた古い解説を前提に、上限を確認せず本番へ出すと、暴走時に止まるまでのステップ数は25の約400倍になります。LangGraphでエージェントを組むときは `recursion_limit` を必ず明示し、環境変数 `LANGGRAPH_DEFAULT_RECURSION_LIMIT` で既定を戻すかも決めておきます。

## Pythonによる最小エージェントループの実装と3つの停止条件

フレームワークを使わない場合の骨格です。反復回数の上限だけでは、応答しないツールを停止できないため、本番では各ツールのタイムアウトと実行全体の制限時間も設けます。Anthropic Python SDKの `client.messages.create` を前提に、最大反復回数・トークン累計上限・`stop_reason` による完了判定を入れています。トークンはキャッシュの書き込み・読み出し分も合算し、応答終了の判定より先に照合します。ただし応答を受け取った後の事後判定なので、上限を超えた周の消費は止められません。金額で縛るなら、入力・出力・キャッシュ書き込み・キャッシュ読み出しを、それぞれ適用されるモデル別単価で換算して累計し、同じ位置で判定します。ツールの例外も握りつぶさず、`is_error` 付きの観測としてモデルに返します。戻り値の「done」はモデルの応答終了を表すだけなので、タスクの成功は呼び出し側で成果物を検証して判定します。

```
import json

MAX_STEPS = 8          # 歯止め1: モデル呼び出しの最大回数
MAX_TOKENS_TOTAL = 50_000  # 歯止め2: 入出力トークンの累計上限（キャッシュ分を含む）


def run_agent(client, model, tools, tool_impls, task):
    messages = [{"role": "user", "content": task}]
    used = 0
    for step in range(1, MAX_STEPS + 1):
        resp = client.messages.create(
            model=model, max_tokens=1024, tools=tools, messages=messages)
        u = resp.usage
        used += (u.input_tokens + u.output_tokens
                 + (u.cache_creation_input_tokens or 0)
                 + (u.cache_read_input_tokens or 0))
        messages.append({"role": "assistant", "content": resp.content})

        if used >= MAX_TOKENS_TOTAL:             # 事後判定: 超えた周の分は消費済み
            return "budget_exceeded", step, resp.content
        if resp.stop_reason == "end_turn":       # 歯止め3: モデル自身の完了宣言
            return "done", step, resp.content
        if resp.stop_reason != "tool_use":       # max_tokens・refusal 等は打ち切る
            return resp.stop_reason, step, resp.content

        results = []
        for block in resp.content:               # 行動: 要求されたツールを実行
            if block.type != "tool_use":
                continue
            try:
                out = tool_impls[block.name](**block.input)
                results.append({"type": "tool_result", "tool_use_id": block.id,
                                "content": json.dumps(out, ensure_ascii=False)})
            except Exception as e:               # 失敗も観測として返す
                results.append({"type": "tool_result", "tool_use_id": block.id,
                                "content": str(e), "is_error": True})
        messages.append({"role": "user", "content": results})  # 観測を次の周へ
    return "max_steps", MAX_STEPS, None
```

APIを呼ばない模擬クライアントで7通りの経路を流すと、2周目で完了する場合は `("done", 2)`、ツールを要求し続ける場合は `("max_steps", 8)`、1周3万トークンの応答が続く場合は `("budget_exceeded", 2)`、6万トークンを使って完了した場合やキャッシュ読み出しが6万トークンあった場合は `("budget_exceeded", 1)`、拒否された場合は `("refusal", 1)` を返し、ツールが例外を出しても次の周へ進んで `("done", 2)` で終わりました。この関数は `pause_turn` も打ち切りとして扱うので、サーバーツールを併用するなら `pause_turn` の分岐を足します。

ツール定義のJSON Schema、承認フロー、トレースまで含めて組み上げる手順は[AIエージェントの作り方：ツール定義からループ・承認・トレースまでコードで組む](/tech/details/17571/)で通しで解説しています。

## エージェントループの観測と、ループを外から見る観測ツールの違い

エージェントループでいう「観測」は、ツールの戻り値をモデルの次の入力に入れる段階のことで、ループの内側の話です。一方、「AIエージェントの観測ツール」と言うときは、ループが何周回り、どのツールをどんな引数で呼び、何トークン使ったかを外から記録するオブザーバビリティ基盤（LangSmith、Langfuse、OpenTelemetryのGenAIセマンティック規約に沿った計装など）を指します。

運用で後者が欠かせないのは、ループの失敗が最終回答だけを見ても分からないからです。同じツールを同じ引数で3回呼んでいる、ツールのエラーを読まずに推論を続けている、といった症状は、1周ごとのスパンを並べて初めて見えます。OpenAI Agents SDKはトレースが既定で有効（`tracing_disabled` の既定はFalse、環境変数 `OPENAI_AGENTS_DISABLE_TRACING` で無効化）なので、社外へ送ってよいデータかを先に確認します。スパンの切り方とgen\_ai属性の設計は[エージェントトレーシングとは？スパン木の設計・gen\_ai属性・記録範囲を実装目線で解説【2026年版】](/tech/details/16332/)、OSSで自前運用する選択肢は[Langfuseとは？読み方・機能・使い方とLangSmithとの違いを解説【2026年最新】](/tech/details/6031/)で比べています。

## 単一のエージェントループで足りる場面と、ループにしない・複数に広げる判断

ループが効くのは、次に何をすべきかが前の結果を見るまで決まらないタスクです。障害調査でログを見てから次に引くメトリクスを決める、テストの失敗内容を見て修正箇所を変える、といった仕事がこれに当たります。

逆に、手順が最初から固定できる処理をループにすると、毎周の再推論が遅さと費用と非決定性を足すだけです。請求書の項目抽出、定型レポートの生成、分類してから要約する2段処理などは、段をコードで固定する[プロンプトチェイニングとは？段の切り方とゲート設計・採用判断を実装目線で解説【2026年版】](/tech/details/16470/)の方が、失敗した段を特定しやすく、テストも書けます。判断の目安は、次に呼ぶツールと分岐条件を事前にコードで固定できるかどうかです。固定できるなら、毎周LLMに行動を選ばせず、必要な反復もコードで制御します。

複数のエージェントに分けるのは、1本のループに渡すツールが増えて選択を誤り始めたときや、調査と実装のように権限を分けたい役割があるときです。分けるとエージェント間の受け渡しが増え、トークン消費も失敗箇所も増えます。まず単一ループでツールを絞り、上で挙げた3つの歯止めとトレースを入れてから判断するのが順序です。比較の軸は[シングルエージェントとマルチエージェントの違い｜使い分けの判断基準とコスト・失敗モード【2026年版】](/tech/details/4261/)、構成パターンは[マルチエージェントとは？仕組み・構成パターンと採用判断を実装者視点で解説【2026年版】](/tech/details/13604/)で扱っています。

## エージェントループの仕組みと止め方でよくある質問

### エージェントループとは何ですか？

LLMが観測・推論・行動を繰り返し、行動の結果を次の入力に戻しながら目標に近づく制御構造です。LLMを呼び、要求されたツールを実行し、結果を履歴に積んで再び呼ぶ外側の反復処理を指します。

### ReActループとエージェントループはどう違いますか？

エージェントループは反復構造全般の呼び名で、ReActはその一形式です。ReActは思考（Thought）・行動（Action）・観察（Observation）をテキストで交互に出させる方式で、関数呼び出しが標準になった現在は、行動部分をAPIのtool useが担う形で実装するのが一般的です。

### エージェントループが止まらないのを防ぐには？

最大反復回数、トークンまたは金額の上限、`stop_reason` による完了判定の3つを自分のコードで明示します。LangGraph 1.0.6以降は既定の `recursion_limit` が10000以上、Claude Agent SDKの `max_turns` は既定で無指定なので、SDKの既定値に頼ると、用途に合った回数や費用で止まるとは限りません。

### エージェントループの観測ツールには何を使いますか？

ループの各周を記録するには、LangSmith・Langfuseなどのトレース基盤や、OpenTelemetryのGenAIセマンティック規約に沿った計装を使います。ツール名・引数・戻り値・トークン数を1周ごとのスパンとして残すと、同じ呼び出しの繰り返しやエラーの読み飛ばしを特定できます。

### エージェントループとMCPはどう関係しますか？

MCPはループの行動段階で呼ぶツールを、外部サーバーから共通の形式で提供する仕組みです。ループの制御構造そのものは変わらず、使えるツールの調達方法が変わります。接続と権限の設計は[AIエージェントにMCPで外部ツールを接続する実装手順とは？tool定義・権限・認可の設計を解説【2026年版】](/tech/details/15365/)で解説しています。

## 関連記事

- [ReActパターンとは？思考と行動を交互に回す仕組みと採用判断を実装目線で解説](/tech/details/16312/)
- [AIエージェントの作り方：ツール定義からループ・承認・トレースまでコードで組む](/tech/details/17571/)
- [エージェントトレーシングとは？スパン木の設計・gen\_ai属性・記録範囲を実装目線で解説【2026年版】](/tech/details/16332/)
- [AIハーネスとは？LLMエージェントの制御基盤を構成する6部品とSDK別の実装](/tech/details/11616/)
- [シングルエージェントとマルチエージェントの違い｜使い分けの判断基準とコスト・失敗モード【2026年版】](/tech/details/4261/)

---

出典: [エージェントループとは？止まる条件とSDK別の反復上限を実測で解説【2026年10月】](<https://www.issoh.co.jp/tech/details/13602/>)（株式会社一創）
