Loading...
    • 開発者ガイド
    • API リファレンス
    • MCP
    • リソース
    • リリースノート
    Search...
    ⌘K
    はじめに
    Claude の紹介クイックスタート
    モデルと料金
    モデル概要モデルの選び方Claude 4.6 の新機能移行ガイドモデルの廃止料金
    Claude で構築する
    機能概要Messages API の使用停止理由の処理プロンプトのベストプラクティス
    モデルの機能
    拡張思考適応型思考エフォート高速モード(リサーチプレビュー)構造化出力引用メッセージのストリーミングバッチ処理PDF サポート検索結果多言語サポートエンベディングビジョン
    ツール
    概要ツール使用の実装方法Web 検索ツールWeb フェッチツールコード実行ツールメモリツールBash ツールコンピュータ使用ツールテキストエディタツール
    ツールインフラストラクチャ
    ツール検索プログラムによるツール呼び出しきめ細かいツールストリーミング
    コンテキスト管理
    コンテキストウィンドウコンパクションコンテキスト編集プロンプトキャッシングトークンカウント
    ファイルとアセット
    Files API
    Agent Skills
    概要クイックスタートベストプラクティスエンタープライズ向け SkillsAPI での Skills の使用
    Agent SDK
    概要クイックスタートTypeScript SDKTypeScript V2(プレビュー)Python SDK移行ガイド
    ストリーミング入力リアルタイムでレスポンスをストリーミング停止理由の処理権限の処理ユーザー承認と入力フックによる実行制御セッション管理ファイルチェックポイントSDK での構造化出力Agent SDK のホスティングAI エージェントの安全なデプロイシステムプロンプトの変更SDK での MCPカスタムツールSDK でのサブエージェントSDK でのスラッシュコマンドSDK での Agent Skillsコストと使用量の追跡Todo リストSDK でのプラグイン
    API での MCP
    MCP コネクタリモート MCP サーバー
    サードパーティプラットフォームでの Claude
    Amazon BedrockMicrosoft FoundryVertex AI
    プロンプトエンジニアリング
    概要プロンプトジェネレータープロンプトテンプレートの使用プロンプト改善ツール明確かつ直接的に例を使う(マルチショットプロンプティング)Claude に考えさせる(CoT)XML タグを使うClaude に役割を与える(システムプロンプト)複雑なプロンプトを連鎖させる長文コンテキストのヒント拡張思考のヒント
    テストと評価
    成功基準の定義テストケースの開発評価ツールの使用レイテンシの削減
    ガードレールの強化
    ハルシネーションの削減出力の一貫性を高めるジェイルブレイクの軽減ストリーミング拒否プロンプト漏洩の削減Claude をキャラクターに保つ
    管理とモニタリング
    Admin API 概要データレジデンシーワークスペース使用量とコスト APIClaude Code Analytics APIゼロデータリテンション
    Console
    Log in
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...

    Solutions

    • AI agents
    • Code modernization
    • Coding
    • Customer support
    • Education
    • Financial services
    • Government
    • Life sciences

    Partners

    • Amazon Bedrock
    • Google Cloud's Vertex AI

    Learn

    • Blog
    • Catalog
    • Courses
    • Use cases
    • Connectors
    • Customer stories
    • Engineering at Anthropic
    • Events
    • Powered by Claude
    • Service partners
    • Startups program

    Company

    • Anthropic
    • Careers
    • Economic Futures
    • Research
    • News
    • Responsible Scaling Policy
    • Security and compliance
    • Transparency

    Learn

    • Blog
    • Catalog
    • Courses
    • Use cases
    • Connectors
    • Customer stories
    • Engineering at Anthropic
    • Events
    • Powered by Claude
    • Service partners
    • Startups program

    Help and security

    • Availability
    • Status
    • Support
    • Discord

    Terms and policies

    • Privacy policy
    • Responsible disclosure policy
    • Terms of service: Commercial
    • Terms of service: Consumer
    • Usage policy
    ガイド

    承認とユーザー入力の処理

    Claudeの承認リクエストや確認質問をユーザーに表示し、その判断をSDKに返します。

    Was this page helpful?

    • Claudeが入力を必要とするタイミングの検出

    タスクの作業中、Claudeはユーザーに確認が必要になることがあります。ファイルを削除する前に許可が必要だったり、新しいプロジェクトでどのデータベースを使用するか確認が必要だったりします。アプリケーションはこれらのリクエストをユーザーに表示し、Claudeがユーザーの入力を受けて作業を続行できるようにする必要があります。

    Claudeがユーザー入力をリクエストするのは2つの状況です:ツールの使用許可が必要な場合(ファイルの削除やコマンドの実行など)と、確認質問がある場合(AskUserQuestionツール経由)です。どちらもcanUseToolコールバックをトリガーし、レスポンスを返すまで実行が一時停止します。これは、Claudeが処理を完了して次のメッセージを待つ通常の会話ターンとは異なります。

    確認質問の場合、Claudeが質問と選択肢を生成します。あなたの役割は、それらをユーザーに提示し、選択結果を返すことです。このフローに独自の質問を追加することはできません。ユーザーに何か質問する必要がある場合は、アプリケーションロジックで別途行ってください。

    このガイドでは、各タイプのリクエストを検出し、適切に応答する方法を説明します。

    Claudeが入力を必要とするタイミングの検出

    クエリオプションにcanUseToolコールバックを渡します。コールバックはClaudeがユーザー入力を必要とするたびに発火し、ツール名と入力を引数として受け取ります:

    async def handle_tool_request(tool_name, input_data, context):
        # ユーザーにプロンプトを表示し、許可または拒否を返す
        ...
    
    options = ClaudeAgentOptions(can_use_tool=handle_tool_request)

    コールバックは2つのケースで発火します:

    1. ツールが承認を必要とする場合:Claudeがパーミッションルールやモードで自動承認されていないツールを使用しようとしています。tool_nameでツールを確認します(例:"Bash"、"Write")。
    2. Claudeが質問する場合:ClaudeがAskUserQuestionツールを呼び出します。tool_name == "AskUserQuestion"かどうかを確認して、異なる処理を行います。tools配列を指定する場合は、これが機能するようにAskUserQuestionを含めてください。詳細は確認質問の処理を参照してください。

    ユーザーにプロンプトを表示せずにツールを自動的に許可または拒否するには、代わりにフックを使用してください。フックはcanUseToolの前に実行され、独自のロジックに基づいてリクエストを許可、拒否、または変更できます。また、PermissionRequestフックを使用して、Claudeが承認を待っているときに外部通知(Slack、メール、プッシュ通知)を送信することもできます。

    ツール承認リクエストの処理

    クエリオプションにcanUseToolコールバックを渡すと、Claudeが自動承認されていないツールを使用しようとしたときに発火します。コールバックは2つの引数を受け取ります:

    引数説明
    toolNameClaudeが使用しようとしているツールの名前(例:"Bash"、"Write"、"Edit")
    inputClaudeがツールに渡すパラメータ。内容はツールによって異なります。

    inputオブジェクトにはツール固有のパラメータが含まれます。一般的な例:

    ツール入力フィールド
    Bashcommand、description、timeout
    Writefile_path、content
    Editfile_path、old_string、new_string
    Readfile_path、offset、limit

    完全な入力スキーマについてはSDKリファレンスを参照してください:Python | TypeScript。

    この情報をユーザーに表示して、アクションを許可するか拒否するかを判断してもらい、適切なレスポンスを返すことができます。

    次の例では、Claudeにテストファイルの作成と削除を依頼します。Claudeが各操作を試みると、コールバックがツールリクエストをターミナルに表示し、y/nの承認を求めます。

    Pythonでは、can_use_toolはストリーミングモードと、ストリームを開いたままにするために{"continue_": True}を返すPreToolUseフックが必要です。このフックがないと、パーミッションコールバックが呼び出される前にストリームが閉じてしまいます。

    この例では、y以外の入力はすべて拒否として扱うy/nフローを使用しています。実際には、ユーザーがリクエストを変更したり、フィードバックを提供したり、Claudeを完全にリダイレクトしたりできる、より豊富なUIを構築することもあります。応答方法のすべてについては、ツールリクエストへの応答を参照してください。

    ツールリクエストへの応答

    コールバックは2つのレスポンスタイプのいずれかを返します:

    レスポンスPythonTypeScript
    許可PermissionResultAllow(updated_input=...){ behavior: "allow", updatedInput }
    拒否PermissionResultDeny(message=...){ behavior: "deny", message }

    許可する場合は、ツール入力(元のまたは変更済み)を渡します。拒否する場合は、理由を説明するメッセージを提供します。Claudeはこのメッセージを確認し、アプローチを調整する場合があります。

    from claude_agent_sdk.types import PermissionResultAllow, PermissionResultDeny
    
    # ツールの実行を許可
    return PermissionResultAllow(updated_input=input_data)
    
    # ツールをブロック
    return PermissionResultDeny(message="User rejected this action")

    許可または拒否に加えて、ツールの入力を変更したり、Claudeがアプローチを調整するのに役立つコンテキストを提供したりできます:

    • 承認:Claudeがリクエストした通りにツールを実行させる
    • 変更付き承認:実行前に入力を変更する(例:パスのサニタイズ、制約の追加)
    • 拒否:ツールをブロックし、Claudeに理由を伝える
    • 代替案の提案:ブロックするが、ユーザーが望むものに向けてClaudeを導く
    • 完全なリダイレクト:ストリーミング入力を使用して、Claudeにまったく新しい指示を送る

    確認質問の処理

    Claudeが複数の有効なアプローチがあるタスクでより多くの方向性を必要とする場合、AskUserQuestionツールを呼び出します。これにより、toolNameがAskUserQuestionに設定された状態でcanUseToolコールバックがトリガーされます。入力にはClaudeの質問が多肢選択式のオプションとして含まれており、ユーザーに表示して選択結果を返します。

    確認質問はplanモードで特に一般的です。このモードでは、Claudeがコードベースを探索し、プランを提案する前に質問します。これにより、planモードは、Claudeに変更を加える前に要件を収集させたいインタラクティブなワークフローに最適です。

    以下の手順で確認質問を処理します:

    質問フォーマット

    入力にはClaudeが生成した質問がquestions配列に含まれています。各質問には以下のフィールドがあります:

    フィールド説明
    question表示する完全な質問テキスト
    header質問の短いラベル(最大12文字)
    options2〜4個の選択肢の配列、各選択肢にlabelとdescriptionがある
    multiSelecttrueの場合、ユーザーは複数のオプションを選択できる

    受け取る構造の例:

    {
      "questions": [
        {
          "question": "How should I format the output?",
          "header": "Format",
          "options": [
            { "label": "Summary", "description": "Brief overview of key points" },
            { "label": "Detailed", "description": "Full explanation with examples" }
          ],
          "multiSelect": false
        }
      ]
    }

    レスポンスフォーマット

    各質問のquestionフィールドを選択されたオプションのlabelにマッピングするanswersオブジェクトを返します:

    フィールド説明
    questions元の質問配列をそのまま渡す(ツール処理に必要)
    answersキーが質問テキスト、値が選択されたラベルであるオブジェクト

    複数選択の質問の場合、複数のラベルを", "で結合します。自由テキスト入力の場合、ユーザーのカスタムテキストを直接使用します。

    {
      "questions": [...],
      "answers": {
        "How should I format the output?": "Summary",
        "Which sections should I include?": "Introduction, Conclusion"
      }
    }

    自由テキスト入力のサポート

    Claudeの定義済みオプションがユーザーの望むものをカバーしない場合があります。ユーザーが独自の回答を入力できるようにするには:

    • Claudeのオプションの後にテキスト入力を受け付ける追加の「その他」選択肢を表示する
    • 回答値としてユーザーのカスタムテキストを使用する(「その他」という単語ではなく)

    完全な実装については、以下の完全な例を参照してください。

    完全な例

    Claudeは、処理を進めるためにユーザー入力が必要な場合に確認質問をします。例えば、モバイルアプリの技術スタックの決定を手伝うよう依頼された場合、Claudeはクロスプラットフォームかネイティブか、バックエンドの好み、ターゲットプラットフォームについて質問するかもしれません。これらの質問により、Claudeは推測するのではなく、ユーザーの好みに合った決定を下すことができます。

    この例では、ターミナルアプリケーションでこれらの質問を処理します。各ステップで何が起こるかを以下に示します:

    1. リクエストのルーティング:canUseToolコールバックがツール名が"AskUserQuestion"かどうかを確認し、専用のハンドラーにルーティングする
    2. 質問の表示:ハンドラーがquestions配列をループし、各質問を番号付きオプションとともに表示する
    3. 入力の収集:ユーザーは番号を入力してオプションを選択するか、自由テキストを直接入力できる(例:「jquery」、「i don't know」)
    4. 回答のマッピング:コードが入力が数値か(オプションのラベルを使用)自由テキストか(テキストを直接使用)を確認する
    5. Claudeへの返却:レスポンスには元のquestions配列とanswersマッピングの両方が含まれる

    制限事項

    • サブエージェント:AskUserQuestionは現在、Taskツール経由で生成されたサブエージェントでは利用できません
    • 質問の制限:各AskUserQuestion呼び出しは、それぞれ2〜4個のオプションを持つ1〜4個の質問をサポートします

    ユーザー入力を取得するその他の方法

    canUseToolコールバックとAskUserQuestionツールはほとんどの承認と確認のシナリオをカバーしますが、SDKにはユーザーから入力を取得する他の方法もあります:

    ストリーミング入力

    以下の場合にストリーミング入力を使用します:

    • タスク中にエージェントを中断する:Claudeが作業中にキャンセルシグナルを送信したり、方向を変更したりする
    • 追加のコンテキストを提供する:Claudeが質問するのを待たずに、必要な情報を追加する
    • チャットインターフェースを構築する:長時間実行される操作中にユーザーがフォローアップメッセージを送信できるようにする

    ストリーミング入力は、承認チェックポイントだけでなく、実行全体を通じてユーザーがエージェントとやり取りする会話型UIに最適です。

    カスタムツール

    以下の場合にカスタムツールを使用します:

    • 構造化された入力を収集する:AskUserQuestionの多肢選択形式を超えるフォーム、ウィザード、またはマルチステップワークフローを構築する
    • 外部承認システムと統合する:既存のチケット、ワークフロー、または承認プラットフォームに接続する
    • ドメイン固有のインタラクションを実装する:コードレビューインターフェースやデプロイメントチェックリストなど、アプリケーションのニーズに合わせたツールを作成する

    カスタムツールはインタラクションを完全に制御できますが、組み込みのcanUseToolコールバックを使用するよりも多くの実装作業が必要です。

    関連リソース

    • パーミッションの設定:パーミッションモードとルールの設定
    • フックによる実行制御:エージェントライフサイクルの重要なポイントでカスタムコードを実行
    • TypeScript SDKリファレンス:完全なcanUseTool APIドキュメント
    import asyncio
    
    from claude_agent_sdk import ClaudeAgentOptions, query
    from claude_agent_sdk.types import (
        HookMatcher,
        PermissionResultAllow,
        PermissionResultDeny,
        ToolPermissionContext,
    )
    
    
    async def can_use_tool(
        tool_name: str, input_data: dict, context: ToolPermissionContext
    ) -> PermissionResultAllow | PermissionResultDeny:
        # ツールリクエストを表示
        print(f"\nTool: {tool_name}")
        if tool_name == "Bash":
            print(f"Command: {input_data.get('command')}")
            if input_data.get("description"):
                print(f"Description: {input_data.get('description')}")
        else:
            print(f"Input: {input_data}")
    
        # ユーザーの承認を取得
        response = input("Allow this action? (y/n): ")
    
        # ユーザーの応答に基づいて許可または拒否を返す
        if response.lower() == "y":
            # 許可:ツールは元の(または変更された)入力で実行される
            return PermissionResultAllow(updated_input=input_data)
        else:
            # 拒否:ツールは実行されず、Claudeにメッセージが表示される
            return PermissionResultDeny(message="User denied this action")
    
    
    # 必要な回避策:ダミーフックがcan_use_toolのためにストリームを開いたままにする
    async def dummy_hook(input_data, tool_use_id, context):
        return {"continue_": True}
    
    
    async def prompt_stream():
        yield {
            "type": "user",
            "message": {
                "role": "user",
                "content": "Create a test file in /tmp and then delete it",
            },
        }
    
    
    async def main():
        async for message in query(
            prompt=prompt_stream(),
            options=ClaudeAgentOptions(
                can_use_tool=can_use_tool,
                hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},
            ),
        ):
            if hasattr(message, "result"):
                print(message.result)
    
    
    asyncio.run(main())
    1. 1

      canUseToolコールバックを渡す

      クエリオプションにcanUseToolコールバックを渡します。デフォルトでは、AskUserQuestionは利用可能です。Claudeの機能を制限するためにtools配列を指定する場合(例えば、Read、Glob、Grepのみの読み取り専用エージェント)、その配列にAskUserQuestionを含めてください。そうしないと、Claudeは確認質問をすることができません:

      async for message in query(
          prompt="Analyze this codebase",
          options=ClaudeAgentOptions(
              # ツールリストにAskUserQuestionを含める
              tools=["Read", "Glob", "Grep", "AskUserQuestion"],
              can_use_tool=can_use_tool,
          ),
      ):
          # ...
    2. 2

      AskUserQuestionを検出する

      コールバック内で、toolNameがAskUserQuestionと等しいかどうかを確認し、他のツールとは異なる処理を行います:

      async def can_use_tool(tool_name: str, input_data: dict, context):
          if tool_name == "AskUserQuestion":
              # ユーザーから回答を収集する実装
              return await handle_clarifying_questions(input_data)
          # 他のツールは通常通り処理
          return await prompt_for_approval(tool_name, input_data)
    3. 3

      質問入力を解析する

      入力にはClaudeの質問がquestions配列に含まれています。各質問にはquestion(表示するテキスト)、options(選択肢)、multiSelect(複数選択が許可されるかどうか)があります:

      {
        "questions": [
          {
            "question": "How should I format the output?",
            "header": "Format",
            "options": [
              { "label": "Summary", "description": "Brief overview" },
              { "label": "Detailed", "description": "Full explanation" }
            ],
            "multiSelect": false
          },
          {
            "question": "Which sections should I include?",
            "header": "Sections",
            "options": [
              { "label": "Introduction", "description": "Opening context" },
              { "label": "Conclusion", "description": "Final summary" }
            ],
            "multiSelect": true
          }
        ]
      }

      完全なフィールドの説明については質問フォーマットを参照してください。

    4. 4

      ユーザーから回答を収集する

      質問をユーザーに提示し、選択を収集します。方法はアプリケーションによって異なります:ターミナルプロンプト、Webフォーム、モバイルダイアログなど。

    5. 5

      回答をClaudeに返す

      answersオブジェクトを、各キーがquestionテキストで各値が選択されたオプションのlabelであるレコードとして構築します:

      質問オブジェクトから使用方法
      questionフィールド(例:"How should I format the output?")キー
      選択されたオプションのlabelフィールド(例:"Summary")値

      複数選択の質問の場合、複数のラベルを", "で結合します。自由テキスト入力をサポートする場合は、ユーザーのカスタムテキストを値として使用します。

      return PermissionResultAllow(
          updated_input={
              "questions": input_data.get("questions", []),
              "answers": {
                  "How should I format the output?": "Summary",
                  "Which sections should I include?": "Introduction, Conclusion"
              }
          }
      )
    import asyncio
    
    from claude_agent_sdk import ClaudeAgentOptions, query
    from claude_agent_sdk.types import HookMatcher, PermissionResultAllow
    
    
    def parse_response(response: str, options: list) -> str:
        """ユーザー入力をオプション番号またはフリーテキストとして解析する。"""
        try:
            indices = [int(s.strip()) - 1 for s in response.split(",")]
            labels = [options[i]["label"] for i in indices if 0 <= i < len(options)]
            return ", ".join(labels) if labels else response
        except ValueError:
            return response
    
    
    async def handle_ask_user_question(input_data: dict) -> PermissionResultAllow:
        """Claudeの質問を表示し、ユーザーの回答を収集する。"""
        answers = {}
    
        for q in input_data.get("questions", []):
            print(f"\n{q['header']}: {q['question']}")
    
            options = q["options"]
            for i, opt in enumerate(options):
                print(f"  {i + 1}. {opt['label']} - {opt['description']}")
            if q.get("multiSelect"):
                print("  (Enter numbers separated by commas, or type your own answer)")
            else:
                print("  (Enter a number, or type your own answer)")
    
            response = input("Your choice: ").strip()
            answers[q["question"]] = parse_response(response, options)
    
        return PermissionResultAllow(
            updated_input={
                "questions": input_data.get("questions", []),
                "answers": answers,
            }
        )
    
    
    async def can_use_tool(tool_name: str, input_data: dict, context) -> PermissionResultAllow:
        # AskUserQuestionを質問ハンドラーにルーティング
        if tool_name == "AskUserQuestion":
            return await handle_ask_user_question(input_data)
        # この例では他のツールを自動承認
        return PermissionResultAllow(updated_input=input_data)
    
    
    async def prompt_stream():
        yield {
            "type": "user",
            "message": {"role": "user", "content": "Help me decide on the tech stack for a new mobile app"},
        }
    
    
    # 必要な回避策:ダミーフックがcan_use_toolのためにストリームを開いたままにする
    async def dummy_hook(input_data, tool_use_id, context):
        return {"continue_": True}
    
    
    async def main():
        async for message in query(
            prompt=prompt_stream(),
            options=ClaudeAgentOptions(
                can_use_tool=can_use_tool,
                hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},
            ),
        ):
            if hasattr(message, "result"):
                print(message.result)
    
    
    asyncio.run(main())