> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreweave.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration de la sandbox

> Configurez les ressources, les images, le réseau, les délais d’expiration et le stockage des sandboxes.

Ces exemples utilisent un jeton d’accès à l’API CoreWeave défini dans `CWSANDBOX_API_KEY`. Pour l’authentification par clé API Forge, consultez [Premiers pas](/fr/products/sandboxes/get-started). Pour les exigences liées à CKS, consultez [Modes de placement](/fr/products/sandboxes/placement).

Ce guide présente les options de configuration de la sandbox, notamment les ressources, les fichiers montés, les ports, les annotations et les délais d’expiration. Servez-vous-en comme référence pour adapter l’environnement d’exécution d’une sandbox aux exigences d’une charge de travail, par exemple pour réserver de la capacité GPU, exposer un service ou définir des délais d’expiration pour les opérations.

Cette page s’adresse aux développeurs qui utilisent le SDK Python `cwsandbox` pour lancer et gérer des sandboxes.

<h2 id="overview">
  Aperçu
</h2>

Vous pouvez définir la configuration de la sandbox à trois niveaux, présentés de la portée la plus large à la plus spécifique :

* **SandboxDefaults** : valeurs par défaut partagées par toutes les sandboxes d’une session.
* **Sandbox.run() kwargs** : remplacements propres à chaque sandbox.
* **@session.function() kwargs** : configuration propre à une fonction.

```python theme={"system"}
from cwsandbox import ResourceOptions, Sandbox, SandboxDefaults, Session

# Via SandboxDefaults
defaults = SandboxDefaults(
    container_image="python:3.11",
    max_lifetime_seconds=3600,
    resources=ResourceOptions(
        requests={"cpu": "2", "memory": "2Gi"},
        limits={"cpu": "2", "memory": "2Gi"},
    ),
)

# Via les kwargs de Sandbox.run()
sandbox = Sandbox.run(
    defaults=defaults,
    resources=ResourceOptions(
        requests={"cpu": "4", "memory": "4Gi"},
        limits={"cpu": "4", "memory": "4Gi"},
    ),
)

# Via les kwargs de @session.function()
with Session(defaults) as session:
    @session.function(resources={"cpu": "1", "memory": "1Gi"})
    def compute(x: int) -> int:
        return x * 2
```

Les sections suivantes décrivent en détail chaque aspect de la configuration.

<h2 id="resources">
  Ressources
</h2>

Configurez les ressources CPU, mémoire et GPU à l’aide de la dataclass `ResourceOptions` ou d’un dictionnaire standard. Le mode sans serveur est le mode de placement par défaut et applique des demandes de ressources et des limites identiques. Pour définir des demandes de ressources et des limites différentes, utilisez le [placement CKS](#burstable-qos) avec un exécuteur dont la politique l’autorise.

Les exemples suivants utilisent des demandes de ressources et des limites identiques :

```python theme={"system"}
from cwsandbox import ResourceOptions, Sandbox

# Avec ResourceOptions
sandbox = Sandbox.run(
    resources=ResourceOptions(
        requests={"cpu": "2", "memory": "2Gi"},
        limits={"cpu": "2", "memory": "2Gi"},
    ),
)

# Avec un dict
sandbox = Sandbox.run(
    resources={
        "requests": {"cpu": "2", "memory": "2Gi"},
        "limits": {"cpu": "2", "memory": "2Gi"},
    },
)
```

Les deux formes sont équivalentes : le SDK convertit automatiquement les dicts en `ResourceOptions` en interne.

`ResourceOptions` distingue les demandes de ressources des limites. Les demandes de ressources indiquent à l’ordonnanceur ce dont la sandbox a besoin. Les limites fixent le maximum qu’elle peut consommer. Pour savoir comment Kubernetes s’appuie sur les demandes de ressources et les limites pour attribuer des [classes de Qualité de service](https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/), consultez la documentation Kubernetes.

<h3 id="resourceoptions-fields">
  Champs de ResourceOptions
</h3>

| Champ | Type | Description |
| - | - | - |
| `requests` | `dict[str, str] \| None` | Demandes de ressources CPU et mémoire utilisées pour l’ordonnancement (par exemple, `{"cpu": "500m", "memory": "512Mi"}`). |
| `limits` | `dict[str, str] \| None` | Limites de CPU et de mémoire que la sandbox ne peut pas dépasser (par exemple, `{"cpu": "2", "memory": "2Gi"}`). |
| `gpu` | `dict[str, Any] \| None` | Configuration GPU (par exemple, `{"count": 1, "type": "H100"}`). |

Tous les champs sont facultatifs côté client et valent `None` par défaut. L’allocation résolue doit respecter la politique applicable. Si vous omettez l’allocation des ressources, les demandes de ressources et les limites sont toutes deux définies à partir des valeurs par défaut de CPU et de mémoire de cette politique, qui doivent être complètes et positives.

<h3 id="guaranteed-qos">
  QoS Guaranteed
</h3>

Lorsque les demandes de ressources sont égales aux limites, la sandbox se voit attribuer la classe de Qualité de service Guaranteed. L’ordonnanceur réserve l’intégralité de l’allocation, et Kubernetes n’évince les Pods Guaranteed qu’en dernier recours lorsque les ressources du nœud sont sous pression. Une sandbox qui tente d’utiliser plus de CPU que sa limite le permet reste néanmoins bridée. Utilisez cette configuration pour les charges de travail sensibles à la latence.

```python theme={"system"}
sandbox = Sandbox.run(
    resources=ResourceOptions(
        requests={"cpu": "2", "memory": "4Gi"},
        limits={"cpu": "2", "memory": "4Gi"},
    ),
)
```

Pour la QoS Guaranteed, une syntaxe abrégée sous forme de dict plat est disponible. Le SDK normalise les dicts plats en définissant les demandes de ressources et les limites sur les mêmes valeurs.

```python theme={"system"}
# Raccourci sous forme de dict plat : les demandes de ressources et les limites sont définies sur des valeurs identiques
sandbox = Sandbox.run(
    resources={"cpu": "2", "memory": "4Gi"},
)
```

<h3 id="burstable-qos">
  QoS Burstable
</h3>

Sur un exécuteur CKS dont la politique autorise des demandes de ressources et des limites différentes, des demandes de ressources plus faibles attribuent à la sandbox la classe de Qualité de service Burstable. Avec des demandes de ressources plus faibles, l’ordonnanceur peut regrouper davantage de sandboxes sur les nœuds, tandis que chaque sandbox peut monter jusqu’à sa limite si la capacité le permet.

Suivez le guide [Utiliser votre propre infrastructure de calcul](/fr/products/sandboxes/get-started-cks) et définissez `CWSANDBOX_API_KEY` sur un jeton d’accès à l’API CoreWeave. Remplacez `[RUNNER-ID]` par l’ID d’un exécuteur CKS dont la politique autorise ces demandes de ressources et ces limites :

```python theme={"system"}
from cwsandbox import AuthStrategy, ResourceOptions, Sandbox

sandbox = Sandbox.run(
    auth=AuthStrategy.COREWEAVE_API_KEY,
    placement_mode="cks",
    runner_ids=["[RUNNER-ID]"],
    resources=ResourceOptions(
        requests={"cpu": "500m", "memory": "512Mi"},
        limits={"cpu": "4", "memory": "4Gi"},
    ),
)
```

<h3 id="cpu-values">
  Valeurs de CPU
</h3>

Indiquez le CPU en millicœurs ou en cœurs entiers. Pour plus de détails, voir [Resource units in Kubernetes](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-units-in-kubernetes).

| Valeur | Signification |
| - | - |
| `"100m"` | 100 millicœurs (0,1 CPU) |
| `"500m"` | 500 millicœurs (0,5 CPU) |
| `"1000m"` ou `"1"` | 1 cœur de CPU complet |
| `"2000m"` ou `"2"` | 2 cœurs de CPU |

<h3 id="memory-values">
  Valeurs de mémoire
</h3>

La mémoire s’exprime dans les [unités de mémoire Kubernetes](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-memory) standard :

| Valeur | Signification |
| - | - |
| `"128Mi"` | 128 mébioctets |
| `"512Mi"` | 512 mébioctets |
| `"1Gi"` | 1 gibioctet |
| `"4Gi"` | 4 gibioctets |

<h3 id="gpu">
  GPU
</h3>

Demandez des ressources GPU en plus du CPU et de la mémoire. Une requête GPU ne réserve que des GPU ; définissez donc explicitement le CPU et la mémoire.

```python theme={"system"}
sandbox = Sandbox.run(
    resources=ResourceOptions(
        requests={"cpu": "4", "memory": "16Gi"},
        limits={"cpu": "4", "memory": "16Gi"},
        gpu={"count": 1},
    ),
)
```

Clés de configuration GPU :

| Clé | Type | Description |
| - | - | - |
| `count` | `int` | Nombre de GPU à demander. |
| `type` | `str` | Type de GPU, comparé à l'identique aux types qu'un exécuteur expose lors de la [découverte](/fr/products/sandboxes/client/guides/discovery). Ne le définissez pas sur une capacité sans serveur, qui attribue elle-même le type de GPU. Voir [Exécuter une sandbox GPU](/fr/products/sandboxes/gpu-sandboxes). |
| `memory_gb` | `int` | Mémoire GPU minimale, en Go. Sélectionne sur l'exécuteur un type de GPU disposant d'au moins cette quantité de mémoire. Si plusieurs types répondent à ce critère, le type retenu n'est pas déterminé. |

`type` et `memory_gb` sont mutuellement exclusifs. Définissez-en un seul au maximum.

<h3 id="inspect-confirmed-resources">
  Inspecter les ressources confirmées
</h3>

Une fois la sandbox démarrée, inspectez l’allocation des ressources confirmée. Cet exemple utilise des demandes de ressources et des limites différentes sur CKS. Effectuez la configuration de CKS, puis définissez `CWSANDBOX_API_KEY` sur un jeton d’accès à l’API CoreWeave. Remplacez `[RUNNER-ID]` par l’ID d’un exécuteur CKS qui dispose d’une capacité GPU et d’une politique autorisant ces ressources :

```python theme={"system"}
from cwsandbox import AuthStrategy, ResourceOptions, Sandbox

with Sandbox.run(
    auth=AuthStrategy.COREWEAVE_API_KEY,
    placement_mode="cks",
    runner_ids=["[RUNNER-ID]"],
    resources=ResourceOptions(
        requests={"cpu": "500m", "memory": "512Mi"},
        limits={"cpu": "2", "memory": "2Gi"},
        gpu={"count": 1},
    ),
) as sb:
    print(sb.resource_requests)  # {"cpu": "500m", "memory": "512Mi"}
    print(sb.resource_limits)    # {"cpu": "2", "memory": "2Gi"}
    print(sb.resource_gpu)       # {"count": 1}
```

<h3 id="configuration-library-interop">
  Interopérabilité avec les bibliothèques de configuration
</h3>

Tous les types de configuration (`NetworkOptions`, `Secret`, `ResourceOptions`) acceptent soit la dataclass, soit un dictionnaire standard. Les bibliothèques de configuration ML qui résolvent les configurations en dicts ou en objets de type dict peuvent ainsi transmettre directement les valeurs au SDK, sans conversion manuelle.

`SandboxDefaults.from_dict()` accepte un dictionnaire standard ou un `DictConfig` OmegaConf, et convertit automatiquement les champs imbriqués : les dicts deviennent des `NetworkOptions`, `Secret` ou `ResourceOptions` selon le cas, et les listes deviennent des tuples.

```yaml theme={"system"}
# sandbox.yaml
container_image: "pytorch/pytorch:2.4.0-cuda12.4-cudnn9-runtime"
max_lifetime_seconds: 3600
tags:
  - training
  - experiment-42
resources:
  requests:
    cpu: "4"
    memory: "8Gi"
  limits:
    cpu: "4"
    memory: "8Gi"
  gpu:
    count: 1
network:
  egress_mode: "internet"
environment_variables:
  LOG_LEVEL: "info"
```

```python theme={"system"}
from omegaconf import OmegaConf
from cwsandbox import Sandbox, SandboxDefaults

cfg = OmegaConf.load("sandbox.yaml")
defaults = SandboxDefaults.from_dict(cfg)

with Sandbox.run(defaults=defaults) as sb:
    result = sb.exec(["python", "train.py"]).result()
```

Chaque champ accepte également un dict lorsque vous le transmettez directement à `Sandbox.run()` ou à `session.sandbox()`. Pour les ressources, la forme dict imbriquée correspond aux champs de `ResourceOptions`. La forme dict plate (`{"cpu": "1", "memory": "1Gi"}`) est également acceptée et traitée comme une QoS Guaranteed.

<h2 id="mounted-files">
  Fichiers montés
</h2>

Les fichiers montés vous permettent de fournir à la sandbox, dès son démarrage, des fichiers de configuration, des scripts ou d’autres ressources en lecture seule, sans avoir à les intégrer à une image de conteneur.

```python theme={"system"}
sandbox = Sandbox.run(
    mounted_files=[
        {
            "path": "/app/config.json",
            "content": '{"debug": true}',
        },
        {
            "path": "/app/script.py",
            "content": "print('hello')",
        },
    ],
)

# Les fichiers sont immédiatement disponibles
result = sandbox.exec(["python", "/app/script.py"]).result()
```

<h3 id="mount-options">
  Options de montage
</h3>

| Champ | Type | Description |
| - | - | - |
| `path` | `str` | Chemin absolu dans la sandbox. |
| `content` | `str` | Contenu du fichier (texte). |

Les fichiers montés sont en lecture seule. Pour les fichiers à modifier, utilisez `write_file()`.

<h2 id="ports">
  Ports
</h2>

Exposez des ports pour permettre aux processus exécutés dans la sandbox de servir le trafic provenant de clients externes :

```python theme={"system"}
sandbox = Sandbox.run(
    "python", "-m", "http.server", "8080",
    ports=[
        {"container_port": 8080},
    ],
)
```

<h3 id="port-configuration">
  Configuration des ports
</h3>

| Champ | Type | Description |
| - | - | - |
| `container_port` | `int` | Port à l’intérieur du sandbox. |

Pour attribuer à un port une adresse accessible depuis Internet, avec le TLS de la plateforme ou en mode TLS passthrough, consultez [Points de terminaison publics](/fr/products/sandboxes/public-endpoints).

<h2 id="network">
  Réseau
</h2>

Configurez les options réseau à l’aide de la dataclass `NetworkOptions` ou d’un dictionnaire standard :

```python theme={"system"}
from cwsandbox import NetworkOptions, Sandbox

# Avec NetworkOptions
sandbox = Sandbox.run(
    network=NetworkOptions(
        ingress_mode="public",
        exposed_ports=(8080,),
    ),
)

# Avec un dict
sandbox = Sandbox.run(
    network={"ingress_mode": "public", "exposed_ports": [8080]},
)
```

Les deux formes sont équivalentes : le SDK convertit automatiquement les dicts en `NetworkOptions` en interne.

<h3 id="networkoptions-fields">
  Champs de NetworkOptions
</h3>

| Champ | Type | Description |
| - | - | - |
| `ingress_mode` | `str \| None` | Contrôle le trafic entrant, par exemple `"public"` (accessible depuis Internet) ou `"internal"` (cluster uniquement). |
| `exposed_ports` | `tuple[int, ...] \| None` | Ports à exposer (requis avec `ingress_mode`). À fournir sous forme de tuple `(8080,)` ou de liste `[8080]`. |
| `egress_mode` | `str \| None` | Contrôle le trafic sortant, par exemple `"internet"` (accès complet), `"isolated"` (aucun accès externe) ou `"org"` (accès limité à l’organisation). |

Tous les champs sont facultatifs et valent `None` par défaut, auquel cas les valeurs par défaut du backend s’appliquent.

<h3 id="set-network-in-sandboxdefaults">
  Définir le réseau dans SandboxDefaults
</h3>

Définissez une configuration réseau par défaut pour toutes les sandboxes :

```python theme={"system"}
from cwsandbox import NetworkOptions, SandboxDefaults, Session

defaults = SandboxDefaults(
    network=NetworkOptions(egress_mode="internet"),
)

with Session(defaults) as session:
    # Toutes les sandboxes héritent de la configuration réseau
    sb1 = session.sandbox()  # Utilise egress_mode="internet"
    sb2 = session.sandbox()  # Utilise egress_mode="internet"

    # Remplacer la valeur pour une sandbox donnée
    sb3 = session.sandbox(network=NetworkOptions(egress_mode="user"))
```

<h2 id="annotations">
  Annotations
</h2>

Ajoutez des annotations de pod Kubernetes à vos sandboxes. Les annotations sont des paires clé-valeur de chaînes de caractères associées au pod sous-jacent. Elles sont utiles pour les intégrations qui lisent les métadonnées des pods, comme les ordonnanceurs, les outils d’allocation des coûts ou les automatisations externes.

```python theme={"system"}
sandbox = Sandbox.run(
    annotations={
        "team": "ml-infra",
        "experiment": "training-run-42",
    },
)
```

<h3 id="session-level-defaults">
  Valeurs par défaut au niveau de la session
</h3>

Définissez des annotations par défaut pour toutes les sandboxes d’une session :

```python theme={"system"}
defaults = SandboxDefaults(
    annotations={
        "team": "ml-infra",
        "managed-by": "sandbox-sdk",
    },
)

with Session(defaults) as session:
    # Hérite des annotations par défaut
    sb1 = session.sandbox()

    # Fusion : en cas de conflit de clés, les annotations explicites remplacent les valeurs par défaut
    sb2 = session.sandbox(
        annotations={"experiment": "run-42", "team": "ml-research"},
    )
    # sb2 reçoit : team=ml-research, managed-by=sandbox-sdk, experiment=run-42
```

<h3 id="merge-behavior">
  Comportement de fusion
</h3>

Lorsque vous fournissez à la fois `SandboxDefaults.annotations` et des `annotations` propres à chaque sandbox, le SDK les fusionne. En cas de conflit de clés, les valeurs explicitement définies pour la sandbox l’emportent, selon la même sémantique que pour `environment_variables`.

<h3 id="sunk-integration">
  Intégration avec SUNK
</h3>

Pour transmettre le contexte Slurm sous forme d’annotations de pod dans le cadre de l’intégration avec SUNK, consultez le [guide d’intégration du SUNK Pod Scheduler](/fr/products/sandboxes/profiles/sunk-integration#step-4-control-placement-with-slurm-annotations).

<h3 id="validation">
  Validation
</h3>

Le SDK ne valide ni les clés ni les valeurs des annotations. C’est le serveur qui valide les préfixes de clé réservés, le format des valeurs et le nombre maximum d’entrées.

<h2 id="secrets">
  Secrets
</h2>

Pour en savoir plus sur l’injection de secrets d’équipe Forge, les exigences d’authentification et des exemples en Python et TypeScript, consultez [Utiliser les secrets Forge](/fr/products/sandboxes/secrets).

<h2 id="timeouts">
  Délais d’expiration
</h2>

Quatre paramètres déterminent la durée d’exécution d’une sandbox et de ses opérations. Leurs noms se ressemblant, le tableau suivant indique ce que chacun d’eux limite.

| Paramètre | Limite | Appliqué par | Par défaut |
| - | - | - | - |
| `max_lifetime_seconds` | Durée de vie totale de la sandbox avant son arrêt automatique | Serveur | Valeur par défaut de la politique de l’exécuteur, ou 10 minutes si aucune n’est définie |
| `timeout_seconds` | Un seul appel `exec()`, `read_file()` ou `write_file()` | Client | À défaut, `request_timeout_seconds` |
| `max_timeout_seconds` | Durée pendant laquelle le serveur attend de placer une sandbox avant que la tentative n’échoue | Serveur | 30 secondes |
| `request_timeout_seconds` | Délai d’expiration HTTP côté client pour la plupart des appels de procédure à distance (RPC) | Client | 300 secondes |

Seul `max_lifetime_seconds` met fin à une sandbox. Les trois autres limitent des requêtes individuelles sans interrompre la sandbox.

<h3 id="max_lifetime_seconds">
  max\_lifetime\_seconds
</h3>

`max_lifetime_seconds` définit la durée de vie totale d'une sandbox, mesurée en temps réel. Lorsqu'une sandbox atteint cette durée, la plateforme y met fin, même si des tâches sont encore en cours.

Si vous ne définissez pas `max_lifetime_seconds`, la valeur par défaut de la politique de l'exécuteur s'applique. Si la politique ne fournit aucune valeur par défaut positive pour la durée de vie, la plateforme applique une durée de 10 minutes. Pour les tâches de longue durée, définissez explicitement cette valeur :

```python theme={"system"}
from cwsandbox import Sandbox

with Sandbox.run(max_lifetime_seconds=7200) as sandbox:  # 2 heures
    sandbox.exec(["python", "train.py"], timeout_seconds=7000).result()
```

Pour appliquer une même durée de vie à toutes les sandboxes créées par une session, définissez-la dans `SandboxDefaults` :

```python theme={"system"}
from cwsandbox import Sandbox, SandboxDefaults

defaults = SandboxDefaults(
    container_image="python:3.11",
    max_lifetime_seconds=3600,  # 1 heure
)

with Sandbox.run(defaults=defaults) as sandbox:
    sandbox.exec(["python", "-c", "print('working')"]).result()
```

Un argument `max_lifetime_seconds` explicite passé à `Sandbox.run()` est prioritaire sur la valeur définie dans `defaults`. Comme la valeur par défaut de cet argument est `None`, vous ne pouvez pas l'utiliser pour supprimer une durée de vie déjà définie par `defaults`.

La durée de vie maximale que vous pouvez demander est de 30 jours (2 592 000 secondes), aussi bien pour le placement sans serveur que pour le placement CKS. La plateforme rejette toute demande supérieure.

<Warning>
  Vous ne pouvez pas modifier `max_lifetime_seconds` une fois une sandbox démarrée. Aucune API ne permet de prolonger la durée de vie d'une sandbox en cours d'exécution : choisissez donc la valeur lors de sa création. Pour continuer à travailler au-delà de cette limite, capturez ce dont vous avez besoin et démarrez une nouvelle sandbox avec une durée de vie pouvant aller jusqu'à 30 jours.
</Warning>

Pour des exemples de création et les valeurs par défaut des politiques d'exécuteur CKS, consultez [Exécuter des sandboxes de longue durée](/fr/products/sandboxes/long-running-sandboxes).

<h4 id="behavior-when-the-lifetime-expires">
  Comportement à l’expiration de la durée de vie
</h4>

La plateforme applique la durée de vie en mettant fin à la tâche Kubernetes (Job) sous-jacente de la sandbox : l’arrêt est donc immédiat, et non progressif. En pratique, cela a deux conséquences importantes :

* Les processus exécutés dans la sandbox ne bénéficient pas du délai de grâce que fournit [`stop()`](/fr/products/sandboxes/client/guides/sandbox-lifecycle). Toute donnée qui n’a pas encore été écrite est perdue.
* Le client ne reçoit aucune erreur ni aucun motif distinct pour cet arrêt. Le SDK ne signale aucun motif d’arrêt sur un objet `Sandbox` : vous ne pouvez donc pas distinguer par programmation l’expiration de la durée de vie des autres échecs. Suivez vous-même l’âge des sandboxes de longue durée.

Définissez une durée de vie largement supérieure à la durée de travail prévue, et arrêtez explicitement les sandboxes une fois votre travail terminé, plutôt que de compter sur leur expiration.

<h3 id="timeout_seconds">
  timeout\_seconds
</h3>

`timeout_seconds` limite la durée d’une opération individuelle sur une sandbox en cours d’exécution :

```python theme={"system"}
result = sandbox.exec(
    ["python", "long_script.py"],
    timeout_seconds=300,  # 5 minutes
).result()
```

Ce paramètre détermine combien de temps le client attend une réponse. Si l’attente dépasse le délai d’expiration, le SDK lève `SandboxTimeoutError`. La sandbox, elle, continue de s’exécuter. Le décompte ne commence qu’une fois la sandbox passée à l’état `RUNNING`, si bien que le temps de démarrage n’est pas pris en compte.

Veillez à ce que `timeout_seconds` reste inférieur à la valeur `max_lifetime_seconds` de la sandbox. Une commande dont le délai d’expiration dépasse la durée de vie restante de la sandbox s’arrête lorsque la sandbox se termine.

<h3 id="max_timeout_seconds">
  max\_timeout\_seconds
</h3>

`max_timeout_seconds` limite la durée pendant laquelle le serveur tente de placer une sandbox sur un exécuteur avant que la tentative n'échoue. Il s'agit d'un budget de placement côté serveur, et non d'un délai d'expiration de lecture côté client. Il n'a aucune incidence sur la durée d'exécution ultérieure de la sandbox :

```python theme={"system"}
sandbox = Sandbox.run(max_timeout_seconds=120)
```

Le serveur accepte des valeurs comprises entre 1 et 300 secondes, avec une valeur par défaut de 30. Toute valeur supérieure à 300 est ramenée à 300. Si les sandboxes ne parviennent pas à démarrer lorsque le cluster est fortement sollicité, augmentez cette valeur. `max_timeout_seconds` est disponible dans `Sandbox.run()` et `session.sandbox()`, mais pas dans `SandboxDefaults`.

<h3 id="request_timeout_seconds">
  request\_timeout\_seconds
</h3>

`request_timeout_seconds` est le délai d'expiration HTTP côté client appliqué à la plupart des RPC. Il sert également de valeur de repli lorsqu'un appel ne transmet pas son propre `timeout_seconds`. Définissez-le dans `SandboxDefaults` :

```python theme={"system"}
defaults = SandboxDefaults(request_timeout_seconds=600.0)
```

L’interrogation du statut utilise plutôt `poll_rpc_timeout_seconds`, de sorte qu’une interrogation bloquée échoue rapidement au lieu de rester en attente pendant toute la durée du délai d’expiration de la requête. Pour la liste complète des options de réglage côté client, consultez la [référence SandboxDefaults](/fr/products/sandboxes/client/ref/core/sandbox-defaults).

<h2 id="complete-example">
  Exemple complet
</h2>

L’exemple suivant réunit des valeurs par défaut, des remplacements propres à chaque sandbox, des fichiers montés et des ports dans une configuration unique, à l’image du lancement d’une charge de travail en production :

```python theme={"system"}
from cwsandbox import NetworkOptions, ResourceOptions, Sandbox, SandboxDefaults

defaults = SandboxDefaults(
    container_image="python:3.11",
    max_lifetime_seconds=1800,  # 30 minutes
    tags=("production", "ml-pipeline"),
    resources=ResourceOptions(
        requests={"cpu": "4", "memory": "8Gi"},
        limits={"cpu": "4", "memory": "8Gi"},
    ),
    network=NetworkOptions(egress_mode="internet"),
)

with Sandbox.run(
    defaults=defaults,
    mounted_files=[
        {
            "path": "/app/config.yaml",
            "content": "model: gpt-4\nmax_tokens: 1000",
        },
    ],
    ports=[
        {"container_port": 8000},
    ],
) as sandbox:
    # Installer les dépendances
    sandbox.exec(["pip", "install", "fastapi", "uvicorn"]).result()

    # Lancer l’application
    result = sandbox.exec(
        ["python", "-c", "print('Server started')"],
        timeout_seconds=60,
    ).result()
    print(result.stdout)
```
