CLAUDE LABEN
WWDC — WWDC 2026でSiriはGoogle Geminiベースと確定。ChatGPT等への外部ハンドオフは廃止され、サードパーティAI選択はEU(DMA)で当面非対応にBILLING — 6/15の課金変更まで残り6日。Agent SDK・headless Claude Code・GitHub Actions・他社エージェントがAPIレート準拠の月次クレジットへ移行OUTAGE — claude.ai・Claude Code・Coworkで障害が報告(6月)。スケジュール実行はfallbackModelとリトライ前提の設計が安全ですDYNAMIC-WORKFLOWS — Max・TeamプランとAPIでdynamic workflowsがデフォルトON。コードベース横断のバグ探索や独立検証に活用ULTRACODE — Claude Codeの新設定ultracodeがeffortメニューに追加。xhigh固定でワークフロー判断はClaudeに委ねますOPUS4.8 — Claude Opus 4.8が主要プランのデフォルトとして定着。コーディング・エージェント・推論を強化WWDC — WWDC 2026でSiriはGoogle Geminiベースと確定。ChatGPT等への外部ハンドオフは廃止され、サードパーティAI選択はEU(DMA)で当面非対応にBILLING — 6/15の課金変更まで残り6日。Agent SDK・headless Claude Code・GitHub Actions・他社エージェントがAPIレート準拠の月次クレジットへ移行OUTAGE — claude.ai・Claude Code・Coworkで障害が報告(6月)。スケジュール実行はfallbackModelとリトライ前提の設計が安全ですDYNAMIC-WORKFLOWS — Max・TeamプランとAPIでdynamic workflowsがデフォルトON。コードベース横断のバグ探索や独立検証に活用ULTRACODE — Claude Codeの新設定ultracodeがeffortメニューに追加。xhigh固定でワークフロー判断はClaudeに委ねますOPUS4.8 — Claude Opus 4.8が主要プランのデフォルトとして定着。コーディング・エージェント・推論を強化
記事一覧/API & SDK
API & SDK/2026-03-26中級

Claude SDK Tool Runner でエージェントループを自動化する

Claude SDK の Tool Runner と Tool Helpers を使って、ツール呼び出しの自動ループ(エージェントループ)を構築する方法をコード例付きで解説します。

tool-runnertool-use25sdk7agentic-looppython32typescript18

Claude SDK Tool Runner とは

Claude API でツールを使ったアプリケーションを構築する際、従来は「Claude にリクエスト → ツール呼び出しを検出 → ツールを実行 → 結果を Claude に返す」というループを自分で実装する必要がありましました。この繰り返し処理は定型的ですが、エラー処理やコンテキスト管理を含めると複雑になりがちです。

Tool Runner は、このツール呼び出しループを SDK 側で自動管理してくれるベータ機能です。Python・TypeScript・Ruby の各 SDK で利用でき、開発者はツールの定義と実装に集中できます。

Tool Runner が提供する主な機能は以下の通りです。

  • 自動ループ処理: Claude がツールを呼び出すたびに、結果を自動的にフィードバックして次のレスポンスを取得
  • 型安全な入力バリデーション: Tool Helpers と組み合わせて、ツール入力のスキーマ検証を自動化
  • 自動コンパクション: トークン使用量が閾値を超えると、会話の要約を自動生成してコンテキストを管理
  • ストリーミング対応: リアルタイムでレスポンスを受け取りながらループを実行

従来のツール呼び出しループとの違い

まず、Tool Runner を使わない従来のパターンを確認しましょう。

import anthropic
 
client = anthropic.Anthropic()
 
# ツール定義
tools = [
    {
        "name": "get_weather",
        "description": "指定した都市の天気を取得",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "都市名"}
            },
            "required": ["city"]
        }
    }
]
 
def get_weather(city: str) -> str:
    # 実際の天気API呼び出し(ここではモック)
    return f"{city}の天気: 晴れ、気温22°C"
 
# 手動ループ
messages = [{"role": "user", "content": "東京と大阪の天気を教えてください"}]
 
while True:
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        tools=tools,
        messages=messages,
    )
 
    # stop_reason が "end_turn" ならループ終了
    if response.stop_reason == "end_turn":
        break
 
    # ツール呼び出しを処理
    for block in response.content:
        if block.type == "tool_use":
            result = get_weather(block.input["city"])
            messages.append({"role": "assistant", "content": response.content})
            messages.append({
                "role": "user",
                "content": [{
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": result,
                }]
            })
# 最終レスポンスからテキストを抽出
final_text = next(b.text for b in response.content if hasattr(b, "text"))
print(final_text)

このコードでも動作しますが、ループ管理・メッセージの追加・エラー処理がすべて開発者の責任です。Tool Runner を使うとこれが大幅に簡潔になります。

Tool Helpers でツールを定義する

Tool Runner を使う前に、Tool Helpers でツールを型安全に定義する方法を見ていきます。

Python(Pydantic ベース)

import anthropic
from pydantic import BaseModel, Field
 
client = anthropic.Anthropic()
 
# Pydantic モデルでツール入力を定義
class GetWeatherInput(BaseModel):
    city: str = Field(description="天気を取得する都市名")
    unit: str = Field(default="celsius", description="温度の単位(celsius/fahrenheit)")
 
# @tool デコレータでツール関数を定義
@anthropic.tool(name="get_weather", description="指定した都市の現在の天気を取得します")
def get_weather(input: GetWeatherInput) -> str:
    """天気情報を返すツール"""
    return f"{input.city}の天気: 晴れ、気温22°C({input.unit})"
 
# ツール定義から自動的にJSON Schemaが生成される
print(get_weather.to_params())
# 出力例:
# {
#   "name": "get_weather",
#   "description": "指定した都市の現在の天気を取得します",
#   "input_schema": {
#     "type": "object",
#     "properties": {
#       "city": {"type": "string", "description": "天気を取得する都市名"},
#       "unit": {"type": "string", "default": "celsius", ...}
#     },
#     "required": ["city"]
#   }
# }

TypeScript(Zod ベース)

import Anthropic from "@anthropic-ai/sdk";
import { z } from "zod";
 
const client = new Anthropic();
 
// Zod スキーマでツール入力を定義
const GetWeatherInput = z.object({
  city: z.string().describe("天気を取得する都市名"),
  unit: z.enum(["celsius", "fahrenheit"]).default("celsius").describe("温度の単位"),
});
 
// betaZodTool でツールを作成
const weatherTool = client.betaZodTool({
  name: "get_weather",
  description: "指定した都市の現在の天気を取得します",
  schema: GetWeatherInput,
  execute: async (input) => {
    // input は自動的に型推論される
    return `${input.city}の天気: 晴れ、気温22°C(${input.unit})`;
  },
});

Tool Helpers を使うことで、入力値のバリデーションが自動で行われ、不正な型の入力が渡されるとエラーが発生します。

Tool Runner でエージェントループを構築する

Python での実装

import anthropic
from pydantic import BaseModel, Field
 
client = anthropic.Anthropic()
 
class SearchInput(BaseModel):
    query: str = Field(description="検索クエリ")
 
class CalculateInput(BaseModel):
    expression: str = Field(description="計算式")
 
@anthropic.tool(name="web_search", description="Webを検索して情報を取得します")
def web_search(input: SearchInput) -> str:
    return f"検索結果: '{input.query}' に関する最新情報..."
 
@anthropic.tool(name="calculate", description="数式を計算します")
def calculate(input: CalculateInput) -> str:
    try:
        result = eval(input.expression)  # 本番ではsafe_evalを使用
        return f"計算結果: {input.expression} = {result}"
    except Exception as e:
        return f"計算エラー: {e}"
 
# Tool Runner でエージェントループを実行
result = client.messages.tool_runner(
    model="claude-sonnet-4-6",
    max_tokens=4096,
    tools=[web_search, calculate],
    messages=[{
        "role": "user",
        "content": "日本の人口は約何人ですか?また、世界人口の何%にあたるか計算してください。"
    }],
)
 
# result はイテラブル — 各メッセージを順に処理
for message in result:
    print(f"[{message.role}]")
    for block in message.content:
        if hasattr(block, "text"):
            print(block.text)
        elif block.type == "tool_use":
            print(f"  → ツール呼び出し: {block.name}({block.input})")

TypeScript での実装

import Anthropic from "@anthropic-ai/sdk";
import { z } from "zod";
 
const client = new Anthropic();
 
const searchTool = client.betaZodTool({
  name: "web_search",
  description: "Webを検索して情報を取得します",
  schema: z.object({ query: z.string().describe("検索クエリ") }),
  execute: async (input) => {
    return `検索結果: '${input.query}' に関する最新情報...`;
  },
});
 
const calcTool = client.betaZodTool({
  name: "calculate",
  description: "数式を計算します",
  schema: z.object({ expression: z.string().describe("計算式") }),
  execute: async (input) => {
    try {
      // 本番ではmathjs等の安全なパーサーを使用
      const result = Function(`"use strict"; return (${input.expression})`)();
      return `計算結果: ${input.expression} = ${result}`;
    } catch (e) {
      return `計算エラー: ${e}`;
    }
  },
});
 
// Tool Runner でエージェントループを実行
const runner = client.messages.toolRunner({
  model: "claude-sonnet-4-6",
  max_tokens: 4096,
  tools: [searchTool, calcTool],
  messages: [{
    role: "user",
    content: "日本の人口は約何人ですか?また、世界人口の何%にあたるか計算してください。",
  }],
});
 
// ストリーミングで各メッセージを処理
for await (const message of runner) {
  console.log(`[${message.role}]`);
  for (const block of message.content) {
    if ("text" in block) {
      console.log(block.text);
    } else if (block.type === "tool_use") {
      console.log(`  → ツール呼び出し: ${block.name}(${JSON.stringify(block.input)})`);
    }
  }
}

自動コンパクションでコンテキストを管理する

長時間のエージェントセッションでは、ツール呼び出しの結果が蓄積してトークン数が膨大になります。Tool Runner の自動コンパクション機能は、トークン使用量が閾値を超えた際に会話の要約を自動生成し、コンテキストウィンドウ内に収めます。

# Python: 自動コンパクション付き Tool Runner
result = client.messages.tool_runner(
    model="claude-sonnet-4-6",
    max_tokens=4096,
    tools=[web_search, calculate],
    messages=messages,
    # コンパクション設定
    compaction={
        "enabled": True,
        "threshold_tokens": 50000,  # この値を超えたら要約を生成
    },
)
// TypeScript: 自動コンパクション付き Tool Runner
const runner = client.messages.toolRunner({
  model: "claude-sonnet-4-6",
  max_tokens: 4096,
  tools: [searchTool, calcTool],
  messages,
  compaction: {
    enabled: true,
    thresholdTokens: 50000,
  },
});

コンパクションが発生すると、古いメッセージが要約に置き換えられ、重要な情報は保持されたまま会話を続行できます。

strict: true で入力スキーマを厳密に検証する

Structured Outputs の strict: true オプションをツール定義に追加すると、Claude が生成するツール呼び出しの入力が必ず指定したスキーマに一致することが保証されます。

tools = [
    {
        "name": "create_user",
        "description": "新しいユーザーを作成します",
        "strict": True,  # スキーマの厳密な検証を有効化
        "input_schema": {
            "type": "object",
            "properties": {
                "name": {"type": "string"},
                "email": {"type": "string", "format": "email"},
                "age": {"type": "integer", "minimum": 0}
            },
            "required": ["name", "email", "age"],
            "additionalProperties": False  # strict: true 時は必須
        }
    }
]

strict: true を使用すると、型の不一致やフィールドの欠落がなくなるため、ツール実行時のランタイムエラーを大幅に削減できます。

全体を振り返って

Claude SDK の Tool Runner と Tool Helpers を使えば、ツール呼び出しの自動ループ構築が大幅に簡略化されます。従来は手動で管理していたメッセージのやり取り・エラー処理・コンテキスト管理が SDK 側に委譲され、開発者はビジネスロジックに集中できます。

ツール定義の方法については Claude API ツール活用の完全ガイド を、TypeScript SDK の型安全な使い方は TypeScript SDK 型安全プロダクションガイド をご覧ください。API のコスト管理に関しては Claude API トークンカウントとコスト最適化ガイド も参考になります。

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API & SDK2026-04-06
Anthropic SDKのインストール・バージョン不一致エラーを完全解決する方法
Anthropic SDKのインストールエラーやバージョン不一致でAPIが動かないときの原因と解決手順を徹底解説。ImportError・ModuleNotFoundError・依存関係の競合など典型的なエラーパターンを網羅します。
API & SDK2026-05-16
Claude API の Tool Use でスキーマ定義ミスが出たとき:実際に遭遇した3つのパターンと診断手順
Claude API の Tool Use でよく起きるスキーマ定義ミス・invalid_tool_use・Claude がツールを呼ばない問題を、実際のアプリ開発で遭遇したケースをもとに診断手順と修正パターンで解説します。
API & SDK2026-05-08
Claude API のツール呼び出しを Zod で型安全にした — TypeScript 開発者が詰まるポイントと実装パターン
Claude API のツール呼び出しを TypeScript + Zod で型安全に実装する方法。スキーマ自動変換・ランタイムバリデーション・よくある型エラーの解決策を実践コード付きで解説します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →