Exécutez des commandes shell dans des conteneurs hébergés ou dans votre propre environnement d’exécution local.
L’outil shell permet aux modèles de travailler dans un environnement de terminal complet. Il prend en charge l’exécution locale et l’exécution hébergée via l’API Responses.
L’outil shell permet aux modèles d’exécuter des commandes dans l’un des environnements suivants :
Le shell est disponible via l’API Responses. Il n’est pas disponible via l’API Chat Completions.
L’exécution de commandes shell arbitraires peut être dangereuse. Isolez toujours l’exécution dans un bac à sable,
appliquez des listes d’autorisation ou de blocage lorsque c’est possible et journalisez l’activité de l’outil à des fins
d’audit.
Démarrage rapide du shell distant
Le shell distant est une solution native et simple à utiliser pour les tâches qui nécessitent des traitements déterministes plus poussés, du calcul à la manipulation de contenus multimédias.
Utilisez container_auto lorsque vous souhaitez qu’OpenAI provisionne et gère un conteneur pour la requête.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15require "openai"client = OpenAI::Client.newresponse = client.responses.create( model: "gpt-6-astra", input: "Run ls -lah /mnt/data, then show the Python and Node.js versions.", tools: [ { type: :shell, environment: { type: :container_auto } } ])puts(response.output_text)
Détails de l’environnement d’exécution hébergé
L’environnement d’exécution repose actuellement sur Debian 12 et peut évoluer au fil du temps.
Le répertoire de travail par défaut est /mnt/data.
Le répertoire /mnt/data est toujours présent et constitue le chemin pris en charge pour les artefacts que les utilisateurs peuvent télécharger.
Le shell distant ne prend pas en charge les sessions TTY interactives.
Les commandes du shell distant ne s’exécutent pas avec sudo.
Vous pouvez exécuter des services dans le conteneur lorsque votre workflow en a besoin.
Les langages actuellement préinstallés comprennent :
Python 3.11
Node.js 22.16
Java 17.0
PHP 8.2
Ruby 3.1
Go 1.23
Réutilisez un conteneur pour plusieurs requêtes
Si vos workflows itératifs nécessitent un environnement qui reste actif longtemps, créez un conteneur, puis référencez-le dans les appels suivants à l’API Responses.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18require "openai"client = OpenAI::Client.newresponse = client.responses.create( model: "gpt-6-astra", input: "List files in the container and show disk usage.", tools: [ { type: :shell, environment: { type: :container_reference, container_id: "cntr_08f3d96c87a585390069118b594f7481a088b16cda7d9415fe" } } ])puts(response.output_text)
Associez des skills
Les skills sont des ensembles réutilisables et versionnés que vous pouvez monter dans des environnements de shell distant. Ce montage définit les skills disponibles ; au moment de l’exécution du shell, le modèle décide de les invoquer ou non.
Consultez le guide des skills pour en savoir plus sur le téléversement et la gestion des versions.
L’ajout de domaines à une liste d’autorisation présente des risques de sécurité, comme l’exfiltration de données
provoquée par une attaque par injection de prompt. N’autorisez que des domaines auxquels vous faites confiance et que
des attaquants ne peuvent pas utiliser pour recevoir des données exfiltrées. Lisez attentivement la section Risques
et sécurité ci-dessous avant d’utiliser cet outil.
Ordre de priorité des politiques réseau
Lorsque plusieurs contrôles sont en place :
La liste d’autorisation de votre organisation définit l’ensemble complet des domaines autorisés dans allowed_domains.
Le paramètre network_policy défini au niveau de la requête restreint davantage l’accès.
Les requêtes échouent si allowed_domains contient des domaines qui ne figurent pas dans la liste d’autorisation de votre organisation.
Conservation des données et cycle de vie des conteneurs
Les conteneurs hébergés utilisés par le shell distant et l’Interpréteur de code peuvent écrire des données temporaires d’état de l’application dans le système de fichiers du conteneur (reposant sur un stockage par blocs éphémère) tant que celui-ci est actif. Les données du conteneur sont supprimées lorsqu’il expire ou qu’il est explicitement supprimé.
Le shell distant peut produire des fichiers téléchargeables. Utilisez les mêmes API container/files que l’interpréteur de code pour récupérer les artefacts écrits dans /mnt/data.
Contrôles supplémentaires des données
Pour que le contenu et les fichiers restent éphémères pendant le cycle de vie de l’environnement hébergé, vous pouvez intégrer les fichiers directement dans la requête et monter dans le conteneur les skills fournies de la même manière.
Utilisez des fichiers et des skills intégrés à la requête
Pour les requêtes suivantes, transmettez le même container_id avec container_reference. Les skills montées et les fichiers déjà présents dans le conteneur restent disponibles tant que celui-ci est actif.
Supprimez un conteneur avant son expiration
Vous pouvez supprimer explicitement le conteneur une fois le travail terminé, sans attendre son expiration pour inactivité.
import OpenAI from "openai";const client = new OpenAI();const deleted = await client.containers.delete("container_id");console.log(deleted);
# Replace the illustrative IDs and URLs below with your own resource values.from openai import OpenAIclient = OpenAI()container_id = "cntr_123"deleted = client.containers.delete(container_id)print(deleted)
Utilisez domain_secrets lorsqu’un domaine de votre liste allowed_domains nécessite des en-têtes d’autorisation privés, tels que Authorization: Bearer <token>.
Chaque entrée de secret comprend :
Domaine cible
Nom lisible du secret
Valeur du secret
Lors de l’exécution :
Le modèle et l’environnement d’exécution voient des noms de substitution (par exemple, $API_KEY) à la place des identifiants bruts.
Le composant sidecar de conversion des données d’authentification n’applique les valeurs brutes des secrets que pour les destinations approuvées.
Les valeurs brutes des secrets ne sont pas conservées sur les serveurs API et n’apparaissent pas dans le contexte visible par le modèle.
Cela permet à l’assistant d’appeler des services protégés tout en réduisant le risque de fuite.
Outil shell avec domain_secrets
curl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32curl-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" } ] } } } ] }'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36import OpenAI from "openai";const client = new OpenAI();const response = await client.responses.create({ 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", }, ], }, }, }, ],});console.log(response.output_text);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35from openai import OpenAIclient = OpenAI()response = client.responses.create( 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", } ], }, }, } ],)print(response.output_text)
Le shell distant et le shell local utilisent les mêmes types d’éléments de sortie. Les exécutions du shell sont représentées par des paires d’éléments de sortie :
shell_call : commandes demandées par le modèle.
shell_call_output : sortie des commandes et états de fin d’exécution.
Vous pouvez aussi exécuter des commandes shell dans votre propre environnement d’exécution local en exécutant les actions shell_call et en renvoyant shell_call_output au modèle.
Utilisez ce mode lorsque vous avez besoin de contrôler entièrement l’environnement d’exécution, l’accès au système de fichiers ou les outils internes existants.
Requête de shell local
curl
1
2
3
4
5
6
7
8
9curl-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" } }] }'
1
2
3
4
5
6
7
8
9
10
11
12import OpenAI from "openai";const client = new OpenAI();const response = await client.responses.create({ 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" } }],});console.log(response);
1
2
3
4
5
6
7
8
9
10
11
12from openai import OpenAIclient = OpenAI()response = client.responses.create( 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"}}],)print(response)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26package mainimport ( "context" "fmt" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/responses")func main() { client := openai.NewClient() tool := responses.ToolUnionParam{OfShell: &responses.FunctionShellToolParam{ Environment: responses.FunctionShellToolEnvironmentUnionParam{OfLocal: &responses.LocalEnvironmentParam{}}, }} response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{ Model: "gpt-6-astra", Instructions: openai.String("The local bash shell environment is on Mac."), Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("find me the largest pdf file in ~/Documents")}, Tools: []responses.ToolUnionParam{tool}, }) if err != nil { panic(err) } fmt.Println(response.Output)}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import com.openai.client.OpenAIClient;import com.openai.client.okhttp.OpenAIOkHttpClient;import com.openai.core.JsonValue;import com.openai.models.responses.ResponseCreateParams;import java.util.List;import java.util.Map;ResponseCreateParams params = ResponseCreateParams.builder() .model("gpt-6-astra") .input("Find the largest PDF in ~/Documents.") .instructions("The local shell environment is macOS.") .putAdditionalBodyProperty( "tools", JsonValue.from( List.of(Map.of("type", "shell", "environment", Map.of("type", "local"))))) .build();client.responses().create(params).output().stream() .flatMap(item -> item.shellCall().stream()) .flatMap(call -> call.action().commands().stream()) .forEach(System.out::println);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16require "openai"client = OpenAI::Client.newresponse = client.responses.create( model: "gpt-6-astra", instructions: "The local shell environment is macOS.", input: "Find the largest PDF in ~/Documents.", tools: [ { type: :shell, environment: { type: :local } } ])puts(response.output)
Lorsque vous recevez des éléments de sortie shell_call :
Exécutez les commandes demandées dans votre environnement d’exécution.
Capturez stdout, stderr et l’état de fin d’exécution.
Renvoyez les résultats sous forme de shell_call_output dans la requête suivante.
Si une commande dépasse le délai d’exécution imparti, renvoyez un résultat indiquant ce dépassement et incluez la sortie partielle capturée.
Si max_output_length est présent dans shell_call, incluez-le dans shell_call_output.
Ne vous appuyez pas sur des commandes interactives ; l’exécution de l’outil shell doit être non interactive.
Conservez les sorties des commandes dont le code de sortie est non nul afin que le modèle puisse déterminer les mesures à prendre pour reprendre l’exécution.
Risques et sécurité
L’activation de l’accès réseau dans l’API Containers offre des possibilités étendues, mais présente des risques importants pour la sécurité et la gouvernance des données. Par défaut, l’accès réseau est désactivé. Lorsqu’il est activé, l’accès sortant doit rester strictement limité aux domaines de confiance nécessaires à la tâche.
Les conteneurs disposant d’un accès réseau peuvent interagir avec des services tiers et des registres de paquets. Cela présente des risques, notamment des fuites de données, une utilisation détournée des outils à la suite d’attaques par injection de prompt et des accès accidentels au-delà du périmètre prévu. Ces risques augmentent lorsque les politiques sont trop larges, statiques ou appliquées de manière incohérente.
Comprenez les risques d’attaque par injection de prompt liés aux contenus récupérés sur le réseau
Tout contenu externe récupéré sur le réseau peut contenir des instructions cachées visant à manipuler le comportement du modèle. Considérez les contenus réseau non fiables comme potentiellement malveillants et exigez une vigilance accrue pour les actions susceptibles de modifier des données ou des systèmes.
Connectez-vous uniquement à des destinations de confiance
N’autorisez que les domaines auxquels vous faites confiance et que vous maintenez activement. Faites preuve de prudence avec les intermédiaires et les agrégateurs qui relaient les requêtes vers d’autres services. Examinez leurs pratiques de traitement et de conservation des données avant de les ajouter à votre liste de domaines autorisés.
Prévoyez des vérifications avant et après l’exécution des requêtes
Examinez la commande de l’outil shell et sa sortie d’exécution, fournies dans la réponse de l’API Responses. Consignez les hôtes demandés et les destinations sortantes effectivement contactées pour chaque session. Examinez régulièrement les journaux pour vérifier que les accès correspondent aux attentes, détecter les écarts et repérer les comportements suspects.
Vérifiez les exigences de résidence et de conservation des données
Les contrôles des données d’OpenAI s’appliquent au sein du périmètre d’OpenAI. Toutefois, les données transmises à des services tiers par des connexions réseau sont soumises aux politiques de conservation des données de ces services. Assurez-vous que les points de terminaison externes respectent vos exigences de résidence, de conservation et de conformité.