【Claude Code 連載 第78回】Agent SDK クイックスタート — バグを自分で直すエージェントを作る

スポンサーリンク
【Claude Code 連載 第78回】Agent SDK クイックスタート — バグを自分で直すエージェントを作る 用語解説
【Claude Code 連載 第78回】Agent SDK クイックスタート — バグを自分で直すエージェントを作る
この記事は約16分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

スポンサーリンク

背景

この連載では、Claude Codeの公式ドキュメントを1ページずつ読み解いていきます。公式ドキュメントは情報が網羅されている分、「結局どの機能を、どんな場面で使えばいいのか」は自分で考える必要があり、読むのに意外と時間がかかります。そこで、私が実務で使うために読み込んだ内容を「使う場面→実例コード」の順に整理して残していくことにしました。専門家の解説というより、一次情報を読んだ記録です。推測や動作を確認していない部分には、その都度そう書きます。

1. 一言でいうと何か

このページは、Agent SDK で最初のエージェントを実際に動かすための手順書です。

第76回で全体像、第77回でループの中身を見てきました。今回はその実行編。原文の宣言はこうです。

Agent SDK を使用して、コードを読み、バグを見つけ、すべて手動操作なしで修正する AI エージェントを構築します。

やることは3つ。Agent SDK でプロジェクトをセットアップする/バグのあるコードを含むファイルを作成する/バグを自動的に見つけて修正するエージェントを実行する。

わざとバグを仕込んで、それを直させる——動いたことが目で確認できる題材になっています。

このページの締めくくりに置かれた一文が、SDK の価値をよく表しています。

これが Agent SDK を異なるものにする理由です:Claude は、実装するよう求める代わりに、ツールを直接実行します。

前提条件は2つ。Node.js 18+ または Python 3.10+、そしてAnthropic アカウントです。

2. どういう場面で役立つか

シーン1:SDK を初めて触る

インストールから実行まで、4つのツールチェーン(TypeScript 新規/TypeScript 既存/Python + uv/Python + pip)それぞれの手順が揃っています。自分の環境に合うタブを選べばよい構成です。

シーン2:SDK が「動くかどうか」を確かめる

バグ入りファイルを1つ置いて走らせるだけなので、環境が正しく組めているかの検証にそのまま使えます。認証エラーの切り分け方も書かれています。

シーン3:オプションの効き方を体で覚える

**オプションを変更することで、エージェントの動作を変更できます。**Web 検索を足す、システムプロンプトを変える、Bash を許す——3パターンの差分が示されています。

不要・向かないケース

  • **claude.ai のサブスクリプションで動かしたい。**第76回と同じ制約が再掲されています。事前に承認されていない限り、Anthropic は、Claude Agent SDK で構築されたエージェントを含む、サードパーティ開発者が claude.ai ログインまたはレート制限を提供することを許可していません。
  • **.env に API キーを置いて自動で読ませたい。**読みません(後述)。
  • **リアルタイム表示が要らない。****ライブ出力が不要な場合(バックグラウンドジョブや CI パイプラインなど)、すべてのメッセージを一度に収集できます。**この記事の例はストリーミング前提です。
  • **npm ci --omit=optional で入れている。**バイナリが落ちてきません(後述)。

3. 手順とコードの解説

このページの fenced ブロックは20本あります。方針を先に述べます。セットアップから実行までの11本(ディレクトリ作成・4種のインストール・2種の API キー設定・バグ入りファイル・エージェント本体 Python/TypeScript)は原文どおり全数引用します。一方、実行コマンド3本と、末尾の「カスタマイズ」6本は表に圧縮します。後者は同じオプションオブジェクトの1フィールドだけを差し替えた対訳が並ぶ形なので、表のほうが差分が見えるためです。

前提:このページ自体にバージョン要件の記載はありません。

プロジェクトを作る

mkdir my-agent
cd my-agent

独自のプロジェクトの場合、任意のフォルダから SDK を実行できます。デフォルトでは、そのディレクトリとそのサブディレクトリ内のファイルにアクセスできます。

SDK を入れる

TypeScript(新規プロジェクト)。

npm init -y
npm pkg set type=module
npm install @anthropic-ai/claude-agent-sdk
npm install --save-dev tsx

意図が説明されています。package.json で "type": "module" を設定すると、エージェントスクリプトでトップレベルの await を使用でき、tsx は TypeScript ファイルを直接実行します。

TypeScript(既存プロジェクト)。

npm install @anthropic-ai/claude-agent-sdk
npm install --save-dev tsx

こちらには CommonJS 向けの回避策が付いています。プロジェクトが CommonJS を使用している場合は、エージェントスクリプトを agent.ts の代わりに agent.mts という名前にしてください。.mts 拡張子により、tsx はファイルを ES モジュールとして扱うため、プロジェクト全体を ES モジュールに変換することなく、トップレベルの await が機能します。

Python(uv)。

uv init
uv add claude-agent-sdk

Python(pip、macOS / Linux)。

python3 -m venv .venv
source .venv/bin/activate
pip install claude-agent-sdk

Python(pip、Windows)。

py -m venv .venv
.venv\Scripts\Activate.ps1
pip install claude-agent-sdk

Windows 固有の詰まりどころも書かれています。PowerShell が実行ポリシーエラーで Activate.ps1 をブロックする場合は、まず Set-ExecutionPolicy -Scope Process RemoteSigned を実行してください。

バイナリがバンドルされない2つの例外は、第77回では触れられていなかった実務情報です。

  • pip が Python SDK のソース配布をプラットフォームホイールの代わりにインストールする場合(たとえば ARM64 Windows)、バイナリはバンドルされません。この場合はClaude Code をネイティブにインストールすれば、Python SDK は PATH 上でそれを見つけます。
  • TypeScript SDK は npm オプション依存関係を通じてバイナリをインストールするため、それらをスキップするインストール(たとえば npm ci --omit=optional)は、サポートされているプラットフォームでもバイナリを取得しません。対処はオプション依存関係をスキップせずに再インストールするか、Claude Code をネイティブにインストールして pathToClaudeCodeExecutable をそのパスに設定すること。

**CI で npm ci --omit=optional を使っている環境は、これで確実に踏みます。**覚えておく価値があります。

API キーを設定する

export ANTHROPIC_API_KEY=your-api-key
$env:ANTHROPIC_API_KEY = "your-api-key"

必ず読むべき制約がここにあります。

SDK はエージェントを実行するプロセスの環境からキーを読み取ります。.env ファイルを自動的に読み込みません。キーを .env ファイルに保持している場合は、SDK を呼び出す前に、たとえば dotenv パッケージを使用して自分で読み込んでください。

**.env は自動で読まれない。**Node や Python の他のフレームワークに慣れていると、まずここでつまずきます。

サードパーティプロバイダーも使えます。Amazon Bedrock(CLAUDE_CODE_USE_BEDROCK=1)/Claude Platform on AWS(CLAUDE_CODE_USE_ANTHROPIC_AWS=1 と ANTHROPIC_AWS_WORKSPACE_ID)/Google Cloud の Agent Platform(CLAUDE_CODE_USE_VERTEX=1)/Microsoft Foundry(CLAUDE_CODE_USE_FOUNDRY=1)、いずれも各クラウドの認証情報の設定が必要です。

バグ入りファイルを置く

def calculate_average(numbers):
    total = 0
    for num in numbers:
        total += num
    return total / len(numbers)


def get_user_name(user):
    return user["name"].upper()

このコードには2つのバグがあります。calculate_average([]) はゼロで除算してクラッシュします。get_user_name(None) は TypeError でクラッシュします。

どちらもエッジケースの未処理です。「動くように見えるが壊れる」典型なので、エージェントの分析能力を見るのに適した題材だと思います(この評価は筆者のものです)。

エージェント本体

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


async def main():
    # Agentic ループ:Claude が動作するときにメッセージをストリーミングします
    async for message in query(
        prompt="Review utils.py for bugs that would cause crashes. Fix any issues you find.",
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Edit", "Glob"],  # これらのツールを自動承認します
            permission_mode="acceptEdits",  # ファイル編集を自動承認します
        ),
    ):
        # 人間が読める出力を印刷します
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if hasattr(block, "text"):
                    print(block.text)  # Claude の推論
                elif hasattr(block, "name"):
                    print(f"Tool: {block.name}")  # 呼び出されているツール
        elif isinstance(message, ResultMessage):
            print(f"Done: {message.subtype}")  # 最終結果


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

// Agentic ループ:Claude が動作するときにメッセージをストリーミングします
for await (const message of query({
  prompt: "Review utils.py for bugs that would cause crashes. Fix any issues you find.",
  options: {
    allowedTools: ["Read", "Edit", "Glob"], // これらのツールを自動承認します
    permissionMode: "acceptEdits" // ファイル編集を自動承認します
  }
})) {
  // 人間が読める出力を印刷します
  if (message.type === "assistant" && message.message?.content) {
    for (const block of message.message.content) {
      if ("text" in block) {
        console.log(block.text); // Claude の推論
      } else if ("name" in block) {
        console.log(`Tool: ${block.name}`); // 呼び出されているツール
      }
    }
  } else if (message.type === "result") {
    console.log(`Done: ${message.subtype}`); // 最終結果
  }
}

構成要素は3つと整理されています。

  • query:agentic ループを作成するメインエントリーポイント。非同期イテレーターを返すため、async for を使用して Claude が動作するときにメッセージをストリーミングします。
  • prompt:Claude に実行させたいこと。Claude はタスクに基づいて使用するツールを判断します。
  • options:エージェントの構成。

ループが何をしているかの説明が、第77回の内容とつながります。async for ループは、Claude が考え、ツールを呼び出し、結果を観察し、次に何をするかを決定する間、実行し続けます。そしてSDK はオーケストレーション(ツール実行、コンテキスト管理、再試行)を処理するため、ストリームを消費するだけです。

フィルタリングの理由も書かれています。フィルタリングなしでは、システム初期化と内部状態を含む生のメッセージオブジェクトが表示されます。これはデバッグに役立ちますが、そうでない場合はノイズが多くなります。

第77回で指摘した TypeScript の message.message.content 二重構造が、ここでも実物として出てきます(message.message?.content)。

実行する

ツールチェーンコマンド
TypeScriptnpx tsx agent.ts(agent.mts にした場合は npx tsx agent.mts)
Python(uv)uv run agent.py
Python(pip)仮想環境がアクティブな状態で python agent.py

期待される動きはこうです。エージェントは推論と呼び出す各ツールを印刷し、Done: success で終了します。実行後、utils.py を確認します。空のリストと null ユーザーを処理する防御的なコードが表示されます。

エージェントが自律的に行う3ステップも明示されています。読み取り(utils.py でコードを理解)→ 分析(ロジックを分析し、クラッシュを引き起こすエッジケースを特定)→ 編集(ファイルを編集して適切なエラーハンドリングを追加)。

認証で詰まったときの切り分けも用意されています。Not logged in や Invalid API key などの認証エラーが表示される場合は、エージェントを実行するシェルで ANTHROPIC_API_KEY 環境変数を設定していることを確認してください。SDK は .env ファイルを自動的に読み込みません。

他のプロンプトを試す

原文が挙げる3つ。

  • "Add docstrings to all functions in utils.py"
  • "Add type hints to all functions in utils.py"
  • "Create a README.md documenting the functions in utils.py"

カスタマイズ3パターン

オプションを変更することで、エージェントの動作を変更できます。原文は Python / TypeScript の対訳で6ブロックを示していますが、いずれも同じオプションオブジェクトの1フィールドを差し替えたものなので、差分を表にまとめます。

目的変更点(Python / TypeScript)
Web 検索機能を追加するallowed_tools / allowedTools を ["Read", "Edit", "Glob", "WebSearch"] に
カスタムシステムプロンプトを与えるsystem_prompt / systemPrompt に "You are a senior Python developer. Always follow PEP 8 style guidelines." を追加
ターミナルでコマンドを実行するallowed_tools / allowedTools に "Bash" を追加

いずれも permission_mode / permissionMode は "acceptEdits" のままです。原文の補足どおり、各スニペットは同じオプションオブジェクトのフィールドを設定します。

Bash を許した場合の試しプロンプトも示されています。"Write unit tests for utils.py, run them, and fix any failures"——テストを書いて、走らせて、落ちたら直すという、ツールを持たせて初めて成立するタスクです。

ツールの組み合わせ=できることの範囲

ツールエージェントが実行できること
Read、Glob、Grep読み取り専用分析
Read、Edit、Globコードの分析と変更
Read、Edit、Bash、Glob、Grep完全な自動化

**ツールはエージェントが何ができるかを制御します。権限モードについては第77回で扱った表に委ねられており、このページでは「SDK は、アクティブなモードをあなたの許可ルールと拒否ルールと共に、固定の順序で評価します」**とだけ述べられています。

4. まとめ + 次回予告

  • 前提はNode.js 18+ または Python 3.10+ と Anthropic アカウント。
  • インストール経路は4つ——TypeScript 新規/TypeScript 既存/Python + uv/Python + pip。
  • TypeScript は "type": "module" とトップレベル await。CommonJS プロジェクトならagent.mts にすれば全体を変換せずに済む。
  • **SDK にはネイティブ Claude Code バイナリがバンドルされるが、例外が2つ。ソース配布でインストールされた Python SDK(ARM64 Windows など)と、npm ci --omit=optional のようにオプション依存をスキップした TypeScript SDK。**後者は pathToClaudeCodeExecutable で逃げられる。
  • API キーはプロセスの環境変数から読む。.env は自動で読まれない。dotenv 等で自分で読み込む。
  • Bedrock / Claude Platform on AWS / Google Cloud の Agent Platform / Microsoft Foundry も環境変数で選べる。
  • claude.ai ログインをエンドユーザーに提供するのは、事前承認がない限り不可。
  • エージェントの骨格は3要素——query(非同期イテレーターを返す)/prompt/options。
  • **async for を回すだけでよい。**ツール実行・コンテキスト管理・再試行は SDK 側が持つ。
  • 生メッセージにはシステム初期化や内部状態が混ざるので、表示にはフィルタが要る。
  • TypeScript は**message.message?.content**(第77回で見た二重構造)。
  • 実行は**npx tsx agent.ts / uv run agent.py / python agent.py。成功するとDone: success。**
  • 挙動は読み取り → 分析 → 編集の3段階。
  • 認証エラーが出たら、まず実行するシェルで ANTHROPIC_API_KEY が設定されているかを見る。
  • カスタマイズは**allowedTools に足すか、systemPrompt を与えるか。**Bash を足せば「テストを書いて走らせて直す」まで届く。
  • ツールの組み合わせが権限の実体——読み取り専用/分析と変更/完全な自動化の3段階で考える。

次回予告(暫定):このページが「各設定をカバーするページを見つける」入口として指していた**エージェントの設定(agent-sdk/configuration)**を取り上げ、オプションオブジェクトの全体像とモデル選択を扱う予定です。


よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました