AIエージェント入門

Claude Agent SDKバッチ処理実装ガイド — 並列タスクを動かす

Claude Agent SDKバッチ処理実装ガイド — 並列タスクを動かす

この記事の結論

Claude Agent SDKを使ったバッチ処理の実装パターンを解説。複数タスク並列実行、ファイル一括処理、データパイプラインのコード例をPython/TypeScriptで紹介します。

「Claude Codeに頼んでいた作業を、Pythonスクリプトから自動で回せないか?」——そう思ったことがあるなら、Claude Agent SDKのバッチ処理が答えになる。

Claude Agent SDKは2026年初頭にAnthropicが公開したライブラリで、Claude Codeを動かしている内部のエージェントループをPython/TypeScript APIとして提供する。ファイルの読み書き、コマンド実行、Web検索——Claude Codeが使えるツールをそのままプログラムから呼び出せる。

この記事では特に「バッチ処理」に焦点を当てる。複数のファイルを並列で処理したい、定期的なデータパイプラインを組みたい、大量のテキストを自律的に分析させたい——そういったユースケースで、Claude Agent SDKがどう使えるかをコード例つきで示す。


まず5分で動かすセットアップ

Claude Agent SDKのインストールは1コマンドだ。


# Python版
pip install claude-agent-sdk

# TypeScript版
npm install @anthropic-ai/claude-agent-sdk

# APIキーを環境変数に設定
export ANTHROPIC_API_KEY=your-api-key

最小限の動作確認コードを見てみよう。


# hello_agent.py — 最小構成の動作確認
# 動作環境: Python 3.11+, claude-agent-sdk>=0.1
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions

async def main():
    async for message in query(
        prompt="カレントディレクトリのファイル一覧を表示して",
        options=ClaudeAgentOptions(allowed_tools=["Bash", "Glob"]),
    ):
        if hasattr(message, "result"):
            print(message.result)

asyncio.run(main())

ポイント:

  • query()はasync generatorで、メッセージをストリームとして返す
  • allowed_toolsでエージェントが使えるツールを制限できる(セキュリティ上重要)
  • message.resultが最終的な実行結果

ここまでが基本。次からバッチ処理の実装に入る。

Claude Agent SDKの全体像

バッチ処理の実装を始める前に、SDKの主要な概念を整理しておく。

利用可能な組み込みツール

ツール名 できること 主なユースケース
Read ファイルを読む コードレビュー、ドキュメント分析
Write ファイルを作る レポート生成、コード生成
Edit ファイルを部分編集 バグ修正、リファクタリング
Bash コマンド実行 テスト実行、ビルド、データ変換
Glob ファイルパターン検索 対象ファイルの特定
Grep ファイル内容を正規表現検索 パターン抽出、コード分析
WebSearch Webを検索 情報収集、事実確認
WebFetch URLのコンテンツを取得 ページ解析、スクレイピング
Agent サブエージェントを起動 並列処理、専門エージェントへの委任

(参照: Claude Agent SDK Overview — Anthropic Docs / 最終確認日: 2026-04-14)

AIエージェントの設計パターンの基礎はAIエージェント構築完全ガイドでまとめている。

Client SDKとの違い

Client SDK(従来の`anthropic`ライブラリ)と比較すると、役割の違いが明確だ。


# Client SDK: ツールループを自分で実装する
from anthropic import Anthropic
client = Anthropic()

response = client.messages.create(
    model="claude-opus-4-6",
    messages=[{"role": "user", "content": "auth.pyのバグを直して"}],
    tools=[...],  # ツール定義を手書き
)
# stop_reason == "tool_use" なら自分でツールを実行して再送信
while response.stop_reason == "tool_use":
    result = execute_tool(response.tool_use)  # 自前実装
    response = client.messages.create(tool_result=result, ...)

# Agent SDK: ツールループはSDKが担う
from claude_agent_sdk import query, ClaudeAgentOptions
async for msg in query("auth.pyのバグを直して", ClaudeAgentOptions(...)):
    print(msg)  # Claudeがファイルを読み、バグを見つけ、修正する

バッチ処理パターン1: ファイル一括処理

最も典型的なバッチ処理が「複数ファイルへの一括適用」だ。例として、Pythonコードのリポジトリ全体にコメントを追加するケースを実装する。


# batch_file_processor.py — ファイル一括処理
# 動作環境: Python 3.11+, claude-agent-sdk>=0.1
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
# 警告: allow_tools=["Edit"] を指定するとファイルが書き換えられます。
#       必ず git でコミットした状態から実行してください。

import asyncio
import glob
from claude_agent_sdk import query, ClaudeAgentOptions

async def process_file(file_path: str) -> tuple[str, str]:
    """1つのファイルを処理してresultを返す"""
    result_text = ""
    async for message in query(
        prompt=f"""
        以下のファイルを読み、各関数・クラスにdocstringを追加してください。
        - 既存のdocstringは変更しないこと
        - Google Style docstringを使用すること
        - ファイルパス: {file_path}
        """,
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Edit"],
            permission_mode="acceptEdits",  # 確認なしで編集を許可
        ),
    ):
        if hasattr(message, "result"):
            result_text = message.result
    return file_path, result_text

async def batch_process(pattern: str = "src/**/*.py", max_concurrent: int = 3):
    """複数ファイルを並列バッチ処理"""
    files = glob.glob(pattern, recursive=True)
    print(f"{len(files)}件のファイルを処理します")

    # semaphoreで同時実行数を制限(API rate limit対策)
    semaphore = asyncio.Semaphore(max_concurrent)

    async def limited_process(fp):
        async with semaphore:
            return await process_file(fp)

    # 並列実行
    tasks = [limited_process(f) for f in files]
    results = await asyncio.gather(*tasks, return_exceptions=True)

    # 結果レポート
    success, failed = [], []
    for r in results:
        if isinstance(r, Exception):
            failed.append(str(r))
        else:
            fp, msg = r
            success.append(fp)
            print(f"  OK: {fp}")

    print(f"n完了: 成功 {len(success)}件 / 失敗 {len(failed)}件")
    if failed:
        for err in failed:
            print(f"  ERR: {err}")

if __name__ == "__main__":
    asyncio.run(batch_process(pattern="src/**/*.py", max_concurrent=3))

ポイント:

  • asyncio.Semaphore(max_concurrent)で同時リクエスト数を制限。Claude APIにはレートリミットがあるため必須
  • return_exceptions=Trueを使うと1つのエラーで全体が止まらない
  • permission_mode="acceptEdits"は確認なしで編集を許可するモード。本番では慎重に使うこと

バッチ処理パターン2: データパイプライン

次は「入力データを処理して構造化出力を生成する」パイプラインだ。例として、複数のWebページからの情報抽出を実装する。


# data_pipeline.py — URLリストからデータを並列抽出
# 動作環境: Python 3.11+, claude-agent-sdk>=0.1
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

import asyncio
import json
from pathlib import Path
from claude_agent_sdk import query, ClaudeAgentOptions

URLS = [
    "https://example.com/product-a",
    "https://example.com/product-b",
    "https://example.com/product-c",
]

async def extract_product_info(url: str) -> dict:
    """URLからプロダクト情報を抽出"""
    collected_result = ""
    async for message in query(
        prompt=f"""
        以下のURLのページを取得し、以下の情報をJSON形式で返してください:
        - name: 製品名
        - price: 価格(数値のみ、円なし)
        - features: 特徴のリスト(最大5つ)
        - availability: 在庫状況("available" or "unavailable")

        URL: {url}

        必ずJSON形式のみで返すこと。説明文は不要。
        """,
        options=ClaudeAgentOptions(
            allowed_tools=["WebFetch"],
        ),
    ):
        if hasattr(message, "result"):
            collected_result = message.result

    # JSON部分を抽出してパース
    try:
        # ```json ... ``` ブロックがあれば取り出す
        if "```json" in collected_result:
            json_str = collected_result.split("```json")[1].split("```")[0].strip()
        elif "```" in collected_result:
            json_str = collected_result.split("```")[1].split("```")[0].strip()
        else:
            json_str = collected_result.strip()
        return {"url": url, "data": json.loads(json_str), "error": None}
    except (json.JSONDecodeError, IndexError) as e:
        return {"url": url, "data": None, "error": str(e)}

async def run_pipeline(urls: list[str], output_path: str = "output.json"):
    """データパイプラインの実行"""
    semaphore = asyncio.Semaphore(5)  # 同時5リクエストまで

    async def limited_extract(url):
        async with semaphore:
            return await extract_product_info(url)

    print(f"{len(urls)}件のURLを処理中...")
    results = await asyncio.gather(*[limited_extract(u) for u in urls])

    # 結果を保存
    Path(output_path).write_text(
        json.dumps(results, ensure_ascii=False, indent=2),
        encoding="utf-8"
    )
    print(f"結果を {output_path} に保存しました")

    # サマリー表示
    success = [r for r in results if r["error"] is None]
    print(f"成功: {len(success)}/{len(results)}件")

if __name__ == "__main__":
    asyncio.run(run_pipeline(URLS, output_path="products.json"))

バッチ処理パターン3: サブエージェントで専門分業

Claude Agent SDKの真骨頂は「エージェントがサブエージェントを起動する」再帰的な構成だ。大きなタスクを分割して専門エージェントに委任できる。


# multi_agent_review.py — コードレビューを専門エージェントで分業
# 動作環境: Python 3.11+, claude-agent-sdk>=0.1
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition

async def multi_agent_code_review(target_dir: str):
    """セキュリティ・パフォーマンス・スタイルの3専門エージェントでコードレビュー"""
    result_text = ""
    async for message in query(
        prompt=f"""
        {target_dir} のPythonコードを3つの観点でレビューしてください:
        1. security-reviewer エージェントでセキュリティ問題を検出
        2. performance-reviewer エージェントでパフォーマンス問題を検出
        3. style-reviewer エージェントでコードスタイル問題を検出

        各エージェントの結果を統合して最終レポートを作成してください。
        """,
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Glob", "Grep", "Agent"],
            agents={
                "security-reviewer": AgentDefinition(
                    description="セキュリティ専門のコードレビュアー。SQLインジェクション、XSS、秘密情報の漏洩等を検出。",
                    prompt="コードのセキュリティ脆弱性を分析し、問題点と修正案をMarkdownで報告してください。",
                    tools=["Read", "Glob", "Grep"],
                ),
                "performance-reviewer": AgentDefinition(
                    description="パフォーマンス専門のコードレビュアー。N+1クエリ、メモリリーク、非効率なアルゴリズムを検出。",
                    prompt="コードのパフォーマンス問題を分析し、改善提案をMarkdownで報告してください。",
                    tools=["Read", "Glob", "Grep"],
                ),
                "style-reviewer": AgentDefinition(
                    description="コードスタイル専門のレビュアー。PEP8準拠、命名規則、ドキュメント不足を検出。",
                    prompt="コードのスタイル問題を分析し、具体的な改善案をMarkdownで報告してください。",
                    tools=["Read", "Glob", "Grep"],
                ),
            },
        ),
    ):
        if hasattr(message, "result"):
            result_text = message.result

    return result_text

if __name__ == "__main__":
    result = asyncio.run(multi_agent_code_review("./src"))
    print(result)
    # レポートをファイルに保存する場合
    # Path("review_report.md").write_text(result, encoding="utf-8")

ポイント:

  • AgentDefinitionでサブエージェントの専門性を定義する
  • 親エージェントが`Agent`ツールを使って子エージェントを呼び出す設計
  • 各サブエージェントには独立したtoolsリストを設定でき、権限を最小化できる

セッション管理: 状態を引き継いでバッチを継続

長時間のバッチ処理では、中断・再開が重要だ。Claude Agent SDKはセッションIDで会話コンテキストを保持できる。


# session_batch.py — セッションIDを使った継続バッチ
# 動作環境: Python 3.11+, claude-agent-sdk>=0.1
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage, ResultMessage

async def analyze_codebase_in_steps():
    """2段階で大規模コードベースを分析"""

    # ステップ1: コードベースの概要を把握
    session_id = None
    async for message in query(
        prompt="src/ ディレクトリの構造を把握して、主要コンポーネントを説明してください",
        options=ClaudeAgentOptions(allowed_tools=["Read", "Glob", "Grep"]),
    ):
        # セッションIDを取得(初期化メッセージから)
        if isinstance(message, SystemMessage) and message.subtype == "init":
            session_id = message.data["session_id"]
            print(f"セッションID取得: {session_id}")
        if isinstance(message, ResultMessage):
            print("ステップ1完了:", message.result[:200], "...")

    # ステップ2: 前のコンテキストを保持したまま詳細分析
    if session_id:
        async for message in query(
            prompt="把握した構造を踏まえて、認証フローのセキュリティリスクを分析してください",
            options=ClaudeAgentOptions(
                resume=session_id,  # 前のセッションを再開
                allowed_tools=["Read", "Grep"],
            ),
        ):
            if isinstance(message, ResultMessage):
                print("ステップ2完了:", message.result)

asyncio.run(analyze_codebase_in_steps())

【要注意】バッチ処理でよくある失敗パターン

失敗1: レートリミットを無視した並列実行

❌ よくある間違い: Semaphoreなしで大量のタスクを一斉にasyncio.gather()

⭕ 正しいアプローチ: asyncio.Semaphore(3〜5)で同時実行数を制御

なぜ重要か: AnthropicのAPIにはTPM(Tokens Per Minute)とRPM(Requests Per Minute)の制限がある。Semaphoreなしで100タスクを同時に走らせると、RateLimitErrorが頻発してバッチが途中で止まる。

失敗2: max_turnsを設定しない

❌ 無限ループのリスク: 複雑なタスクでエージェントが終了条件を見つけられず延々ループする

⭕ 必ず設定: ClaudeAgentOptions(max_turns=30)で上限を設ける


# 安全なオプション設定例
options = ClaudeAgentOptions(
    allowed_tools=["Read", "Edit", "Bash"],
    max_turns=30,                    # ループ上限
    permission_mode="default",       # 危険な操作は確認を求める
)

失敗3: エラーハンドリングを省略する

❌ `asyncio.gather()`でエラーを拾わない → 1つの失敗で全体のリザルトが壊れる

return_exceptions=True + 個別のtry/exceptで安全に処理する


# エラーハンドリングの正しいパターン
async def safe_process(item):
    try:
        return await process_item(item)
    except Exception as e:
        return {"item": item, "error": str(e), "status": "failed"}

results = await asyncio.gather(*[safe_process(i) for i in items], return_exceptions=True)
# return_exceptions=True でException自体もresultsに含まれる
errors = [r for r in results if isinstance(r, Exception)]
successes = [r for r in results if not isinstance(r, Exception)]

失敗4: allowed_toolsを広く設定しすぎる

❌ ファイル読み取りだけのタスクにallowed_tools=["Read", "Write", "Edit", "Bash"]

⭕ 必要最小限のツールだけ許可する(最小権限の原則)

なぜ重要か: Claudeはプロンプトインジェクション攻撃に対してある程度の防御を持つが、不必要なツールを与えると意図しないファイル操作が起きる可能性がある。WebFetchで取得したコンテンツに悪意あるプロンプトが含まれている場合のリスクを最小化するためにも、ツールは絞ること。

コスト管理: APIの使いすぎを防ぐ

バッチ処理はトークン消費が大きい。コスト管理の基本設定を示す。


# コスト制御のオプション
options = ClaudeAgentOptions(
    allowed_tools=["Read", "Grep"],   # 必要最小限
    max_turns=20,                      # ターン数制限
    # モデルを明示的に指定(小さいモデルでコスト削減)
    # 2026年4月現在、Agent SDKはデフォルトでclaudeの最新版を使用
    # 軽いタスクはclaude-haiku-4-5を検討
)

# 実行前にトークン使用量を概算
# 1ファイル処理: 約1,000〜5,000トークン(ファイルサイズ依存)
# 100ファイルバッチ: 100,000〜500,000トークン
# claude-opus-4-6: $15/1Mトークン → 100ファイルで$1.5〜7.5

参考・出典


まとめ:今日から始める3つのアクション

  1. 今日やること: pip install claude-agent-sdk を実行して、最小構成のhello_agent.pyを動かしてみる。5分でエージェントが動く感触をつかむ
  2. 今週中: 自分のプロジェクトで「繰り返しClaude Codeに頼んでいる作業」を1つ選んでバッチ化を試みる。ファイルが10本以下なら並列処理の恩恵が出始める
  3. 今月中: サブエージェントパターンを1つ実装する。コードレビューを専門エージェントに分業させる構成は、CI/CDパイプラインへの組み込みにも発展しやすい

あわせて読みたい:

著者: 佐藤傑(さとう・すぐる)
株式会社Uravation代表取締役。X(@SuguruKun_ai)フォロワー10万人超。100社以上の企業向けAI研修・導入支援。著書累計3万部突破。SoftBank IT連載7回執筆(NewsPicks最大1,125ピックス)。
ご質問・ご相談は お問い合わせフォーム からお気軽にどうぞ。

Need help moving from reading to rollout?

この記事を読んで導入イメージが固まってきた方へ

Uravationでは、AIエージェントの要件整理、PoC設計、社内導入、研修まで一気通貫で支援しています。

この記事をシェア

X Facebook LINE

※ 本記事の情報は2026年4月時点のものです。サービスの料金・仕様は変更される可能性があります。最新情報は各サービスの公式サイトをご確認ください。

関連記事