For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navegación principal
Theme

Shell

Ejecuta comandos de shell en contenedores alojados en la nube o en tu propio entorno de ejecución local.

La herramienta de shell permite que los modelos trabajen en un entorno de terminal completo. A través de la API de Responses, puedes ejecutar comandos de shell tanto de forma local como en la nube.

Con la herramienta de shell, los modelos pueden ejecutar comandos en cualquiera de estos entornos:

La herramienta de shell está disponible a través de la API de Responses. No está disponible a través de la API para completar chats.

Ejecutar comandos de shell arbitrarios puede ser peligroso. Ejecuta siempre los comandos en un sandbox, permite o bloquea comandos específicos cuando sea posible y registra la actividad de la herramienta para poder auditarla.

Inicio rápido con la terminal alojada en la nube

La terminal alojada en la nube ofrece una opción nativa y fácil de usar para tareas que requieren un procesamiento más avanzado y determinista, desde hacer cálculos hasta trabajar con contenido multimedia.

Usa container_auto cuando quieras que OpenAI aprovisione y administre un contenedor para la solicitud.

Herramienta de shell con container_auto
curl -L 'https://api.openai.com/v1/responses' \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-6-astra",
    "tools": [
      { "type": "shell", "environment": { "type": "container_auto" } }
    ],
    "input": [
      {
        "type": "message",
        "role": "user",
        "content": [
          { "type": "input_text", "text": "Execute: ls -lah /mnt/data && python --version && node --version" }
        ]
      }
    ],
    "tool_choice": "auto"
  }'

Detalles del entorno de ejecución alojado en la nube

  • El entorno de ejecución se basa actualmente en Debian 12 y puede cambiar con el tiempo.
  • El directorio de trabajo predeterminado es /mnt/data.
  • /mnt/data siempre está disponible y es la ruta admitida para los artefactos que el usuario puede descargar.
  • La terminal alojada en la nube no admite sesiones TTY interactivas.
  • Los comandos de la terminal alojada en la nube se ejecutan sin sudo.
  • Puedes ejecutar servicios dentro del contenedor cuando tu flujo de trabajo los necesite.

Estos son algunos de los lenguajes que vienen preinstalados actualmente:

  • Python 3.11
  • Node.js 22.16
  • Java 17.0
  • PHP 8.2
  • Ruby 3.1
  • Go 1.23

Reutiliza un contenedor en varias solicitudes

Si necesitas un entorno de larga duración para flujos de trabajo iterativos, crea un contenedor y haz referencia a él en las llamadas posteriores a la API de Responses.

1. Crea un contenedor

Crea un contenedor reutilizable
curl -L 'https://api.openai.com/v1/containers' \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "name": "analysis-container",
    "memory_limit": "1g",
    "expires_after": { "anchor": "last_active_at", "minutes": 20 }
  }'

2. Haz referencia al contenedor en Responses

Usa la herramienta de shell con container_reference
curl -L 'https://api.openai.com/v1/responses' \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-6-astra",
    "tools": [
      {
        "type": "shell",
        "environment": {
          "type": "container_reference",
          "container_id": "cntr_08f3d96c87a585390069118b594f7481a088b16cda7d9415fe"
        }
      }
    ],
    "input": "List files in the container and show disk usage."
  }'

Adjunta habilidades

Las habilidades son paquetes reutilizables con control de versiones que puedes montar en entornos de la terminal alojada en la nube. Al montarlas, defines qué habilidades están disponibles. Cuando se ejecuta el shell, el modelo decide si las invoca.

Consulta la guía de habilidades para saber cómo subirlas y gestionar sus versiones.

Crea un contenedor con habilidades adjuntas
curl -L 'https://api.openai.com/v1/containers' \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "name": "skill-container",
    "skills": [
      { "type": "skill_reference", "skill_id": "skill_4db6f1a2c9e73508b41f9da06e2c7b5f" },
      { "type": "skill_reference", "skill_id": "openai-spreadsheets", "version": "latest" }
    ]
  }'

Acceso a la red

De forma predeterminada, los contenedores alojados en la nube no tienen acceso saliente a la red.

Para habilitarlo:

  1. Un administrador debe configurar la lista de dominios permitidos de tu organización en el panel.
  2. En tu solicitud, debes establecer explícitamente network_policy en el entorno del contenedor.
Herramienta de shell con una lista de dominios permitidos
curl -L 'https://api.openai.com/v1/responses' \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-6-astra",
    "tool_choice": "required",
    "tools": [
      {
        "type": "shell",
        "environment": {
          "type": "container_auto",
          "network_policy": {
            "type": "allowlist",
            "allowed_domains": ["pypi.org", "files.pythonhosted.org", "github.com"]
          }
        }
      }
    ],
    "input": [
      {
        "role": "user",
        "content": "In the container, pip install httpx beautifulsoup4, fetch release pages, and write /mnt/data/release_digest.md."
      }
    ]
  }'

Permitir el acceso a determinados dominios conlleva riesgos de seguridad, como la exfiltración de datos mediante la inyección de prompts. Permite únicamente dominios de confianza que los atacantes no puedan usar para recibir datos robados. Antes de usar esta herramienta, revisa detenidamente la sección Riesgos y seguridad que aparece más adelante.

Orden de aplicación de las políticas de red

Cuando se aplican varios controles:

  • La lista de dominios permitidos de tu organización define el conjunto completo de allowed_domains.
  • La política network_policy de cada solicitud restringe aún más el acceso.
  • Las solicitudes fallan si allowed_domains incluye dominios que no figuran en la lista de tu organización.

Retención de datos y ciclo de vida del contenedor

La terminal alojada en la nube y el intérprete de código usan contenedores alojados en la nube. Mientras están activos, estos contenedores pueden guardar el estado temporal de la aplicación en su sistema de archivos, que utiliza almacenamiento efímero en bloques. Los datos del contenedor se eliminan cuando el contenedor caduca o cuando lo eliminas explícitamente.

Para obtener más detalles sobre los controles de datos, consulta ZDR y residencia de datos.

Descarga artefactos

La terminal alojada en la nube puede generar archivos descargables. Usa las mismas API de contenedores y archivos que usa el intérprete de código para recuperar los artefactos guardados en /mnt/data.

Controles de datos adicionales

Si quieres que el contenido y los archivos sean efímeros durante el ciclo de vida del contenedor alojado en la nube, puedes incluir los archivos directamente en la solicitud y montar en el contenedor las habilidades incluidas de la misma forma.

Usa archivos y habilidades incluidos directamente en la solicitud
INLINE_ZIP=$(base64 -i ./csv_insights.zip)
REPORT_CSV=$(base64 -i ./report.csv)

CONTAINER_ID=$(
  curl -sL 'https://api.openai.com/v1/containers' \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $OPENAI_API_KEY" \
    -d '{
      "name": "inline-skill-container",
      "skills": [
        {
          "type": "inline",
          "name": "csv-insights",
          "description": "Summarize CSV files and produce a markdown report.",
          "source": {
            "type": "base64",
            "media_type": "application/zip",
            "data": "'"$INLINE_ZIP"'"
          }
        }
      ]
    }' | jq -r '.id'
)

curl -L 'https://api.openai.com/v1/responses' \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-6-astra",
    "tools": [
      {
        "type": "shell",
        "environment": {
          "type": "container_reference",
          "container_id": "'"$CONTAINER_ID"'"
        }
      }
    ],
    "input": [
      {
        "role": "user",
        "content": [
          {
            "type": "input_file",
            "filename": "report.csv",
            "file_data": "data:text/csv;base64,'"${REPORT_CSV}"'"
          },
          {
            "type": "input_text",
            "text": "Use the csv-insights skill to summarize report.csv."
          }
        ]
      }
    ]
  }'

Para las solicitudes posteriores, pasa el mismo container_id con container_reference. Las habilidades montadas y los archivos que ya están en el contenedor siguen disponibles mientras el contenedor está activo.

Elimina el contenedor al terminar

Puedes eliminar el contenedor explícitamente cuando termines el trabajo, sin esperar a que caduque por inactividad.

Elimina un contenedor
curl -L -X DELETE 'https://api.openai.com/v1/containers/container_id' \
  -H "Authorization: Bearer $OPENAI_API_KEY"

Secretos de dominio

Usa domain_secrets cuando un dominio de tu lista allowed_domains requiera encabezados de autorización privados, como Authorization: Bearer <token>.

Cada entrada de secreto incluye:

  • El dominio de destino
  • Un nombre descriptivo para el secreto
  • El valor del secreto

Durante la ejecución:

  • El modelo y el entorno de ejecución ven marcadores de posición (por ejemplo, $API_KEY) en lugar de las credenciales reales.
  • El contenedor auxiliar que sustituye los marcadores de autenticación usa los valores reales de los secretos solo para los destinos aprobados.
  • Los valores reales de los secretos no se conservan en los servidores de la API ni aparecen en el contexto que ve el modelo.

Así, el asistente puede llamar a servicios protegidos con un menor riesgo de filtración de credenciales.

Herramienta de shell con domain_secrets
curl -L 'https://api.openai.com/v1/responses' \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-6-astra",
    "input": [
      {
        "role": "user",
        "content": "Use curl to call https://httpbin.org/headers with header Authorization: Bearer $API_KEY. Tell me what you see in the final text response."
      }
    ],
    "tool_choice": "required",
    "tools": [
      {
        "type": "shell",
        "environment": {
          "type": "container_auto",
          "network_policy": {
            "type": "allowlist",
            "allowed_domains": ["httpbin.org"],
            "domain_secrets": [
              {
                "domain": "httpbin.org",
                "name": "API_KEY",
                "value": "debug-secret-123"
              }
            ]
          }
        }
      }
    ]
  }'

Flujos de trabajo de varios turnos

Para seguir trabajando en el mismo entorno alojado en la nube, reutiliza el contenedor y pasa previous_response_id.

Continúa un flujo de trabajo de shell
curl -L 'https://api.openai.com/v1/responses' \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-6-astra",
    "previous_response_id": "resp_2a8e5c9174d63b0f18a4c572de9f64a1b3c76d508e12f9ab47",
    "tools": [
      {
        "type": "shell",
        "environment": {
          "type": "container_reference",
          "container_id": "cntr_f19c2b51e4a06793d82d54a7be0fc9154d3361ab28ce7f6041"
        }
      }
    ],
    "input": "Read /mnt/data/top5.csv and report the top candidate."
  }'

Salida de shell en Responses

La terminal alojada en la nube y el shell local usan los mismos tipos de elementos de salida. Cada ejecución de shell se representa con un par de elementos de salida:

  • shell_call: comandos que solicita el modelo.
  • shell_call_output: salida de los comandos y resultados de su ejecución.
Ejemplo de un elemento shell_call
{
  "type": "shell_call",
  "call_id": "call_9d14ac6f2b73485e91c0f4da6e1b27c8",
  "action": {
    "commands": ["ls -l"],
    "timeout_ms": 120000,
    "max_output_length": 4096
  },
  "status": "in_progress"
}

Modo de shell local

También puedes ejecutar comandos de shell en tu propio entorno de ejecución local. Para ello, ejecuta las acciones shell_call y devuelve shell_call_output al modelo.

Usa este modo cuando necesites controlar el sistema de archivos o acceder a herramientas internas. Establece el tipo de herramienta en shell y el tipo de entorno en local. Si estás migrando desde la herramienta local_shell, que ya se retiró, actualiza tu solicitud y procesa shell_call y shell_call_output en tu bucle de ejecución.

Solicitud de shell local
curl -L 'https://api.openai.com/v1/responses' \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-6-astra",
    "instructions": "The local bash shell environment is on Mac.",
    "input": "find me the largest pdf file in ~/Documents",
    "tools": [{ "type": "shell", "environment": { "type": "local" } }]
  }'

Cuando recibas elementos de salida shell_call:

  • Revisa cada comando antes de ejecutarlo. Usa una lista de comandos permitidos y exige aprobación para los comandos destructivos o que accedan a datos sensibles.
  • Ejecuta los comandos aprobados en un sandbox que limite explícitamente el acceso al sistema de archivos y a la red, el uso de memoria y el tiempo de ejecución. Aplica tu propio límite de tiempo aunque el modelo sugiera uno.
  • Registra los comandos y sus resultados para poder auditarlos.
  • Captura stdout, stderr y el resultado de la ejecución.
  • Devuelve los resultados como shell_call_output en la siguiente solicitud.
Ejemplo de un ejecutor de shell local
from contextlib import suppress
from dataclasses import dataclass
import os
import signal
import subprocess


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


class ShellExecutor:
    def __init__(self, default_timeout: float = 60):
        self.default_timeout = default_timeout

    def run(self, cmd: str, timeout: float | None = None) -> CmdResult:
        t = self.default_timeout if timeout is None else timeout
        p = subprocess.Popen(
            cmd,
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            start_new_session=True,
        )
        try:
            out, err = p.communicate(timeout=t)
            return CmdResult(out, err, p.returncode, False)
        except subprocess.TimeoutExpired:
            # Stop the shell and its children before draining their output pipes.
            with suppress(ProcessLookupError):
                os.killpg(p.pid, signal.SIGKILL)
            out, err = p.communicate()
            return CmdResult(out, err, p.returncode, True)

Estos ejemplos requieren Linux o macOS y detienen el grupo de procesos del comando cuando se agota el tiempo asignado al comando.

Ejemplo del contenido de shell_call_output
{
  "type": "shell_call_output",
  "call_id": "call_3ef1b8c79a4d6520f9e3ab7d41c68f25",
  "max_output_length": 4096,
  "output": [
    {
      "stdout": "...",
      "stderr": "...",
      "outcome": {
        "type": "exit",
        "exit_code": 0
      }
    },
    {
      "stdout": "...",
      "stderr": "...",
      "outcome": {
        "type": "timeout"
      }
    }
  ]
}

Si un comando falla o se agota su tiempo de ejecución, devuelve el resultado para que el modelo pueda decidir si vuelve a intentarlo. Consulta el aviso de retiro de la herramienta anterior.

Usa el shell local con el SDK de agentes

Si usas el SDK de agentes, puedes pasar tu propia implementación del ejecutor de shell a la función auxiliar de la herramienta de shell.

Usa el shell local con el SDK de agentes
import { Agent, run, withTrace, shellTool } from "@openai/agents";

class LocalShell {
  async run(action) {
    return {
      output: [
        {
          stdout: "Shell is not available. Needs to be implemented first.",
          stderr: "",
          outcome: {
            type: "exit",
            exitCode: 1,
          },
        },
      ],
      maxOutputLength: action.maxOutputLength,
    };
  }
}

const shell = new LocalShell();

const agent = new Agent({
  name: "Shell Assistant",
  model: "gpt-6-astra",
  instructions:
    "You can execute shell commands to inspect the repository. Keep responses concise and include command output when helpful.",
  tools: [
    shellTool({
      shell,
      needsApproval: true,
      onApproval: async (_ctx, _approvalItem) => {
        return { approve: true };
      },
    }),
  ],
});

await withTrace("shell-tool-example", async () => {
  const result = await run(agent, "Show the Node.js version.");
  console.log(`\nFinal response:\n${result.finalOutput}`);
});

En los repositorios del SDK encontrarás ejemplos que puedes ejecutar.

Ejemplo de la herramienta de shell en TypeScript

Ejemplo en TypeScript de cómo usar la herramienta de shell en el SDK de agentes.

Ejemplo de la herramienta de shell en Python

Ejemplo en Python de cómo usar la herramienta de shell en el SDK de agentes.

Manejo de errores comunes

  • Si un comando supera el tiempo límite de ejecución, devuelve un resultado que indique que se agotó el tiempo e incluye la salida parcial capturada.
  • Si max_output_length está presente en shell_call, inclúyelo en shell_call_output.
  • Evita depender de comandos interactivos. La herramienta de shell debe ejecutarse sin interacción.
  • Conserva la salida de los comandos que terminan con un código de salida distinto de cero para que el modelo pueda determinar cómo recuperarse.

Riesgos y seguridad

Habilitar el acceso a la red en la API de contenedores amplía considerablemente sus capacidades y conlleva riesgos importantes para la seguridad y la gobernanza de datos. El acceso a la red está deshabilitado de forma predeterminada. Si lo habilitas, limita estrictamente el acceso saliente a los dominios de confianza que requiera la tarea.

Los contenedores con acceso a la red pueden interactuar con servicios de terceros y registros de paquetes. Esto conlleva riesgos como la filtración de datos, el uso indebido de herramientas mediante la inyección de prompts y el acceso accidental a recursos fuera del alcance previsto. Estos riesgos aumentan cuando las políticas son amplias, son estáticas o se aplican de manera inconsistente.

Comprende los riesgos de inyección de prompts en el contenido obtenido de la red

Cualquier contenido externo que se obtenga a través de la red puede incluir instrucciones ocultas destinadas a manipular el comportamiento del modelo. Trata el contenido de red que no sea de confianza como potencialmente malicioso y extrema las precauciones ante acciones que puedan modificar datos o sistemas.

Conéctate solo a destinos de confianza

Permite únicamente dominios de confianza que mantengas activamente. Ten cuidado con los intermediarios y agregadores que reenvían solicitudes a otros servicios. Antes de agregarlos a tu lista de dominios permitidos, revisa cómo manejan y retienen los datos.

Incorpora revisiones antes y después de ejecutar las solicitudes

Revisa el comando de la herramienta de shell y la salida de su ejecución. Encontrarás ambos en la respuesta de la API de Responses. Registra en cada sesión los hosts solicitados y los destinos reales de las conexiones salientes. Revisa los registros periódicamente para verificar que los patrones de acceso coincidan con lo previsto, detectar desviaciones e identificar comportamientos sospechosos.

Verifica los requisitos de residencia y retención de datos

Los controles de datos de OpenAI se aplican dentro de la infraestructura de OpenAI. Sin embargo, los datos que se transmiten a servicios de terceros a través de conexiones de red están sujetos a las políticas de retención de datos de esos servicios. Verifica que los puntos de acceso externos cumplan tus requisitos de residencia de datos, retención y cumplimiento normativo.