前提条件

  • Node.js 18+

インストール

NPMから@anthropic-ai/claude-codeをインストールします:

npm install -g @anthropic-ai/claude-code

TypeScript SDKのソースコードを表示するには、NPMの@anthropic-ai/claude-codeページをご覧ください。

基本的な使用方法

TypeScript SDKを介した主要なインターフェースはquery関数で、メッセージが到着するとそれらをストリーミングする非同期イテレータを返します:

import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "システムパフォーマンスを分析する",
  options: {
    maxTurns: 5,
    appendSystemPrompt: "あなたはパフォーマンスエンジニアです",
    allowedTools: ["Bash", "Read", "WebSearch"],
    abortController: new AbortController(),
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

設定オプション

引数説明デフォルト
abortControllerAbortController操作をキャンセルするためのアボートコントローラーnew AbortController()
additionalDirectoriesstring[]セッションに含める追加ディレクトリundefined
allowedToolsstring[]Claudeが使用を許可されているツールのリストデフォルトで全ツールが有効
appendSystemPromptstringデフォルトのシステムプロンプトに追加するテキストundefined
canUseTool(toolName: string, input: any) => Promise<ToolPermissionResult>ツール使用のカスタム許可関数undefined
continueboolean最新のセッションを継続するfalse
customSystemPromptstringデフォルトのシステムプロンプトを完全に置き換えるundefined
cwdstring現在の作業ディレクトリprocess.cwd()
disallowedToolsstring[]Claudeが使用を許可されていないツールのリストundefined
envDict<string>設定する環境変数undefined
executable'bun' | 'deno' | 'node'使用するJavaScriptランタイムNode.jsで実行時はnode、Bunで実行時はbun
executableArgsstring[]実行可能ファイルに渡す引数[]
fallbackModelstringプライマリモデルが失敗した場合に使用するモデルundefined
hooksPartial<Record<HookEvent, HookCallbackMatcher[]>>カスタマイゼーション用のライフサイクルフックundefined
includePartialMessagesbooleanメッセージストリームに部分的なストリーミングイベントを含めるfalse
maxThinkingTokensnumberClaudeの思考プロセスの最大トークン数undefined
maxTurnsnumber会話ターンの最大数undefined
mcpServersRecord<string, McpServerConfig>MCPサーバー設定undefined
modelstring使用するClaudeモデルCLI設定からのデフォルトを使用
pathToClaudeCodeExecutablestringClaude Code実行可能ファイルへのパス@anthropic-ai/claude-codeに付属の実行可能ファイル
permissionModePermissionModeセッションの許可モード"default" (オプション: "default", "acceptEdits", "bypassPermissions", "plan")
resumestring再開するセッションIDundefined
stderr(data: string) => voidstderr出力のコールバックundefined
strictMcpConfigboolean厳密なMCP設定検証を強制するundefined

部分メッセージストリーミング

includePartialMessagesが有効になっている場合、SDKはClaude APIからの生のストリーミングイベントを含むstream_eventメッセージを発行します。これにより、生成中の部分的なコンテンツにアクセスでき、リアルタイムUI更新やプログレスインジケーターの実装に便利です。

import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "人工知能について長いエッセイを書いて",
  options: {
    includePartialMessages: true,
    maxTurns: 1
  }
})) {
  // 部分的なストリーミングイベントを処理
  if (message.type === "stream_event") {
    const event = message.event;
    
    // ストリーミング中の部分的なテキストにアクセス
    if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
      process.stdout.write(event.delta.text);
    }
    
    // 思考の進捗を追跡
    if (event.type === "content_block_start" && event.content_block.type === "thinking") {
      console.log("\n[Claudeが考えています...]");
    }
  }
  
  // 最終結果も取得
  if (message.type === "result" && message.subtype === "success") {
    console.log("\n最終結果:", message.result);
  }
}

stream_eventメッセージには以下が含まれます:

  • event: APIからの生のストリーミングイベント
  • session_id: 現在のセッション識別子
  • parent_tool_use_id: 実行中のツールのID(該当する場合)
  • uuid: このイベントの一意識別子

部分メッセージストリーミングは主に、ストリーミングレスポンスに対する細かい制御が必要な高度なユースケースに有用です。ほとんどのアプリケーションでは、デフォルトの動作(完全なメッセージを待つ)で十分です。

マルチターン会話

マルチターン会話には2つのオプションがあります。

レスポンスを生成して再開するか、メッセージの配列に対して非同期/ジェネレーターを受け入れるストリーミング入力モードを使用できます。現在のところ、ストリーミング入力モードがメッセージ経由で画像を添付する唯一の方法です。

セッション管理による再開

import { query } from "@anthropic-ai/claude-code";

// 最新の会話を継続
for await (const message of query({
  prompt: "今度はパフォーマンス向上のためにリファクタリングして",
  options: { continue: true }
})) { 
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// 特定のセッションを再開
for await (const message of query({
  prompt: "テストを更新して",
  options: {
    resume: "550e8400-e29b-41d4-a716-446655440000",
    maxTurns: 3
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

ストリーミング入力モード

ストリーミング入力モードでは、単一の文字列の代わりに非同期イテラブルとしてメッセージを提供できます。これにより、マルチターン会話、画像添付、動的メッセージ生成が可能になります:

import { query } from "@anthropic-ai/claude-code";

// ストリーミングメッセージ用の非同期ジェネレーターを作成
async function* generateMessages() {
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: "このコードベースの分析を開始して"
    }
  };
  
  // 何らかの条件やユーザー入力を待つ
  await new Promise(resolve => setTimeout(resolve, 1000));
  
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: "今度は認証モジュールに焦点を当てて"
    }
  };
}

// ストリーミング入力を使用
for await (const message of query({
  prompt: generateMessages(),
  options: {
    maxTurns: 5,
    allowedTools: ["Read", "Grep", "Bash"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

画像付きストリーミング入力

ストリーミング入力モードは、メッセージ経由で画像を添付する唯一の方法です:

import { query } from "@anthropic-ai/claude-code";
import { readFileSync } from "fs";

async function* messagesWithImage() {
  // テキストと一緒に画像を送信
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: [
        {
          type: "text",
          text: "このスクリーンショットを分析して改善点を提案して"
        },
        {
          type: "image",
          source: {
            type: "base64",
            media_type: "image/png",
            data: readFileSync("screenshot.png", "base64")
          }
        }
      ]
    }
  };
}

for await (const message of query({
  prompt: messagesWithImage()
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

カスタムシステムプロンプト

システムプロンプトは、エージェントの役割、専門知識、動作を定義します:

import { query } from "@anthropic-ai/claude-code";

// SREインシデント対応エージェント
for await (const message of query({
  prompt: "APIがダウンしています、調査してください",
  options: {
    customSystemPrompt: "あなたはSREの専門家です。問題を体系的に診断し、実行可能な解決策を提供してください。",
    maxTurns: 3
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// デフォルトのシステムプロンプトに追加
for await (const message of query({
  prompt: "この関数をリファクタリングして",
  options: {
    appendSystemPrompt: "常に包括的なエラーハンドリングとユニットテストを含めてください。",
    maxTurns: 2
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

MCPサーバー統合

Model Context Protocol(MCP)により、エージェントにカスタムツールと機能を提供できます:

import { query } from "@anthropic-ai/claude-code";

// 監視ツール付きSREエージェント
for await (const message of query({
  prompt: "決済サービスの障害を調査して",
  options: {
    mcpConfig: "sre-tools.json",
    allowedTools: ["mcp__datadog", "mcp__pagerduty", "mcp__kubernetes"],
    appendSystemPrompt: "あなたはSREです。監視データを使用して問題を診断してください。",
    maxTurns: 4
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

インプロセスMCPサーバーによるカスタムツール

SDK MCPサーバーを使用すると、アプリケーションプロセス内で直接実行されるカスタムツールを作成でき、別プロセスやネットワーク通信のオーバーヘッドなしに型安全なツール実行を提供します。

カスタムツールの作成

createSdkMcpServertoolヘルパー関数を使用して型安全なカスタムツールを定義します:

import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-code";
import { z } from "zod";

// カスタムツール付きSDK MCPサーバーを作成
const customServer = createSdkMcpServer({
  name: "my-custom-tools",
  version: "1.0.0",
  tools: [
    tool(
      "calculate_compound_interest",
      "投資の複利を計算する",
      {
        principal: z.number().describe("初期投資額"),
        rate: z.number().describe("年利率(小数、例:5%の場合0.05)"),
        time: z.number().describe("投資期間(年)"),
        n: z.number().default(12).describe("年間複利回数")
      },
      async (args) => {
        const amount = args.principal * Math.pow(1 + args.rate / args.n, args.n * args.time);
        const interest = amount - args.principal;
        
        return {
          content: [{
            type: "text",
            text: `最終金額: $${amount.toFixed(2)}\n獲得利息: $${interest.toFixed(2)}`
          }]
        };
      }
    ),
    tool(
      "fetch_user_data",
      "アプリケーションデータベースからユーザーデータを取得する",
      {
        userId: z.string().describe("取得するユーザーID"),
        fields: z.array(z.string()).optional().describe("返す特定のフィールド")
      },
      async (args) => {
        // アプリケーションのデータレイヤーへの直接アクセス
        const userData = await myDatabase.getUser(args.userId, args.fields);
        
        return {
          content: [{
            type: "text",
            text: JSON.stringify(userData, null, 2)
          }]
        };
      }
    )
  ]
});

// クエリでカスタムツールを使用
for await (const message of query({
  prompt: "$10,000を5%で10年間の複利を計算して",
  options: {
    mcpServers: {
      "my-custom-tools": customServer
    },
    maxTurns: 3
  }
})) {
  if (message.type === "result") {
    console.log(message.result);
  }
}

Zodによる型安全性

toolヘルパーは、Zodスキーマから完全なTypeScript型推論を提供します:

tool(
  "process_data",
  "型安全性を持つ構造化データを処理する",
  {
    // Zodスキーマはランタイム検証とTypeScript型の両方を定義
    data: z.object({
      name: z.string(),
      age: z.number().min(0).max(150),
      email: z.string().email(),
      preferences: z.array(z.string()).optional()
    }),
    format: z.enum(["json", "csv", "xml"]).default("json")
  },
  async (args) => {
    // argsはスキーマに基づいて完全に型付けされる
    // TypeScriptは知っている: args.data.nameは文字列、args.data.ageは数値など
    console.log(`${args.data.name}のデータを${args.format}として処理中`);
    
    // ここに処理ロジック
    return {
      content: [{
        type: "text",
        text: `${args.data.name}のデータを処理しました`
      }]
    };
  }
)

フック

フックを使用すると、エージェントのライフサイクルの様々な時点でカスタムコールバックを実行することで、Claude Codeの動作をカスタマイズおよび拡張できます。bashコマンドを実行するCLIフックとは異なり、SDKフックはインプロセスで実行されるJavaScript/TypeScript関数です。

フックの定義

フックはイベントタイプ別に整理され、実行タイミングをフィルタリングするオプションのマッチャーがあります:

import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "コードベースを分析して",
  options: {
    hooks: {
      PreToolUse: [
        {
          matcher: "Write",
          hooks: [
            async (input, toolUseId, { signal }) => {
              console.log(`ファイル書き込み予定: ${input.tool_input.file_path}`);
              
              // 操作を検証
              if (input.tool_input.file_path.includes('.env')) {
                return {
                  decision: 'block',
                  stopReason: '環境ファイルには書き込めません'
                };
              }
              
              // 操作を許可
              return { continue: true };
            }
          ]
        }
      ],
      PostToolUse: [
        {
          matcher: "Write|Edit",
          hooks: [
            async (input, toolUseId, { signal }) => {
              console.log(`ファイル変更: ${input.tool_response.filePath}`);
              // カスタムフォーマットや検証を実行
              return { continue: true };
            }
          ]
        }
      ]
    }
  }
})) {
  if (message.type === "result") console.log(message.result);
}

利用可能なフックイベント

  • PreToolUse: ツール実行前に実行。ツールをブロックしたりフィードバックを提供できます。
  • PostToolUse: ツール実行成功後に実行。
  • UserPromptSubmit: ユーザーがプロンプトを送信したときに実行。
  • SessionStart: セッション開始時に実行。
  • SessionEnd: セッション終了時に実行。
  • Stop: Claudeが応答を停止しようとするときに実行。
  • SubagentStop: サブエージェントが停止しようとするときに実行。
  • PreCompact: 会話の圧縮前に実行。
  • Notification: 通知が送信されるときに実行。

フック入力タイプ

各フックはイベントに基づいて型付けされた入力を受け取ります:

// PreToolUse入力
type PreToolUseHookInput = {
  hook_event_name: 'PreToolUse';
  session_id: string;
  transcript_path: string;
  cwd: string;
  permission_mode?: string;
  tool_name: string;
  tool_input: unknown;
}

// PostToolUse入力
type PostToolUseHookInput = {
  hook_event_name: 'PostToolUse';
  session_id: string;
  transcript_path: string;
  cwd: string;
  permission_mode?: string;
  tool_name: string;
  tool_input: unknown;
  tool_response: unknown;
}

フック出力

フックは実行フローを制御する出力を返します:

interface HookJSONOutput {
  // 実行を継続(デフォルト: true)
  continue?: boolean;
  
  // ユーザーへの出力を抑制
  suppressOutput?: boolean;
  
  // 停止理由(モデルに表示)
  stopReason?: string;
  
  // PreToolUseフック用の決定
  decision?: 'approve' | 'block';
  
  // 表示するシステムメッセージ
  systemMessage?: string;
  
  // フック固有の出力
  hookSpecificOutput?: {
    // PreToolUse用
    permissionDecision?: 'allow' | 'deny' | 'ask';
    permissionDecisionReason?: string;
    
    // UserPromptSubmitまたはPostToolUse用
    additionalContext?: string;
  };
}

実用的な例

ログと監視

const hooks = {
  PreToolUse: [
    {
      hooks: [
        async (input) => {
          // 全ツール使用をログ
          await logToMonitoring({
            event: 'tool_use',
            tool: input.tool_name,
            input: input.tool_input,
            session: input.session_id
          });
          
          return { continue: true };
        }
      ]
    }
  ]
};

ファイル操作の検証

const hooks = {
  PreToolUse: [
    {
      matcher: "Write|Edit",
      hooks: [
        async (input) => {
          const filePath = input.tool_input.file_path;
          
          // 機密ファイルをブロック
          const sensitivePatterns = ['.env', '.git/', 'secrets/', '*.key'];
          
          for (const pattern of sensitivePatterns) {
            if (filePath.includes(pattern)) {
              return {
                decision: 'block',
                stopReason: `${pattern}にマッチする機密ファイルは変更できません`
              };
            }
          }
          
          return { continue: true };
        }
      ]
    }
  ]
};

コードの自動フォーマット

import { exec } from 'child_process';
import { promisify } from 'util';

const execAsync = promisify(exec);

const hooks = {
  PostToolUse: [
    {
      matcher: "Write|Edit|MultiEdit",
      hooks: [
        async (input) => {
          const filePath = input.tool_response.filePath;
          
          // ファイルタイプに基づいて自動フォーマット
          if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
            await execAsync(`prettier --write "${filePath}"`);
          } else if (filePath.endsWith('.py')) {
            await execAsync(`black "${filePath}"`);
          }
          
          return { continue: true };
        }
      ]
    }
  ]
};

プロンプトの強化

const hooks = {
  UserPromptSubmit: [
    {
      hooks: [
        async (input) => {
          // プロンプトにコンテキストを追加
          const projectContext = await loadProjectContext();
          
          return {
            continue: true,
            hookSpecificOutput: {
              hookEventName: 'UserPromptSubmit',
              additionalContext: `プロジェクトコンテキスト: ${projectContext}`
            }
          };
        }
      ]
    }
  ]
};

カスタム圧縮指示

const hooks = {
  PreCompact: [
    {
      hooks: [
        async (input) => {
          const trigger = input.trigger; // 'manual'または'auto'
          
          return {
            continue: true,
            systemMessage: '実装の詳細とエラー解決の保持に焦点を当ててください'
          };
        }
      ]
    }
  ]
};

フック実行動作

  • 並列化: マッチするすべてのフックが並列で実行されます
  • タイムアウト: フックはオプションからのアボートシグナルを尊重します
  • エラーハンドリング: フックエラーはログに記録されますが実行は停止しません
  • マッチャー: 正規表現パターンをサポート(例:"Write|Edit"

canUseToolとフックの組み合わせ

canUseToolが許可制御を提供する一方で、フックはより広範なライフサイクル統合を提供します:

for await (const message of query({
  prompt: "機能を構築して",
  options: {
    // 細かい許可制御
    canUseTool: async (toolName, input) => {
      // ランタイム条件に基づいて入力を変更または拒否
      return { behavior: "allow", updatedInput: input };
    },
    
    // 監視と自動化のためのライフサイクルフック
    hooks: {
      PreToolUse: [
        {
          hooks: [
            async (input) => {
              // ログ、検証、または準備
              return { continue: true };
            }
          ]
        }
      ]
    }
  }
})) {
  // メッセージを処理
}

canUseToolによる許可制御

canUseToolコールバックは、ツール実行に対する細かい制御を提供します。各ツール使用前に呼び出され、ツール入力を許可、拒否、または変更できます:

type ToolPermissionResult = 
  | { behavior: "allow"; updatedInput?: any }
  | { behavior: "deny"; message?: string };

for await (const message of query({
  prompt: "ユーザー行動を分析してメトリクスを計算して",
  options: {
    mcpServers: {
      "analytics": analyticsServer
    },
    canUseTool: async (toolName: string, input: any) => {
      // どのツールが使用できるかを制御
      if (toolName.startsWith("mcp__analytics__")) {
        // 分析ツールの許可をチェック
        const hasPermission = await checkUserPermissions(toolName);
        
        return hasPermission
          ? { behavior: "allow", updatedInput: input }
          : { behavior: "deny", message: "権限が不十分です" };
      }
      
      // 特定のツールの入力を変更
      if (toolName === "Bash") {
        // 安全性チェックを追加またはコマンドを変更
        const safeInput = sanitizeBashCommand(input);
        return { behavior: "allow", updatedInput: safeInput };
      }
      
      // デフォルトで他のツールを許可
      return { behavior: "allow", updatedInput: input };
    }
  }
})) {
  if (message.type === "result") console.log(message.result);
}

canUseToolのユースケース

  • 許可管理: ツール実行を許可する前にユーザー許可をチェック
  • 入力検証: 実行前にツール入力を検証またはサニタイズ
  • レート制限: 高コストな操作にレート制限を実装
  • 監査ログ: コンプライアンスやデバッグのためのツール使用をログ
  • 動的許可: ランタイム条件に基づいてツールを有効/無効化
// 例: Webスクレイピングレート制限器
const rateLimits = new Map<string, { count: number; resetTime: number }>();

const canUseTool = async (toolName: string, input: any) => {
  // IP禁止とAPIクォータ問題を防ぐためWebスクレイピングをレート制限
  if (toolName === "WebFetch" || toolName === "WebSearch") {
    const now = Date.now();
    const limit = rateLimits.get(toolName) || { count: 0, resetTime: now + 60000 };
    
    // 毎分カウンターをリセット
    if (now > limit.resetTime) {
      limit.count = 0;
      limit.resetTime = now + 60000;
    }
    
    // 1分間に最大10リクエストを許可
    if (limit.count >= 10) {
      return { 
        behavior: "deny", 
        message: `レート制限を超過: 1分間に最大10回の${toolName}リクエスト。${Math.ceil((limit.resetTime - now) / 1000)}秒後にリセット` 
      };
    }
    
    limit.count++;
    rateLimits.set(toolName, limit);
    
    // 監視のためスクレイピング活動をログ
    console.log(`${toolName}リクエスト ${limit.count}/10 宛先: ${input.url || input.query}`);
  }
  
  // bashスクリプトでの偶発的な無限ループを防止
  if (toolName === "Bash" && input.command?.includes("while true")) {
    return { 
      behavior: "deny", 
      message: "無限ループは許可されていません" 
    };
  }
  
  return { behavior: "allow", updatedInput: input };
};

出力形式

テキスト出力(デフォルト)

// デフォルトのテキスト出力
for await (const message of query({
  prompt: "ファイルsrc/components/Header.tsxを説明して"
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
    // 出力: これは...を表示するReactコンポーネントです
  }
}

JSON出力

// JSON風アクセスのため全メッセージを収集
const messages = [];
for await (const message of query({
  prompt: "データレイヤーはどのように動作しますか?"
})) {
  messages.push(message);
}

// メタデータ付きの結果メッセージにアクセス
const result = messages.find(m => m.type === "result" && message.subtype === "success");
console.log({
  result: result.result,
  cost: result.total_cost_usd,
  duration: result.duration_ms
});

入力形式

// 直接プロンプト
for await (const message of query({
  prompt: "このコードを説明して"
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// 変数から
const userInput = "このコードを説明して";
for await (const message of query({ prompt: userInput })) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

エージェント統合例

SREインシデント対応エージェント

import { query } from "@anthropic-ai/claude-code";

// 自動インシデント対応エージェント
async function investigateIncident(
  incidentDescription: string,
  severity = "medium"
) {
  const messages = [];

  for await (const message of query({
    prompt: `インシデント: ${incidentDescription} (重要度: ${severity})`,
    options: {
      appendSystemPrompt: "あなたはSREの専門家です。問題を診断し、影響を評価し、即座の対応項目を提供してください。",
      maxTurns: 6,
      allowedTools: ["Bash", "Read", "WebSearch", "mcp__datadog"],
      mcpConfig: "monitoring-tools.json"
    }
  })) {
    messages.push(message);
  }

  return messages.find(m => m.type === "result" && message.subtype === "success");
}

// 使用方法
const result = await investigateIncident("決済APIが500エラーを返している", "high");
console.log(result.result);

自動セキュリティレビュー

import { query } from "@anthropic-ai/claude-code";
import { execSync } from "child_process";

async function auditPR(prNumber: number) {
  // PR差分を取得
  const prDiff = execSync(`gh pr diff ${prNumber}`, { encoding: 'utf8' });

  const messages = [];
  for await (const message of query({
    prompt: prDiff,
    options: {
      appendSystemPrompt: "あなたはセキュリティエンジニアです。このPRを脆弱性、安全でないパターン、コンプライアンス問題についてレビューしてください。",
      maxTurns: 3,
      allowedTools: ["Read", "Grep", "WebSearch"]
    }
  })) {
    messages.push(message);
  }

  return messages.find(m => m.type === "result" && message.subtype === "success");
}

// 使用方法
const report = await auditPR(123);
console.log(JSON.stringify(report, null, 2));

マルチターン法務アシスタント

import { query } from "@anthropic-ai/claude-code";

async function legalReview() {
  // 法務レビューセッションを開始
  let sessionId: string;

  for await (const message of query({
    prompt: "法務レビューセッションを開始",
    options: { maxTurns: 1 }
  })) {
    if (message.type === "system" && message.subtype === "init") {
      sessionId = message.session_id;
    }
  }

  // 同じセッションを使用したマルチステップレビュー
  const steps = [
    "contract.pdfの責任条項をレビュー",
    "GDPR要件への準拠をチェック",
    "リスクのエグゼクティブサマリーを生成"
  ];

  for (const step of steps) {
    for await (const message of query({
      prompt: step,
      options: { resume: sessionId, maxTurns: 2 }
    })) {
      if (message.type === "result" && message.subtype === "success") {
        console.log(`ステップ: ${step}`);
        console.log(message.result);
      }
    }
  }
}

メッセージスキーマ

JSON APIから返されるメッセージは、以下のスキーマに従って厳密に型付けされています:

type SDKMessage =
  // アシスタントメッセージ
  | {
      type: "assistant";
      uuid: string;
      session_id: string;
      message: Message; // Anthropic SDKから
      parent_tool_use_id: string | null;
    }

  // ユーザーメッセージ(入力)
  | {
      type: "user";
      uuid?: string;
      session_id: string;
      message: MessageParam; // Anthropic SDKから
      parent_tool_use_id: string | null;
    }

  // ユーザーメッセージ(出力/リプレイ、必須UUID付き)
  | {
      type: "user";
      uuid: string;
      session_id: string;
      message: MessageParam; // Anthropic SDKから
      parent_tool_use_id: string | null;
    }

  // 成功時の最後のメッセージとして発行
  | {
      type: "result";
      subtype: "success";
      uuid: UUID;
      session_id: string;
      duration_ms: number;
      duration_api_ms: number;
      is_error: boolean;
      num_turns: number;
      result: string;
      total_cost_usd: number;
      usage: Usage;
      permission_denials: SDKPermissionDenial[];
    }

  // エラーまたは最大ターン時の最後のメッセージとして発行
  | {
      type: "result";
      subtype: "error_max_turns" | "error_during_execution";
      uuid: UUID;
      session_id: string;
      duration_ms: number;
      duration_api_ms: number;
      is_error: boolean;
      num_turns: number;
      total_cost_usd: number;
      usage: Usage;
      permission_denials: SDKPermissionDenial[];
    }

  // 会話開始時の最初のメッセージとして発行
  | {
      type: "system";
      subtype: "init";
      uuid: UUID;
      session_id: string;
      apiKeySource: "user" | "project" | "org" | "temporary";
      cwd: string;
      tools: string[];
      mcp_servers: {
        name: string;
        status: string;
      }[];
      model: string;
      permissionMode: "default" | "acceptEdits" | "bypassPermissions" | "plan";
      slash_commands: string[];
      output_style: string;
    };

  type SDKPermissionDenial = {
    tool_name: string;
    tool_use_id: string;
    tool_input: Record<string, unknown>;
  }

追加のサポート型:

MessageMessageParamUsage型はAnthropic TypeScript SDKで利用可能です。

関連リソース