Usare lo strumento shell con l'API Azure OpenAI Responses

Lo strumento shell esegue comandi in un ambiente terminale completo come parte di una chiamata API Risposte . Usarlo per eseguire script, usare file ed eseguire programmi. Lo strumento shell supporta due modalità di esecuzione:

  • shell Hosted: Azure OpenAI effettua il provisioning e gestisce un contenitore in modalità sandbox per la richiesta.
  • Shell locale: si eseguono le azioni del shell_call modello nel proprio runtime e si restituiscono i risultati.

È possibile accedere allo strumento shell solo tramite l'API Risposte. Non è disponibile tramite l'API Chat Completions.

Importante

L'esecuzione di comandi arbitrari della shell può essere pericolosa. Eseguire sempre in una sandbox, applicare liste di elementi consentiti o liste di blocco ove possibile e registrare l'attività dello strumento a fini di audit.

Note

Lo strumento shell richiede una versione dell'API OpenAI Azure che la supporta e una distribuzione del modello che supporta l'API Risposte. Verificare il supporto per la versione dell'API di destinazione prima di eseguire la distribuzione nell'ambiente di produzione.

Prerequisiti

  • Un modello di Azure OpenAI distribuito che supporta l'API Responses e lo strumento shell.
  • Metodo di autenticazione:
    • Chiave API o
    • Microsoft Entra ID.
  • Installa la libreria client per il tuo linguaggio:
    • Python: pip install openai azure-identity
    • JavaScript/TypeScript: npm install openai @azure/identity
    • Java: aggiungere com.openai:openai-java e com.azure:azure-identity al progetto.
  • Per esempi REST, impostare AZURE_OPENAI_API_KEY (flusso di chiave API) o AZURE_OPENAI_AUTH_TOKEN (flusso di Microsoft Entra ID).

Eseguire il primo comando con la shell ospitata

La shell ospitata è il modo più veloce per iniziare. Impostare l'ambiente su container_auto per consentire ad Azure OpenAI di effettuare il provisioning e gestire un contenitore per la richiesta. Il modello decide se chiamare lo strumento in base alla richiesta.

Negli esempi seguenti, sostituisci gpt-5.5 con il nome della distribuzione del modello.

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

Questi esempi usano Microsoft Entra ID. Per usare invece una chiave API, impostare api_key sul valore della chiave (Python e JavaScript), passare AzureApiKeyCredential quando si compila il client (Java) o inviare l'intestazione api-key anziché Authorization: Bearer (REST).

Riferimento: Use the Azure OpenAI Responses API | OpenAI Python SDK | OpenAI Node SDK | OpenAI Java SDK

Dettagli del runtime ospitato

Il contenitore ospitato fornisce un ambiente Linux gestito per ogni sessione di richiesta o contenitore:

  • Il runtime è basato su Debian 12 e può cambiare nel tempo.
  • La directory di lavoro predefinita è /mnt/data. Questa directory è sempre presente ed è il percorso supportato per gli artefatti scaricabili dall'utente.
  • Python 3.11 è preinstallato.
  • La shell ospitata non supporta sessioni TTY interattive e i comandi non vengono eseguiti con sudo.
  • I contenitori ospitati non hanno accesso alla rete in uscita.

È possibile eseguire servizi all'interno del contenitore quando il flusso di lavoro li necessita.

Riutilizzare un contenitore tra le richieste

Per i flussi di lavoro iterativi, creare un contenitore una sola volta e farvi riferimento nelle chiamate API risposte successive. Il contenitore mantiene i file e lo stato tra le richieste mentre è attivo.

Creare prima di tutto il contenitore.

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

print(container.id)

Fare quindi riferimento al contenitore in base all'ID in una richiesta della shell.

# 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)

Per continuare a lavorare nello stesso contenitore tra un turno e l'altro, passare lo stesso container_id e il previous_response_id della risposta precedente.

Eseguire comandi in modalità shell locale

In modalità shell locale si eseguono i comandi del modello nel proprio runtime anziché in un contenitore ospitato. Usare questa modalità quando è necessario il controllo completo sull'ambiente di esecuzione, sull'accesso al file system o sugli strumenti interni esistenti.

Impostare l'ambiente su local. Il modello restituisce shell_call elementi che descrivono i comandi da eseguire.

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))

Quando si ricevono shell_call elementi, eseguire i comandi richiesti, acquisire l'output e restituire i risultati come shell_call_output nella richiesta successiva. Il seguente esecutore acquisisce stdout, stderr, e l'esito di uscita, e gestisce i timeout.

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)

Riferimento: Use the Azure OpenAI Responses API

Output della shell nelle risposte

La shell ospitata e la shell locale usano gli stessi tipi di elemento di output. Ogni esecuzione della shell è rappresentata da una coppia di elementi:

  • shell_call: i comandi richiesti dal modello.
  • shell_call_output: l'output del comando e il risultato in uscita.

Il modello richiede comandi con un shell_call elemento:

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

Si restituiscono risultati con un shell_call_output elemento:

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

Se un shell_call include max_output_length, includi lo stesso valore nel shell_call_output. Se un comando supera il timeout di esecuzione, restituisci un esito timeout e includi l'eventuale output parziale acquisito.

Scarica artefatti

La shell ospitata può produrre file scaricabili. Per recuperare gli artefatti, scriverli in /mnt/data, quindi scaricarli usando le stesse API contenitore e file usate dall'interprete del codice.

Conservazione dei dati e ciclo di vita del contenitore

  • Una sessione contenitore ospitata termina dopo 20 minuti di inattività.
  • Un contenitore ospitato viene eliminato un'ora dopo la creazione. Tutti i dati archiviati nel contenitore vengono rimossi quando il contenitore viene eliminato.

I contenitori ospitati potrebbero scrivere lo stato temporaneo dell'applicazione nel file system del contenitore (supportato dall'archiviazione a blocchi temporanei) mentre il contenitore è attivo. I dati del contenitore vengono eliminati quando il contenitore scade o lo si elimina.

Gestire gli errori comuni

  • Timeout: se un comando supera il timeout di esecuzione, restituisci un timeout esito e includi qualsiasi output parziale catturato.
  • Output troncato: quando max_output_length è presente su un shell_call, impostare lo stesso valore sul shell_call_output.
  • Comandi interattivi: l'esecuzione dello strumento shell non è interattiva. Non fare affidamento sui comandi che richiedono l'input.
  • Uscite non zero: mantenere l'output da uscite non pari a zero in modo che il modello possa ragionarsi sui passaggi di ripristino.