Azure OpenAI Responses API でシェル ツールを使用する

シェル ツールは、 Responses API 呼び出しの一部として、完全なターミナル環境でコマンドを実行します。 スクリプトの実行、ファイルの操作、プログラムの実行に使用します。 シェル ツールでは、次の 2 つの実行モードがサポートされています。

  • Hosted shell: Azure OpenAI は、要求のサンドボックス コンテナーをプロビジョニングおよび管理します。
  • ローカル シェル: モデルの shell_call アクションを独自のランタイムで実行し、結果を返します。

シェル ツールには、Responses API 経由でのみアクセスできます。 Chat Completions API では使用できません。

Important

任意のシェル コマンドを実行すると、危険な場合があります。 常にサンドボックスを実行し、可能な場合は許可リストまたはブロック リストを適用し、監査用にツール アクティビティをログに記録します。

Note

シェル ツールには、それをサポートする Azure OpenAI API バージョンと、Responses API をサポートするモデル デプロイが必要です。 運用環境にデプロイする前に、ターゲット API バージョンのサポートを確認します。

前提条件

  • Responses API とシェル ツールをサポートする、デプロイされた Azure OpenAI モデル。
  • 認証方法:
    • API キー、または
    • Microsoft Entra ID。
  • 言語のクライアント ライブラリをインストールします。
    • Python: pip install openai azure-identity
    • JavaScript/TypeScript: npm install openai @azure/identity
    • Java: com.openai:openai-java と com.azure:azure-identity をプロジェクトに追加します。
  • REST の例では、AZURE_OPENAI_API_KEY (API キー フロー) または AZURE_OPENAI_AUTH_TOKEN (Microsoft Entra ID フロー) を設定します。

ホストされたシェルを使用して最初のコマンドを実行する

ホストシェルは、最も早く開始する方法です。 環境を container_auto に設定して、Azure OpenAI が要求のコンテナーをプロビジョニングおよび管理できるようにします。 モデルは、プロンプトに基づいてツールを呼び出すかどうかを決定します。

次の例では、 gpt-5.5 を独自のモデル デプロイの名前に置き換えます。

from openai import OpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider

endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/"
token_provider = get_bearer_token_provider(
    DefaultAzureCredential(), "https://ai.azure.com/.default"
)

# Create the client against the Azure OpenAI v1 endpoint.
openai = OpenAI(base_url=endpoint, api_key=token_provider)

# Run a command in an auto-provisioned hosted container.
response = openai.responses.create(
    model="gpt-5.5",
    tools=[{"type": "shell", "environment": {"type": "container_auto"}}],
    input="Run: python --version && echo 'hello from the shell'",
)

print(response.output_text)

Tip

これらの例では、Microsoft Entra IDを使用します。 代わりに API キーを使用するには、api_keyをキー値 (Pythonと JavaScript) に設定し、クライアントのビルド時に AzureApiKeyCredential を渡すか (Java)、または api-key (REST) ではなく Authorization: Bearer ヘッダーを送信します。

リファレンス: Azure OpenAI Responses API を使用する | OpenAI Python SDK | OpenAI Node SDK | OpenAI Java SDK

ホストされるランタイムの詳細

ホストされるコンテナーは、要求またはコンテナー セッションごとにマネージド Linux 環境を提供します。

  • ランタイムは Debian 12 に基づいており、時間の経過と伴って変化する可能性があります。
  • デフォルトの作業ディレクトリは /mnt/data です。 このディレクトリは常に存在し、ユーザーがダウンロードできる成果物のサポートされているパスです。
  • Python 3.11 がプレインストールされています。
  • ホストされたシェルは対話型の TTY セッションをサポートせず、コマンドは sudoで実行されません。
  • ホストされているコンテナーには、送信ネットワーク アクセスがありません。

ワークフローで必要なときに、コンテナー内でサービスを実行できます。

要求間でコンテナーを再利用する

反復ワークフローの場合は、コンテナーを 1 回作成し、後の Responses API 呼び出しでそれを参照します。 コンテナーは、アクティブな間、要求間でファイルと状態を保持します。

最初に、コンテナーを作成します。

# Create a reusable container.
container = openai.containers.create(
    name="analysis-container",
    expires_after={"anchor": "last_active_at", "minutes": 20},
)

print(container.id)

次に、シェル要求で ID によってコンテナーを参照します。

# Reference the existing container in a shell request.
response = openai.responses.create(
    model="gpt-5.5",
    tools=[{
        "type": "shell",
        "environment": {
            "type": "container_reference",
            "container_id": container.id,
        },
    }],
    input="List files in the container and show disk usage.",
)

print(response.output_text)

同じコンテナーで順番に作業を続行するには、前の応答から同じ container_id と previous_response_id を渡します。

ローカル シェル モードでコマンドを実行する

ローカル シェル モードでは、ホストされたコンテナーではなく、独自のランタイムでモデルのコマンドを実行します。 実行環境、ファイルシステム アクセス、または既存の内部ツールを完全に制御する必要がある場合は、このモードを使用します。

環境を localに設定します。 モデルは、実行するコマンド shell_call 説明する項目を返します。

response = openai.responses.create(
    model="gpt-5.5",
    instructions="The local shell environment is on Linux.",
    input="Find the largest PDF file in the current directory.",
    tools=[{"type": "shell", "environment": {"type": "local"}}],
)

print(response.model_dump_json(indent=2))

shell_call項目を受け取ったら、要求されたコマンドを実行し、出力をキャプチャして、次の要求でshell_call_output結果を返します。 次の Executor は、 stdout、 stderr、終了結果をキャプチャし、タイムアウトを処理します。

import subprocess
from dataclasses import dataclass

@dataclass
class CmdResult:
    stdout: str
    stderr: str
    exit_code: int | None
    timed_out: bool

def run_command(cmd: str, timeout: float = 60) -> CmdResult:
    process = subprocess.Popen(
        cmd, shell=True, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, text=True,
    )
    try:
        out, err = process.communicate(timeout=timeout)
        return CmdResult(out, err, process.returncode, False)
    except subprocess.TimeoutExpired:
        process.kill()
        out, err = process.communicate()
        return CmdResult(out, err, process.returncode, True)

リファレンス: Azure OpenAI Responses API

応答内のシェル出力

ホステッド シェルとローカル シェルでは、同じ出力項目の種類が使用されます。 各シェル実行は、項目のペアによって表されます。

  • shell_call: モデルが要求するコマンド。
  • shell_call_output: コマンドの出力と終了の結果。

モデルは、 shell_call 項目を含むコマンドを要求します。

{
  "type": "shell_call",
  "call_id": "call_<id>",
  "action": {
    "commands": ["ls -l"],
    "timeout_ms": 120000,
    "max_output_length": 4096
  },
  "status": "in_progress"
}

shell_call_output項目を含む結果を返します。

{
  "type": "shell_call_output",
  "call_id": "call_<id>",
  "max_output_length": 4096,
  "output": [
    {
      "stdout": "...",
      "stderr": "",
      "outcome": { "type": "exit", "exit_code": 0 }
    }
  ]
}

shell_callにmax_output_lengthが含まれている場合は、shell_call_outputに同じ値を含めます。 コマンドが実行タイムアウトを超えた場合は、 timeout 結果を返し、キャプチャした部分的な出力を含めます。

成果物をダウンロードする

ホストされたシェルは、ダウンロード可能なファイルを生成できます。 成果物を取得するには、 /mnt/dataの下に書き込み、コード インタープリターで使用されるのと同じコンテナーとファイル API を使用してダウンロードします。

データの保持とコンテナーのライフサイクル

  • ホストされたコンテナー セッションは、アイドル時間が 20 分経過すると終了します。
  • ホストされているコンテナーは、作成されてから 1 時間後に削除されます。 コンテナーに格納されているすべてのデータは、コンテナーが削除されると削除されます。

ホストされたコンテナーは、コンテナーがアクティブな間に、一時的なアプリケーションの状態をコンテナー ファイル システム (エフェメラル ブロック ストレージによってサポート) に書き込む場合があります。 コンテナー データは、コンテナーの有効期限が切れた場合、またはコンテナーを削除した場合に削除されます。

一般的なエラーの処理

  • タイムアウト: コマンドが実行タイムアウトを超えた場合は、 timeout 結果を返し、キャプチャした部分的な出力を含めます。
  • 切り捨てられた出力: max_output_length が shell_callに存在する場合は、 shell_call_outputに同じ値を設定します。
  • 対話型コマンド: シェル ツールの実行は非対話型です。 入力を求めるコマンドに依存しないでください。
  • ゼロ以外の出口: ゼロ以外の出口からの出力を保持して、モデルが復旧ステップについて推論できるようにします。