Claude Agent SDK 入門 2026 — Claude CodeをAPIから呼び出すカスタム自動化ガイド

Claude Agent SDK 入門 2026 — Claude CodeをAPIから呼び出すカスタム自動化ガイド

Claude Agent SDK でClaude Codeをプログラムから呼び出す方法を完全解説。SDK インストール、ストリーミング応答、Tool Use、Hooks連携、本番運用パターンまで。

Claude Codeを「対話しながら使う」のとは別に、「プログラムから呼び出して自動で動かす」ニーズがある。

たとえばこんなケース。

  • PRが来たらClaude Codeにレビューさせてステータスを更新したい
  • 毎朝ログファイルを分析して異常を検知させたい
  • Webhookを受け取ったらコードを自動修正して PR を作らせたい

こういう「インタラクティブじゃない用途」に答えるのが Claude Agent SDK だ。

CLIを手で操作するのではなく、PythonやTypeScriptのコードからClaude Codeのエージェントループをそのまま起動できる。読んでいるファイル、実行しているコマンド、文脈の管理まで全部SDKがやってくれるので、ツール実行ループを自分で書く必要がない。

この記事では、SDKの概念的な位置付けから実際の動かし方、本番投入する際の考え方まで一通り書く。


Claude Agent SDKとは(CLIとの違い)

Claude Agent SDKは、Claude Codeが持つエージェント機能をPythonまたはTypeScriptのライブラリとして提供するものだ。

Anthropicの公式説明を引用すると:

Build production AI agents with Claude Code as a library

「Claude Codeをライブラリとして」というのがポイント。CLIを使うときと同じツール(Read、Edit、Bash、Grep、Glob…)を、同じエージェントループで、コードから呼び出せる。

CLIとSDKの使い分け

用途向いているもの
日常の開発作業CLI
CI/CDパイプラインSDK
カスタムアプリへの組み込みSDK
単発の一回タスクCLI
本番の自動化処理SDK

多くのチームは「開発中はCLI、本番処理はSDK」という使い分けをするケースが多い。CLIで試した処理をそのままSDKに移植できるのが強みで、ワークフローの翻訳コストがほとんどかからない。

Anthropic Client SDKとの違い

混乱しやすいのが「Anthropic Client SDK」との区別だ。

Anthropic Client SDKは、Messages APIを直接叩くためのライブラリ。つまり「APIを呼ぶ → ツール使いたい → 自分でツール実行 → また呼ぶ」というループを自分で実装しなければならない。

Claude Agent SDKはそのループを全部内部でやってくれる。コードはこんなに変わる。

# Anthropic Client SDK: ツールループを自分で実装
response = client.messages.create(...)
while response.stop_reason == "tool_use":
    result = your_tool_executor(response.tool_use)
    response = client.messages.create(tool_result=result, **params)

# Claude Agent SDK: Claudeがツールを自律実行
async for message in query(prompt="auth.pyのバグを直して"):
    print(message)
// Anthropic Client SDK: ツールループを自分で実装
let response = await client.messages.create({ ...params });
while (response.stop_reason === "tool_use") {
  const result = yourToolExecutor(response.tool_use);
  response = await client.messages.create({ tool_result: result, ...params });
}

// Claude Agent SDK: Claudeがツールを自律実行
for await (const message of query({ prompt: "auth.tsのバグを直して" })) {
  console.log(message);
}

処理の意図が明確になるし、書くコード量も圧倒的に少なくなる。


SDKを使う3つの場面

実際にSDKが活きるのはどういうときか。僕が使っていて「これはSDKじゃないと無理だな」と思った場面を3つ挙げる。

1. CI/CDへの組み込み

GitHub ActionsなどのCI環境でClaude Codeを動かす場合、対話型のCLIは使えない。SDKならスクリプトとして実行できるので、PRの内容を自動レビューしたり、テスト失敗の原因を分析して修正案を作ったりできる。

2. アプリケーションへの組み込み

「ユーザーがボタンを押したらAIがファイルを分析して結果を返す」というようなアプリを作るとき、SDKを使えばClaude Codeのエージェント機能をAPIエンドポイントの中で普通に呼び出せる。

3. 定期実行・バッチ処理

毎朝決まった時間にコードをチェックしたり、ログを分析したりする定期タスクに使える。cron + Pythonスクリプトという形でClaude Codeの能力をバックグラウンドで走らせられる。


インストールと初期設定(Python / TypeScript)

必要な環境

  • Python 3.10以上 または Node.js 18以上
  • Anthropic APIキー(Consoleから取得)

Python

pip install claude-agent-sdk

uvを使うなら:

uv init
uv add claude-agent-sdk

Python 3.9以下では No matching distribution found for claude-agent-sdk というエラーが出る。python3 --version でバージョンを確認してから入れること。

TypeScript

npm install @anthropic-ai/claude-agent-sdk

TypeScript SDKはClaude CodeのネイティブバイナリをSDKパッケージ内にバンドルしているので、Claude Code本体を別途インストールする必要はない。

APIキーの設定

export ANTHROPIC_API_KEY=your-api-key

プロジェクトの .env ファイルに書いておくと管理しやすい。

SDKはAmazon Bedrock、Google Vertex AI、Microsoft Azureも認証プロバイダーとして対応している。

# Bedrockの場合
export CLAUDE_CODE_USE_BEDROCK=1
# + AWS認証情報の設定

# Vertex AIの場合
export CLAUDE_CODE_USE_VERTEX=1
# + Google Cloud認証情報の設定

基本的な使い方(質問→応答の最小例)

最小構成のコードを見てみる。

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())
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "このディレクトリにあるファイルを一覧で教えて",
  options: { allowedTools: ["Bash", "Glob"] }
})) {
  if ("result" in message) console.log(message.result);
}

query() がメインのエントリポイントで、非同期イテレータを返す。async for で回すと、Claudeが作業しながら流してくる各メッセージを順番に受け取れる。

オプションの概要

ClaudeAgentOptions(Python)または options オブジェクト(TypeScript)に渡せる主なパラメータ:

パラメータ説明
allowed_tools / allowedTools事前承認するツールのリスト
permission_mode / permissionMode権限モード(後述)
system_prompt / systemPromptカスタムシステムプロンプト
max_turns / maxTurns最大ターン数
cwd作業ディレクトリ
resume既存セッションのID(セッション再開用)

パーミッションモード

モード動作
acceptEditsファイル編集と一般的なコマンドを自動承認
dontAskallowedTools 以外をすべて拒否
bypassPermissionsすべてのツールをプロンプトなしで実行(テスト環境向け)
defaultcanUseTool コールバックで承認フローを自分で実装

CI/CDやバックグラウンドジョブで使う場合は dontAskacceptEdits を明示するのが基本。default のままだと対話プロンプトが出てしまって処理が止まる。


ストリーミング応答の処理

query() はストリーミングで動作する。Claudeが何かを考え、ツールを呼び出し、結果を受け取り、また考える、というループの各ステップがメッセージとして流れてくる。

メッセージの種類と処理例:

import asyncio
from claude_agent_sdk import (
    query,
    ClaudeAgentOptions,
    AssistantMessage,
    ResultMessage,
    SystemMessage,
)


async def main():
    async for message in query(
        prompt="utils.pyにあるバグを探して修正して",
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Edit", "Glob"],
            permission_mode="acceptEdits",
        ),
    ):
        if isinstance(message, SystemMessage) and message.subtype == "init":
            # セッション開始。session_idが取れる
            print(f"セッション開始: {message.data.get('session_id')}")

        elif isinstance(message, AssistantMessage):
            # Claudeの発言・思考
            for block in message.content:
                if hasattr(block, "text"):
                    print(f"[Claude] {block.text}")
                elif hasattr(block, "name"):
                    print(f"[ツール呼び出し] {block.name}")

        elif isinstance(message, ResultMessage):
            # 最終結果
            print(f"完了: {message.subtype}")
            if message.subtype == "success":
                print(message.result)


asyncio.run(main())
import { query } from "@anthropic-ai/claude-agent-sdk";

let sessionId: string | undefined;

for await (const message of query({
  prompt: "utils.tsにあるバグを探して修正して",
  options: {
    allowedTools: ["Read", "Edit", "Glob"],
    permissionMode: "acceptEdits"
  }
})) {
  if (message.type === "system" && message.subtype === "init") {
    // セッション開始
    sessionId = (message as any).session_id;
    console.log(`セッション開始: ${sessionId}`);

  } else if (message.type === "assistant" && message.message?.content) {
    // Claudeの発言・思考
    for (const block of message.message.content) {
      if ("text" in block) {
        console.log(`[Claude] ${block.text}`);
      } else if ("name" in block) {
        console.log(`[ツール呼び出し] ${block.name}`);
      }
    }

  } else if (message.type === "result") {
    // 最終結果
    console.log(`完了: ${message.subtype}`);
    if ("result" in message) console.log(message.result);
  }
}

バックグラウンドジョブでリアルタイム出力が不要な場合は、すべてのメッセージを配列に集めてから処理するシングルターンモードもある。ストリーミングか一括処理かは用途に合わせて選ぶ。


Tool Use(ファイル操作・コマンド実行)

SDKで使えるビルトインツールの一覧:

ツールできること
Read作業ディレクトリ内のファイルを読む
Write新規ファイルを作成する
Edit既存ファイルを精密に編集する
Bashターミナルコマンド、スクリプト、git操作
Monitorバックグラウンドスクリプトを監視して各出力行を処理
Globパターンでファイルを検索(**/*.tssrc/**/*.py
Grep正規表現でファイル内容を検索
WebSearchWebを検索する
WebFetchWebページのコンテンツを取得・解析
AskUserQuestionユーザーに確認を求める

ツールの組み合わせパターン

# 読み取り専用の分析
options = ClaudeAgentOptions(allowed_tools=["Read", "Glob", "Grep"])

# コードを分析して修正まで
options = ClaudeAgentOptions(
    allowed_tools=["Read", "Edit", "Glob"],
    permission_mode="acceptEdits"
)

# フル自動化(テスト実行まで含む)
options = ClaudeAgentOptions(
    allowed_tools=["Read", "Edit", "Bash", "Glob", "Grep"],
    permission_mode="acceptEdits"
)
// 読み取り専用の分析
const readOnlyOptions = { allowedTools: ["Read", "Glob", "Grep"] };

// フル自動化
const fullOptions = {
  allowedTools: ["Read", "Edit", "Bash", "Glob", "Grep"],
  permissionMode: "acceptEdits" as const
};

MCP(Model Context Protocol)との接続

ビルトインツール以外に、MCPサーバー経由で外部システムへの接続もできる。

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions


async def main():
    async for message in query(
        prompt="example.comを開いて、ページの内容を教えて",
        options=ClaudeAgentOptions(
            mcp_servers={
                "playwright": {
                    "command": "npx",
                    "args": ["@playwright/mcp@latest"]
                }
            }
        ),
    ):
        if hasattr(message, "result"):
            print(message.result)


asyncio.run(main())
for await (const message of query({
  prompt: "example.comを開いて、ページの内容を教えて",
  options: {
    mcpServers: {
      playwright: { command: "npx", args: ["@playwright/mcp@latest"] }
    }
  }
})) {
  if ("result" in message) console.log(message.result);
}

Hooks連携(プログラムから挙動を制御)

Hooksは、エージェントのライフサイクルの特定のタイミングでカスタムコードを実行する仕組みだ。

「このコマンドは実行させない」「このファイルへの書き込みをログに残す」「外部APIに通知を送る」といった挙動をプログラムから制御できる。

主なHookイベント

イベントタイミング用途例
PreToolUseツール呼び出し前危険なコマンドをブロック
PostToolUseツール実行後変更内容をログに記録
PostToolUseFailureツール実行失敗時エラーを通知
UserPromptSubmitプロンプト送信時プロンプトにコンテキストを追加
Stop実行終了時セッション状態を保存
Notificationステータス通知時Slackなどに転送
SubagentStartサブエージェント開始時並列タスクの追跡
SubagentStopサブエージェント完了時結果の集約

基本的なHook設定

import asyncio
from datetime import datetime
from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher


async def log_file_change(input_data, tool_use_id, context):
    """ファイル変更をaudit.logに記録する"""
    file_path = input_data.get("tool_input", {}).get("file_path", "unknown")
    with open("./audit.log", "a") as f:
        f.write(f"{datetime.now()}: modified {file_path}\n")
    return {}


async def main():
    async for message in query(
        prompt="utils.pyをリファクタリングして可読性を上げて",
        options=ClaudeAgentOptions(
            permission_mode="acceptEdits",
            hooks={
                "PostToolUse": [
                    HookMatcher(matcher="Edit|Write", hooks=[log_file_change])
                ]
            },
        ),
    ):
        if hasattr(message, "result"):
            print(message.result)


asyncio.run(main())
import { query, HookCallback } from "@anthropic-ai/claude-agent-sdk";
import { appendFile } from "fs/promises";

const logFileChange: HookCallback = async (input) => {
  const filePath = (input as any).tool_input?.file_path ?? "unknown";
  await appendFile("./audit.log", `${new Date().toISOString()}: modified ${filePath}\n`);
  return {};
};

for await (const message of query({
  prompt: "utils.tsをリファクタリングして可読性を上げて",
  options: {
    permissionMode: "acceptEdits",
    hooks: {
      PostToolUse: [{ matcher: "Edit|Write", hooks: [logFileChange] }]
    }
  }
})) {
  if ("result" in message) console.log(message.result);
}

.envファイルへの書き込みをブロックする

セキュリティ上重要な制御の例として、 .env ファイルへの書き込みを禁止するHookを作ってみる。

async def protect_env_files(input_data, tool_use_id, context):
    file_path = input_data["tool_input"].get("file_path", "")
    file_name = file_path.split("/")[-1]

    if file_name == ".env":
        return {
            "hookSpecificOutput": {
                "hookEventName": input_data["hook_event_name"],
                "permissionDecision": "deny",
                "permissionDecisionReason": ".envファイルは変更できません",
            }
        }

    return {}


options = ClaudeAgentOptions(
    hooks={
        "PreToolUse": [
            HookMatcher(matcher="Write|Edit", hooks=[protect_env_files])
        ]
    }
)
import { query, HookCallback, PreToolUseHookInput } from "@anthropic-ai/claude-agent-sdk";

const protectEnvFiles: HookCallback = async (input) => {
  const preInput = input as PreToolUseHookInput;
  const toolInput = preInput.tool_input as Record<string, unknown>;
  const filePath = toolInput?.file_path as string;
  const fileName = filePath?.split("/").pop();

  if (fileName === ".env") {
    return {
      hookSpecificOutput: {
        hookEventName: preInput.hook_event_name,
        permissionDecision: "deny",
        permissionDecisionReason: ".envファイルは変更できません"
      }
    };
  }

  return {};
};

permissionDecision"allow" / "deny" / "ask" / "defer" の4種類。複数のHookが衝突した場合は deny が最優先になる。


本番運用パターン(エラーハンドリング・タイムアウト・コスト管理)

エラーハンドリング

Claudeが実行に失敗すると ResultMessagesubtype"error" になる。これを必ず拾う。

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage


async def run_with_error_handling(prompt: str, max_retries: int = 3):
    for attempt in range(max_retries):
        try:
            async for message in query(
                prompt=prompt,
                options=ClaudeAgentOptions(
                    allowed_tools=["Read", "Edit", "Bash"],
                    permission_mode="acceptEdits",
                    max_turns=20,  # 無限ループ防止
                ),
            ):
                if isinstance(message, ResultMessage):
                    if message.subtype == "success":
                        return message.result
                    elif message.subtype == "error":
                        print(f"実行エラー (attempt {attempt + 1}): {message}")
                        break

        except Exception as e:
            print(f"例外 (attempt {attempt + 1}): {e}")
            if attempt == max_retries - 1:
                raise

    return None


asyncio.run(run_with_error_handling("src/auth.pyのバグを直して"))
import { query, ResultMessage } from "@anthropic-ai/claude-agent-sdk";

async function runWithRetry(prompt: string, maxRetries = 3): Promise<string | null> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      for await (const message of query({
        prompt,
        options: {
          allowedTools: ["Read", "Edit", "Bash"],
          permissionMode: "acceptEdits",
          maxTurns: 20
        }
      })) {
        if (message.type === "result") {
          if (message.subtype === "success" && "result" in message) {
            return message.result as string;
          } else if (message.subtype === "error") {
            console.log(`実行エラー (attempt ${attempt + 1})`);
            break;
          }
        }
      }
    } catch (e) {
      console.log(`例外 (attempt ${attempt + 1}): ${e}`);
      if (attempt === maxRetries - 1) throw e;
    }
  }
  return null;
}

タイムアウト制御

SDKにはセッション単位のタイムアウト機能がない。maxTurns でターン数を制限するのが現実的な制御方法だ。

options = ClaudeAgentOptions(
    allowed_tools=["Read", "Edit", "Bash"],
    permission_mode="acceptEdits",
    max_turns=30,  # 最大30ターンで強制終了
)
const options = {
  allowedTools: ["Read", "Edit", "Bash"],
  permissionMode: "acceptEdits" as const,
  maxTurns: 30
};

処理時間でのタイムアウトが必要な場合は Promise.race()asyncio.wait_for() と組み合わせる。

コスト管理

トークンコストがインフラコストを大きく上回ることが多いので、コスト計測は重要だ。

# セッションIDでコスト追跡
async def main():
    session_id = None
    total_cost_info = []

    async for message in query(
        prompt="コードベース全体を分析して改善点をリストアップして",
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Glob", "Grep"],
        ),
    ):
        # SystemMessageからセッションIDを取得
        if hasattr(message, "subtype") and message.subtype == "init":
            if hasattr(message, "data"):
                session_id = message.data.get("session_id")

        # ResultMessageにはコスト情報が含まれることがある
        if hasattr(message, "usage"):
            total_cost_info.append(message.usage)

    print(f"Session: {session_id}")
    # cost_tracking オプションの詳細はAnthropicドキュメントを参照


asyncio.run(main())

本番ではOpenTelemetryを使った観測も有効だ。

# .env
CLAUDE_CODE_ENABLE_TELEMETRY=1
OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=otlp
OTEL_EXPORTER_OTLP_ENDPOINT=http://collector.example.com:4318

マルチテナント環境での分離

複数のユーザーのジョブを1台のサーバーで処理する場合は、テナント間でファイルシステムが混在しないよう分離する。

from claude_agent_sdk import query, ClaudeAgentOptions

async def run_for_tenant(tenant_id: str, prompt: str, tenant_dir: str):
    """テナントごとに作業ディレクトリと設定を分離する"""
    async for message in query(
        prompt=prompt,
        options=ClaudeAgentOptions(
            cwd=tenant_dir,
            setting_sources=[],  # ファイルシステムの設定を読み込まない
            env={
                "CLAUDE_CONFIG_DIR": f"/configs/{tenant_id}",
                "CLAUDE_CODE_DISABLE_AUTO_MEMORY": "1",
            },
        ),
    ):
        yield message
async function* runForTenant(tenantId: string, prompt: string, tenantDir: string) {
  for await (const message of query({
    prompt,
    options: {
      cwd: tenantDir,
      settingSources: [],
      env: {
        ...process.env,
        CLAUDE_CONFIG_DIR: `/configs/${tenantId}`,
        CLAUDE_CODE_DISABLE_AUTO_MEMORY: "1"
      }
    }
  })) {
    yield message;
  }
}

GitHub Actions / Webhook連携サンプル

GitHub Actions でPRを自動レビュー

.github/workflows/claude-review.yml として配置する。

name: Claude Code Review

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install Claude Agent SDK
        run: pip install claude-agent-sdk

      - name: Run code review
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
        run: python .github/scripts/review.py
# .github/scripts/review.py
import asyncio
import os
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage


async def main():
    pr_number = os.getenv("PR_NUMBER")

    prompt = f"""
    このPR(#{pr_number})の変更内容をレビューしてください。
    以下の観点で確認し、Markdownで報告書を作成してください:
    - バグの可能性
    - セキュリティ上の懸念
    - コード品質
    - テストの十分性
    """

    async for message in query(
        prompt=prompt,
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Glob", "Grep", "Bash"],
            permission_mode="dontAsk",  # CI環境なので対話プロンプト禁止
            system_prompt="あなたはシニアエンジニアです。コードレビューを行ってください。",
            max_turns=20,
        ),
    ):
        if isinstance(message, ResultMessage):
            if message.subtype == "success":
                print(message.result)
                # GitHubコメントAPIでPRに結果を投稿する処理をここに追加
            break


asyncio.run(main())
// .github/scripts/review.ts
import { query, ResultMessage } from "@anthropic-ai/claude-agent-sdk";

const prNumber = process.env.PR_NUMBER;

const prompt = `
このPR(#${prNumber})の変更内容をレビューしてください。
以下の観点で確認し、Markdownで報告書を作成してください:
- バグの可能性
- セキュリティ上の懸念
- コード品質
- テストの十分性
`;

for await (const message of query({
  prompt,
  options: {
    allowedTools: ["Read", "Glob", "Grep", "Bash"],
    permissionMode: "dontAsk",
    systemPrompt: "あなたはシニアエンジニアです。コードレビューを行ってください。",
    maxTurns: 20
  }
})) {
  if (message.type === "result") {
    if (message.subtype === "success" && "result" in message) {
      console.log(message.result);
      // GitHubコメントAPIでPRに結果を投稿する処理をここに追加
    }
    break;
  }
}

Webhook受信時に自動修正

Express.jsのWebhookサーバーの例:

import express from "express";
import { query } from "@anthropic-ai/claude-agent-sdk";

const app = express();
app.use(express.json());

app.post("/webhook/fix-bug", async (req, res) => {
  const { filePath, errorMessage, repository } = req.body;

  // 即座にレスポンスを返してWebhookのタイムアウトを防ぐ
  res.json({ status: "processing", message: "修正を開始しました" });

  // バックグラウンドで修正を実行
  (async () => {
    const prompt = `
      ${filePath} でエラーが発生しています:
      ${errorMessage}

      ファイルを読んでエラーの原因を特定し、修正してください。
      修正後はテストを実行して動作確認してください。
    `;

    for await (const message of query({
      prompt,
      options: {
        allowedTools: ["Read", "Edit", "Bash"],
        permissionMode: "acceptEdits",
        cwd: `/repos/${repository}`,
        maxTurns: 15
      }
    })) {
      if (message.type === "result") {
        // Slackなどへの通知処理
        console.log(`修正完了: ${message.subtype}`);
      }
    }
  })();
});

app.listen(3000);

FAQ(よくある質問)

Q. Claude Agent SDKとManaged Agentsはどう違う?

A. Agent SDKは自分のサーバー上でエージェントループを動かすライブラリ。Managed AgentsはAnthropicのインフラ上でエージェントを動かすREST API。手元のファイルシステムに直接アクセスしたい場合やカスタムHooksが必要な場合はAgent SDK、インフラ管理を任せたい場合はManaged Agentsが向いている。

Q. クレジット消費はAPIキーと別?

A. 2026年6月15日以降、サブスクリプションプランでのAgent SDKと claude -p の使用は、インタラクティブ利用とは別の「月次Agent SDKクレジット」から引き落とされるようになった。詳細はAnthropicのサポートページを確認してほしい。

Q. セッションを跨いで会話を続けられる?

A. できる。SystemMessageinit イベントからセッションIDを取得しておいて、次の query()resume=session_id を渡すと、前のセッションの文脈(読んだファイル、分析内容、会話履歴)をすべて引き継いで作業を続けられる。

# セッションIDを保存しておく
session_id = None
async for message in query(prompt="認証モジュールを読んで"):
    if hasattr(message, "subtype") and message.subtype == "init":
        if hasattr(message, "data"):
            session_id = message.data["session_id"]

# 別の処理で再開
async for message in query(
    prompt="それを呼び出している箇所をすべて見つけて",
    options=ClaudeAgentOptions(resume=session_id),
):
    if hasattr(message, "result"):
        print(message.result)

Q. サブエージェントを使うと何が嬉しい?

A. 並列処理ができる。「コードレビューエージェント」「テスト生成エージェント」「ドキュメント更新エージェント」みたいに専門化したエージェントを定義しておいて、メインエージェントが仕事を振り分けるアーキテクチャが作れる。allowed_tools"Agent" を追加すると有効になる。

Q. Python 3.9で動かしたらエラーになった

A. Claude Agent SDKはPython 3.10以上が必要。python3 --version でバージョンを確認してアップグレードすること。

Q. Hooksでエラーが発生するとエージェントも止まる?

A. Hook関数内で例外をcatchしておかないと、エージェントの実行が中断される可能性がある。ログ送信や通知など副作用だけのHookは、必ず内部でtry/catchするか、async: true の非同期モードを使って影響を切り離しておく。

Q. claude -p コマンドとの関係は?

A. claude -p はCLIからnon-interactiveにClaude Codeを呼び出すコマンド。Agent SDKはその機能をPython/TypeScriptのライブラリから使えるようにしたもの。内部的には同じエンジンが動いている。


おわりに

Claude Agent SDKを使えば、「CLIで手でやっていた作業」をコードに変換できる。

最初は「APIキーを設定して query() を呼ぶだけ」から始めて、Hooks で細かい制御を加えていくのがスムーズだと思う。GitHubActionsやWebhookとの連携は、一度動くサンプルを作ってから本番に繋げるのが順番として楽だ。

2026年6月以降はサブスクリプションプランでのAgent SDK利用が別クレジットになったので、コスト感は初めに確認しておくといい。


関連記事

← 記事一覧に戻る