---
title: Déployer des workers auto-hébergés
url: https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-workers
description: "Choisissez comment les workers de sandbox auto-hébergés réclament le travail et où les sessions s'exécutent : en permanence ou déclenchés par webhook, dans un seul processus ou dans une sandbox par session."
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

Le [démarrage rapide](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes#quickstart) exécute un worker CLI `ant` qui interroge la file en continu et exécute chaque session dans un seul processus. Cette page présente les autres façons d'exécuter un worker et comment choisir entre elles.

## Choisir un modèle de déploiement

Lors du déploiement de workers, vous devez faire deux choix : comment le worker réclame le travail, et où chaque session s'exécute.

**Comment le worker réclame le travail :**

* **Toujours actif :** Un processus de longue durée interroge la file en continu et n'a besoin que de HTTPS sortant. C'est la configuration la plus simple.
* **Déclenché par webhook :** Un gestionnaire se réveille sur `session.status_run_started` et commence à interroger la file. Cela évite un « poller » (processus d'interrogation) inactif, mais nécessite un point de terminaison de [webhook](https://platform.claude.com/docs/fr/managed-agents/webhooks) accessible par Anthropic.

**Où chaque session s'exécute :**

* **Dans le processus :** Le worker qui réclame une session exécute également ses appels d'outils, dans un répertoire de travail partagé unique.
* **Une sandbox par session :** Un poller lance une nouvelle sandbox pour chaque session réclamée. Choisissez cette option pour une isolation plus forte : un système de fichiers neuf, des limites de ressources ou des contrôles réseau par session.

Les workers CLI et SDK prennent en charge différentes combinaisons :

| Capacité                                                                                                      | CLI `ant`                                              | SDK (Python, TypeScript, Go)               |
| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------ |
| Interrogation permanente                                                                                      | Oui                                                    | Oui                                        |
| Déclenché par webhook                                                                                         | Non                                                    | Oui                                        |
| Une sandbox par session                                                                                       | Oui                                                    | Oui                                        |
| [Magasins de mémoire](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-memory)        | Oui, avec les paramètres de synchronisation par défaut | Oui, avec une synchronisation configurable |
| [Outils personnalisés](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-custom-tools) | Non                                                    | Oui                                        |

Consultez la [référence des workers auto-hébergés](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-reference) pour chaque option de la CLI et du SDK. Pour plus de contrôle, appelez directement les [points de terminaison Environments Work](https://platform.claude.com/docs/fr/api/beta/environments/work) et implémentez votre propre worker.

## Exécuter un worker toujours actif

Démarrez un worker qui interroge la file en continu. Il s'authentifie avec la [clé d'environnement](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes#run-your-first-session) du démarrage rapide :

<CodeGroup exclude="shell:cURL, csharp, java, php, ruby">
  ```bash CLI
  ant beta:worker poll --workdir /workspace
  ```

  ```python Python
  import asyncio
  import contextlib
  import os
  import signal
  from anthropic import AsyncAnthropic
  from anthropic.lib.environments import EnvironmentWorker


  async def main() -> None:
      environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
      environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"]
      async with AsyncAnthropic(auth_token=environment_key) as client:
          worker = EnvironmentWorker(
              client,
              environment_id=environment_id,
              environment_key=environment_key,
              workdir="/workspace",
          )
          task = asyncio.create_task(worker.run())
          # Annuler la tâche, plutôt que de tuer le processus, permet au worker d'arrêter son
          # élément de travail en cours et de téléverser les fichiers mémoire modifiés avant de quitter.
          loop = asyncio.get_running_loop()
          for signum in (signal.SIGINT, signal.SIGTERM):
              loop.add_signal_handler(signum, task.cancel)
          with contextlib.suppress(asyncio.CancelledError):
              await task


  asyncio.run(main())
  ```

  ```typescript TypeScript
  import Anthropic from "@anthropic-ai/sdk";
  import { EnvironmentWorker } from "@anthropic-ai/sdk/helpers/beta/environments";

  const environmentKey = process.env.ANTHROPIC_ENVIRONMENT_KEY!;
  const environmentId = process.env.ANTHROPIC_ENVIRONMENT_ID!;
  const client = new Anthropic({ authToken: environmentKey });
  const controller = new AbortController();
  // L'abandon sur l'un ou l'autre signal permet au worker de téléverser les fichiers mémoire modifiés et de supprimer ses
  // répertoires de stockage avant la fin du processus.
  process.once("SIGINT", () => controller.abort());
  process.once("SIGTERM", () => controller.abort());

  await new EnvironmentWorker({
    client,
    environmentId,
    environmentKey,
    workdir: "/workspace",
    signal: controller.signal
  }).run();
  ```

  <CodeGroupItem language="C#">
    Le SDK C# ne dispose pas de `EnvironmentWorker`. Exécutez plutôt le worker CLI `ant` : `ant beta:worker poll --workdir /workspace`.
  </CodeGroupItem>

  ```go Go
  package main

  import (
  	"context"
  	"log"
  	"os"
  	"os/signal"
  	"syscall"

  	"github.com/anthropics/anthropic-sdk-go"
  	"github.com/anthropics/anthropic-sdk-go/lib/environments"
  	"github.com/anthropics/anthropic-sdk-go/option"
  )

  func main() {
  	environmentKey := os.Getenv("ANTHROPIC_ENVIRONMENT_KEY")
  	environmentID := os.Getenv("ANTHROPIC_ENVIRONMENT_ID")

  	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
  	defer stop()

  	client := anthropic.NewClient(option.WithAuthToken(environmentKey))

  	worker := environments.NewEnvironmentWorker(client, environments.EnvironmentWorkerOptions{
  		EnvironmentID:  environmentID,
  		EnvironmentKey: environmentKey,
  		Workdir:        "/workspace",
  	})
  	if err := worker.Run(ctx); err != nil {
  		log.Fatalf("worker: %v", err)
  	}
  }
  ```

  <CodeGroupItem language="Java">
    Le SDK Java ne dispose pas de `EnvironmentWorker`. Exécutez plutôt le worker CLI `ant` : `ant beta:worker poll --workdir /workspace`.
  </CodeGroupItem>

  <CodeGroupItem language="PHP">
    Le SDK PHP ne dispose pas de `EnvironmentWorker`. Exécutez plutôt le worker CLI `ant` : `ant beta:worker poll --workdir /workspace`.
  </CodeGroupItem>

  <CodeGroupItem language="Ruby">
    Le SDK Ruby ne dispose pas de `EnvironmentWorker`. Exécutez plutôt le worker CLI `ant` : `ant beta:worker poll --workdir /workspace`.
  </CodeGroupItem>
</CodeGroup>

## Déclencher des workers à partir de webhooks

<Steps>
  <Step title="S'abonner aux webhooks de session">
    Dans la [Console](https://platform.claude.com/settings/workspaces/default/webhooks), définissez un point de terminaison de webhook qui écoute les événements `session.status_run_started`. Consultez [Webhooks](https://platform.claude.com/docs/fr/managed-agents/webhooks) pour plus de détails.
  </Step>

  <Step title="Exporter la clé de signature du webhook">
    En plus de l'ID et de la clé d'environnement du [démarrage rapide](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes#run-your-first-session), exportez la clé de signature du webhook sur l'hôte de votre gestionnaire. Le gestionnaire l'utilise pour vérifier les charges utiles entrantes.

    ```bash
    export ANTHROPIC_WEBHOOK_SIGNING_KEY="whsec_..."
    ```
  </Step>

  <Step title="Implémenter le gestionnaire de webhook">
    Invoquez le worker lorsque `session.status_run_started` se déclenche. Le gestionnaire vide la file et transmet chaque élément de travail réclamé à `handle_item()` (typescript: `handleItem()`; go: `HandleItem()`), qui télécharge les skills, exécute les appels d'outils, renvoie les résultats et se termine.

    <CodeGroup exclude="shell, csharp, java, php, ruby">
      <CodeGroupItem>
        Pour vérifier les signatures des webhooks, installez l'extra webhooks : `pip install "anthropic[webhooks]"`.

        ```python Python
        import asyncio
        import os
        import anthropic
        import standardwebhooks  # installed by the anthropic[webhooks] extra

        environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
        environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"]
        client = anthropic.AsyncAnthropic(
            auth_token=environment_key,
        )
        # Annulé par shutdown() afin qu'un élément de travail en cours puisse téléverser les fichiers mémoire modifiés et
        # supprimer ses répertoires de store avant la fin du processus.
        inflight: set[asyncio.Task[None]] = set()


        # Attendez ceci depuis le hook d'arrêt de l'hôte, par ex. un arrêt de lifespan ASGI (le code après
        # `yield` dans un lifespan FastAPI), qu'uvicorn exécute sur SIGTERM. uvicorn laisse les requêtes ouvertes
        # se terminer avant l'exécution de ce hook ; définissez --timeout-graceful-shutdown pour borner l'attente.
        async def shutdown() -> None:
            for task in inflight:
                task.cancel()
            await asyncio.gather(*inflight, return_exceptions=True)


        async def handle(raw: bytes, headers: dict[str, str]) -> tuple[dict[str, str], int]:
            try:
                event = client.beta.webhooks.unwrap(raw.decode(), headers=headers)
            except standardwebhooks.WebhookVerificationError:
                return {"error": "signature verification failed"}, 401
            if event.data.type != "session.status_run_started":
                return {"status": "ignored"}, 200
            task = asyncio.create_task(run_queued_work())
            inflight.add(task)
            task.add_done_callback(inflight.discard)
            try:
                # Protégé : une livraison abandonnée ou expirée ne doit pas annuler l'élément ; shutdown() le fait.
                await asyncio.shield(task)
            except asyncio.CancelledError:
                return {"status": "shutting down"}, 503
            return {"status": "ok"}, 200


        async def run_queued_work() -> None:
            async for work in client.beta.environments.work.poller(
                environment_id=environment_id,
                environment_key=environment_key,
                block_ms=None,
                reclaim_older_than_ms=2000,
                drain=True,
                auto_stop=False,
            ):
                await client.beta.environments.work.worker(workdir="/workspace").handle_item(
                    work_id=work.id,
                    environment_id=environment_id,
                    session_id=work.data.id,
                    environment_key=environment_key,
                    # Le secret par session est ce qui permet au worker de monter les stores mémoire de la session.
                    work_secret=work.secret,
                )
        ```
      </CodeGroupItem>

      ```typescript TypeScript
      import Anthropic from "@anthropic-ai/sdk";

      const environmentKey = process.env.ANTHROPIC_ENVIRONMENT_KEY!;
      const environmentId = process.env.ANTHROPIC_ENVIRONMENT_ID!;
      const client = new Anthropic({
        authToken: environmentKey
      });
      // Appelez shutdown.abort() depuis le gestionnaire SIGTERM/SIGINT de l'hôte, en plus de fermer le serveur,
      // puis attendez les appels handle() en cours avant de quitter : l'abort permet à un élément de travail en cours
      // de téléverser les fichiers mémoire modifiés et de supprimer d'abord ses répertoires de store.
      export const shutdown = new AbortController();

      export async function handle(req: Request): Promise<Response> {
        // N'accusez jamais réception d'une livraison dont le travail ne s'exécutera pas ici ; un 503 fait réessayer l'expéditeur.
        if (shutdown.signal.aborted) {
          return Response.json({ status: "shutting down" }, { status: 503 });
        }
        const body = await req.text();
        let event;
        try {
          event = client.beta.webhooks.unwrap(body, { headers: Object.fromEntries(req.headers) });
        } catch {
          return new Response("signature verification failed", { status: 401 });
        }
        if (event.data.type !== "session.status_run_started") {
          return Response.json({ status: "ignored" });
        }

        for await (const work of client.beta.environments.work.poller({
          environmentId,
          environmentKey,
          blockMs: null,
          reclaimOlderThanMs: 2000,
          drain: true,
          autoStop: false,
          signal: shutdown.signal
        })) {
          await client.beta.environments.work.worker({ workdir: "/workspace" }).handleItem({
            workId: work.id,
            environmentId,
            sessionId: work.data.id,
            environmentKey,
            // Le secret par session est ce qui permet au worker de monter les stores de mémoire de la session.
            workSecret: work.secret ?? undefined,
            signal: shutdown.signal
          });
        }
        // Le poller et handleItem retournent silencieusement en cas d'abort, donc un drainage interrompu aboutit ici.
        if (shutdown.signal.aborted) {
          return Response.json({ status: "shutting down" }, { status: 503 });
        }
        return Response.json({ status: "ok" });
      }
      ```

      <CodeGroupItem language="C#">
        Le SDK C# ne dispose pas de `EnvironmentWorker`. Pour traiter des éléments de travail depuis votre propre code, appelez les [points de terminaison Environments Work](https://platform.claude.com/docs/fr/api/beta/environments/work).
      </CodeGroupItem>

      ```go Go
      package main

      import (
      	"context"
      	"encoding/json"
      	"errors"
      	"io"
      	"log/slog"
      	"net/http"
      	"os"
      	"os/signal"
      	"syscall"

      	"github.com/anthropics/anthropic-sdk-go"
      	"github.com/anthropics/anthropic-sdk-go/lib/environments"
      	"github.com/anthropics/anthropic-sdk-go/option"
      	"github.com/anthropics/anthropic-sdk-go/packages/param"
      )

      var (
      	environmentKey = os.Getenv("ANTHROPIC_ENVIRONMENT_KEY")
      	environmentID  = os.Getenv("ANTHROPIC_ENVIRONMENT_ID")
      	client         = anthropic.NewClient(
      		option.WithAuthToken(environmentKey),
      		option.WithWebhookKey(os.Getenv("ANTHROPIC_WEBHOOK_SIGNING_KEY")),
      	)
      	worker = environments.NewEnvironmentWorker(client, environments.EnvironmentWorkerOptions{
      		Workdir: "/workspace",
      	})
      	// Annulé sur SIGINT ou SIGTERM (défini dans main) afin qu'un élément de travail en cours puisse
      	// téléverser les fichiers mémoire modifiés et supprimer ses répertoires de store avant de quitter.
      	shutdown context.Context
      )

      func handle(w http.ResponseWriter, r *http.Request) {
      	body, err := io.ReadAll(r.Body)
      	if err != nil {
      		http.Error(w, "bad request", http.StatusBadRequest)
      		return
      	}
      	event, err := client.Beta.Webhooks.Unwrap(body, r.Header)
      	if err != nil {
      		http.Error(w, "signature verification failed", http.StatusUnauthorized)
      		return
      	}
      	if event.Data.Type != "session.status_run_started" {
      		json.NewEncoder(w).Encode(map[string]string{"status": "ignored"})
      		return
      	}

      	// Le SDK Go ne fournit pas de raccourci RunOne : vider les éléments en attente
      	// avec WorkPoller et exécuter chacun avec HandleItem.
      	// Se détacher de r.Context() : la session peut survivre au délai de livraison du webhook.
      	// Le contexte d'arrêt global au processus termine quand même l'élément proprement sur SIGTERM.
      	ctx := shutdown
      	poller := environments.NewWorkPoller(ctx, client, environments.WorkPollerOptions{
      		EnvironmentID:      environmentID,
      		EnvironmentKey:     environmentKey,
      		BlockMs:            param.Null[int64](),
      		ReclaimOlderThanMs: param.NewOpt[int64](2000),
      		Drain:              true,
      		AutoStop:           param.NewOpt(false),
      	})
      	defer poller.Close()
      	for poller.Next() {
      		item := poller.Current()
      		if err := worker.HandleItem(ctx, environments.HandleItemOptions{
      			WorkID:         item.ID,
      			EnvironmentID:  item.EnvironmentID,
      			SessionID:      item.Data.ID,
      			EnvironmentKey: environmentKey,
      			// Le secret par session est ce qui permet au worker de monter les stores mémoire de la session.
      			WorkSecret: item.Secret,
      		}); err != nil {
      			slog.Error("handle work item", "work_id", item.ID, "err", err)
      			http.Error(w, "internal error", http.StatusInternalServerError)
      			return
      		}
      	}
      	if err := poller.Err(); err != nil {
      		slog.Error("poll work queue", "err", err)
      		http.Error(w, "internal error", http.StatusInternalServerError)
      		return
      	}
      	json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
      }

      func main() {
      	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
      	defer stop()
      	shutdown = ctx

      	server := &http.Server{Addr: ":8080"}
      	http.HandleFunc("POST /webhook", handle)
      	go func() {
      		if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
      			slog.Error("http server", "err", err)
      			os.Exit(1)
      		}
      	}()
      	// Sur un signal, cesser d'accepter les livraisons et ne retourner qu'après que les gestionnaires
      	// en cours, et donc le démontage mémoire de leurs éléments de travail, soient terminés.
      	<-ctx.Done()
      	if err := server.Shutdown(context.Background()); err != nil {
      		slog.Error("http shutdown", "err", err)
      	}
      }
      ```

      <CodeGroupItem language="Java">
        Le SDK Java ne dispose pas de `EnvironmentWorker`. Pour traiter des éléments de travail depuis votre propre code, appelez les [points de terminaison Environments Work](https://platform.claude.com/docs/fr/api/beta/environments/work).
      </CodeGroupItem>

      <CodeGroupItem language="PHP">
        Le SDK PHP ne dispose pas de `EnvironmentWorker`. Pour traiter des éléments de travail depuis votre propre code, appelez les [points de terminaison Environments Work](https://platform.claude.com/docs/fr/api/beta/environments/work).
      </CodeGroupItem>

      <CodeGroupItem language="Ruby">
        Le SDK Ruby ne dispose pas de `EnvironmentWorker`. Pour traiter des éléments de travail depuis votre propre code, appelez les [points de terminaison Environments Work](https://platform.claude.com/docs/fr/api/beta/environments/work).
      </CodeGroupItem>
    </CodeGroup>

    Comme le gestionnaire réclame lui-même le travail, il doit [transmettre le secret de l'élément de travail](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-workers#forward-the-work-items-secret), comme le fait ici l'argument `work_secret` (typescript: `workSecret`; go: `WorkSecret`).
  </Step>
</Steps>

Ce gestionnaire exécute chaque élément réclamé dans un seul processus sur un seul hôte. Si vos sessions attachent le même magasin de mémoire, consultez [Isoler les sessions qui partagent un magasin](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-memory#isolate-sessions-that-share-a-store).

## Exécuter une sandbox par session

Un poller sur l'hôte réclame le travail et appelle votre script une fois par élément de travail. Le script lance une sandbox pour cette session unique.

<Steps>
  <Step title="Construire l'image de la sandbox">
    Installez `ant` et définissez `ant beta:worker run` comme point d'entrée. Lorsqu'une sandbox démarre, elle lit les détails de la session à partir des variables d'environnement, traite cette session, puis se termine. L'image de base doit fournir `/bin/bash` ; `curl` n'est utilisé qu'au moment de la construction.

    ```dockerfile
    FROM your-base-image
    ARG ANT_VERSION=1.42.0
    ARG TARGETARCH
    RUN ARCH=$([ "$TARGETARCH" = "arm64" ] && echo arm64 || echo amd64) && \
        curl -fsSL "https://github.com/anthropics/anthropic-cli/releases/download/v${ANT_VERSION}/ant_${ANT_VERSION}_linux_${ARCH}.tar.gz" \
          | tar -xz -C /usr/local/bin ant
    WORKDIR /workspace
    VOLUME /workspace
    ENTRYPOINT ["ant", "beta:worker", "run"]
    ```
  </Step>

  <Step title="Écrire le script de lancement">
    Le script transmet les détails de la session à une nouvelle sandbox. Il nécessite `jq` sur l'hôte du poller.

    ```bash
    #!/bin/bash
    # spawn.sh : appelé une fois par élément de travail réclamé.
    # L'élément de travail réclamé arrive au format JSON sur stdin.
    ANTHROPIC_WORK_SECRET="$(jq -r '.secret // empty')"
    export ANTHROPIC_WORK_SECRET
    mkdir -p "/host/outputs/$ANTHROPIC_SESSION_ID"
    exec docker run --rm \
      -e ANTHROPIC_SESSION_ID -e ANTHROPIC_ENVIRONMENT_KEY \
      -e ANTHROPIC_WORK_ID -e ANTHROPIC_ENVIRONMENT_ID -e ANTHROPIC_BASE_URL \
      -e ANTHROPIC_WORK_SECRET \
      -v "/host/outputs/$ANTHROPIC_SESSION_ID":/workspace \
      your-image
    ```

    Le poller définit les variables `ANTHROPIC_*` que le script transmet, à l'exception du secret. Consultez [Variables d'environnement](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-reference#environment-variables).

    `/host/outputs` est un répertoire de l'hôte que vous choisissez. Le monter sur `/workspace` vous permet de récupérer les livrables de la session après la fin de la sandbox. Le montage récupère également l'arborescence `skills/` téléchargée et tous les fichiers intermédiaires.
  </Step>

  <Step title="Démarrer le poller">
    ```bash
    ant beta:worker poll --on-work ./spawn.sh
    ```
  </Step>
</Steps>

### Transmettre le secret de l'élément de travail

Chaque élément de travail réclamé peut porter un `secret` (csharp, go: `Secret`) propre à la session, émis par Anthropic. Le worker qui exécute la session en a besoin pour monter les [magasins de mémoire](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-memory).

Un worker qui réclame et exécute les sessions dans un seul processus (`ant beta:worker poll` sans `--on-work`, ou `EnvironmentWorker` avec `run()` (go: `Run()`)) transmet lui-même le secret. Lorsque votre propre code se situe entre la réclamation et le worker, c'est à vous de le transmettre :

| Vous réclamez le travail avec                               | Le secret arrive sous la forme                                                          | Transmettez-le au worker sous la forme                                                                                                                                                                   |
| ----------------------------------------------------------- | --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ant beta:worker poll --on-work`                            | Le champ `secret` du JSON de l'élément de travail sur l'entrée standard de votre script | `ANTHROPIC_WORK_SECRET` dans l'environnement de la sandbox                                                                                                                                               |
| `work.poller()` (go: `environments.NewWorkPoller()`) du SDK | Le champ `secret` (go: `Secret`) de chaque élément de travail réclamé                   | `ANTHROPIC_WORK_SECRET` dans l'environnement de la sandbox, ou l'argument `work_secret` (typescript: `workSecret`; go: `WorkSecret`) de `handle_item()` (typescript: `handleItem()`; go: `HandleItem()`) |

Transmettez le secret uniquement à la sandbox qui sert cette session, et ne le journalisez jamais. Consultez [Modèle de sécurité](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-security) pour comprendre son lien avec la clé d'environnement.

### Lancer des sandboxes depuis le poller du SDK

Pour réclamer le travail depuis votre propre code au lieu de `ant beta:worker poll --on-work`, utilisez `work.poller()` (go: `environments.NewWorkPoller()`). Il interroge la file et vous fournit chaque session réclamée, et c'est vous qui lancez la sandbox :

<CodeGroup exclude="shell, csharp, java, php, ruby">
  <CodeGroupItem language="cURL">
    Réclamer du travail en boucle et lancer une sandbox pour chaque session nécessite plus de logique qu'une seule commande shell. Depuis le shell, exécutez `ant beta:worker poll --on-work` avec un script de lancement, comme dans [Exécuter une sandbox par session](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-workers#run-one-sandbox-per-session).
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    Pour réclamer du travail depuis le shell et lancer une sandbox pour chaque session, exécutez `ant beta:worker poll --on-work` avec un script de lancement, comme dans [Exécuter une sandbox par session](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-workers#run-one-sandbox-per-session).
  </CodeGroupItem>

  ```python Python
  import asyncio
  import os

  from anthropic import AsyncAnthropic
  from anthropic.types.beta.environments import BetaSelfHostedWork

  SANDBOX_ENV = (
      "ANTHROPIC_ENVIRONMENT_ID",
      "ANTHROPIC_ENVIRONMENT_KEY",
      "ANTHROPIC_WORK_ID",
      "ANTHROPIC_SESSION_ID",
      "ANTHROPIC_WORK_SECRET",
      "ANTHROPIC_BASE_URL",  # forwarded only when set on this host
  )


  async def launch_container(work: BetaSelfHostedWork) -> None:
      print(f"claimed session {work.data.id}")
      # Remplacez `docker run` par votre propre lanceur de sandbox. Transmettez la clé
      # d'environnement (jamais votre clé API) et le secret par session de l'élément de travail : le worker
      # à l'intérieur a besoin du secret pour monter les magasins de mémoire de la session.
      env = os.environ | {
          "ANTHROPIC_WORK_ID": work.id,
          "ANTHROPIC_SESSION_ID": work.data.id,
          "ANTHROPIC_WORK_SECRET": work.secret or "",
      }
      forward = [arg for name in SANDBOX_ENV for arg in ("-e", name)]
      launcher = await asyncio.create_subprocess_exec(
          "docker", "run", "--rm", "--detach", *forward, "your-image", env=env
      )
      await launcher.wait()


  async def main() -> None:
      environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
      environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"]
      async with AsyncAnthropic(auth_token=environment_key) as client:
          async for work in client.beta.environments.work.poller(
              environment_id=environment_id,
              environment_key=environment_key,
              auto_stop=False,  # the launched sandbox owns the stop call
          ):
              await launch_container(work)


  asyncio.run(main())
  ```

  ```typescript TypeScript
  import { spawn } from "node:child_process";
  import { once } from "node:events";
  import Anthropic from "@anthropic-ai/sdk";
  import { WorkPoller } from "@anthropic-ai/sdk/helpers/beta/environments";
  import type { BetaSelfHostedWork } from "@anthropic-ai/sdk/resources/beta/environments";

  const SANDBOX_ENV = [
    "ANTHROPIC_ENVIRONMENT_ID",
    "ANTHROPIC_ENVIRONMENT_KEY",
    "ANTHROPIC_WORK_ID",
    "ANTHROPIC_SESSION_ID",
    "ANTHROPIC_WORK_SECRET",
    "ANTHROPIC_BASE_URL" // forwarded only when set on this host
  ];

  const environmentKey = process.env.ANTHROPIC_ENVIRONMENT_KEY!;
  const environmentId = process.env.ANTHROPIC_ENVIRONMENT_ID!;
  const client = new Anthropic({ authToken: environmentKey });

  async function launchContainer(work: BetaSelfHostedWork): Promise<void> {
    console.log(`claimed session ${work.data.id}`);
    // Remplacez `docker run` par votre propre lanceur de sandbox. Transmettez la clé
    // : d'environnement (jamais votre clé API) et le secret par session de l'élément de travail : le worker
    // à l'intérieur a besoin du secret pour monter les magasins de mémoire de la session.
    const env = {
      ...process.env,
      ANTHROPIC_WORK_ID: work.id,
      ANTHROPIC_SESSION_ID: work.data.id,
      ANTHROPIC_WORK_SECRET: work.secret ?? ""
    };
    const forward = SANDBOX_ENV.flatMap((name) => ["-e", name]);
    const launcher = spawn("docker", ["run", "--rm", "--detach", ...forward, "your-image"], {
      env,
      stdio: "inherit"
    });
    await once(launcher, "close");
  }

  const poller = new WorkPoller({
    client,
    environmentId,
    environmentKey,
    autoStop: false // the launched sandbox owns the stop call
  });

  for await (const work of poller) {
    await launchContainer(work);
  }
  ```

  <CodeGroupItem language="C#">
    Le SDK C# ne dispose pas d'un utilitaire qui interroge la file de travail. Pour réclamer du travail depuis votre propre code, appelez les [points de terminaison Environments Work](https://platform.claude.com/docs/fr/api/beta/environments/work).
  </CodeGroupItem>

  ```go Go
  package main

  import (
  	"context"
  	"fmt"
  	"log"
  	"os"
  	"os/exec"

  	"github.com/anthropics/anthropic-sdk-go"
  	"github.com/anthropics/anthropic-sdk-go/lib/environments"
  	"github.com/anthropics/anthropic-sdk-go/option"
  	"github.com/anthropics/anthropic-sdk-go/packages/param"
  )

  var sandboxEnv = []string{
  	"ANTHROPIC_ENVIRONMENT_ID",
  	"ANTHROPIC_ENVIRONMENT_KEY",
  	"ANTHROPIC_WORK_ID",
  	"ANTHROPIC_SESSION_ID",
  	"ANTHROPIC_WORK_SECRET",
  	"ANTHROPIC_BASE_URL", // forwarded only when set on this host
  }

  func launchContainer(ctx context.Context, work *anthropic.BetaSelfHostedWork) error {
  	fmt.Printf("claimed session %s\n", work.Data.ID)
  	// Remplacez `docker run` par votre propre lanceur de sandbox. Transmettez la clé
  	// :d'environnement (jamais votre clé API) et le secret par session de l'élément de travail : le worker
  	// à l'intérieur a besoin du secret pour monter les magasins de mémoire de la session.
  	args := []string{"run", "--rm", "--detach"}
  	for _, name := range sandboxEnv {
  		args = append(args, "-e", name)
  	}
  	launcher := exec.CommandContext(ctx, "docker", append(args, "your-image")...)
  	launcher.Env = append(os.Environ(),
  		"ANTHROPIC_WORK_ID="+work.ID,
  		"ANTHROPIC_SESSION_ID="+work.Data.ID,
  		"ANTHROPIC_WORK_SECRET="+work.Secret,
  	)
  	launcher.Stdout, launcher.Stderr = os.Stdout, os.Stderr
  	return launcher.Run()
  }

  func main() {
  	environmentID := os.Getenv("ANTHROPIC_ENVIRONMENT_ID")
  	environmentKey := os.Getenv("ANTHROPIC_ENVIRONMENT_KEY")

  	client := anthropic.NewClient(option.WithAuthToken(environmentKey))

  	ctx := context.Background()

  	poller := environments.NewWorkPoller(ctx, client, environments.WorkPollerOptions{
  		EnvironmentID:  environmentID,
  		EnvironmentKey: environmentKey,
  		AutoStop:       param.NewOpt(false), // the launched sandbox owns the stop call
  	})
  	defer poller.Close()

  	for work, err := range poller.All() {
  		if err != nil {
  			log.Fatal(err)
  		}
  		if err := launchContainer(ctx, work); err != nil {
  			log.Fatal(err)
  		}
  	}
  }
  ```

  <CodeGroupItem language="Java">
    Le SDK Java ne dispose pas d'un utilitaire qui interroge la file de travail. Pour réclamer du travail depuis votre propre code, appelez les [points de terminaison Environments Work](https://platform.claude.com/docs/fr/api/beta/environments/work).
  </CodeGroupItem>

  <CodeGroupItem language="PHP">
    Le SDK PHP ne dispose pas d'un utilitaire qui interroge la file de travail. Pour réclamer du travail depuis votre propre code, appelez les [points de terminaison Environments Work](https://platform.claude.com/docs/fr/api/beta/environments/work).
  </CodeGroupItem>

  <CodeGroupItem language="Ruby">
    Le SDK Ruby ne dispose pas d'un utilitaire qui interroge la file de travail. Pour réclamer du travail depuis votre propre code, appelez les [points de terminaison Environments Work](https://platform.claude.com/docs/fr/api/beta/environments/work).
  </CodeGroupItem>
</CodeGroup>

### Exécuter le worker du SDK dans la sandbox

Remplacez le point d'entrée `ant beta:worker run` par un point d'entrée SDK lorsque la sandbox doit [servir des outils personnalisés](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-custom-tools) ou utiliser des [paramètres de synchronisation de mémoire non par défaut](https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-memory#configure-sync). Le point d'entrée construit `EnvironmentWorker` et appelle `handle_item()` (typescript: `handleItem()`; go: `HandleItem()`), qui lit les mêmes variables `ANTHROPIC_*` que celles transmises par le script de lancement.

<CodeGroup exclude="shell, csharp, java, php, ruby">
  ```python Python
  import asyncio
  import contextlib
  import os
  import signal
  from anthropic import AsyncAnthropic
  from anthropic.lib.environments import EnvironmentWorker


  async def main() -> None:
      async with AsyncAnthropic(
          auth_token=os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
      ) as client:
          worker = EnvironmentWorker(client, workdir="/workspace")
          # Sans arguments, handle_item() lit les variables ANTHROPIC_* que le script de lancement
          # a transmises, y compris ANTHROPIC_WORK_SECRET.
          task = asyncio.create_task(worker.handle_item())
          # Annuler la tâche lorsque le conteneur est arrêté permet au worker de téléverser
          # les fichiers mémoire modifiés et de supprimer les répertoires du store avant de quitter.
          loop = asyncio.get_running_loop()
          for signum in (signal.SIGINT, signal.SIGTERM):
              loop.add_signal_handler(signum, task.cancel)
          with contextlib.suppress(asyncio.CancelledError):
              await task


  asyncio.run(main())
  ```

  ```typescript TypeScript
  import Anthropic from "@anthropic-ai/sdk";
  import { EnvironmentWorker } from "@anthropic-ai/sdk/helpers/beta/environments";

  const client = new Anthropic({ authToken: process.env.ANTHROPIC_ENVIRONMENT_KEY });
  const controller = new AbortController();
  // Abandonner lorsque le conteneur est arrêté permet au worker de téléverser les fichiers mémoire
  // modifiés et de supprimer les répertoires du store avant de quitter.
  process.once("SIGTERM", () => controller.abort());
  process.once("SIGINT", () => controller.abort());

  // Sans argument, handleItem() lit les variables ANTHROPIC_* que le script de lancement
  // a transmises, y compris ANTHROPIC_WORK_SECRET.
  await new EnvironmentWorker({
    client,
    workdir: "/workspace",
    signal: controller.signal
  }).handleItem();
  ```

  <CodeGroupItem language="C#">
    Le SDK C# ne dispose pas de `EnvironmentWorker`.
  </CodeGroupItem>

  ```go Go
  package main

  import (
  	"context"
  	"log"
  	"os"
  	"os/signal"
  	"syscall"

  	"github.com/anthropics/anthropic-sdk-go"
  	"github.com/anthropics/anthropic-sdk-go/lib/environments"
  	"github.com/anthropics/anthropic-sdk-go/option"
  )

  func main() {
  	// Annuler le contexte lorsque le conteneur est arrêté permet au worker de téléverser
  	// les fichiers mémoire modifiés et de supprimer les répertoires du store avant de quitter.
  	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
  	defer stop()

  	client := anthropic.NewClient(option.WithAuthToken(os.Getenv("ANTHROPIC_ENVIRONMENT_KEY")))
  	worker := environments.NewEnvironmentWorker(client, environments.EnvironmentWorkerOptions{
  		Workdir: "/workspace",
  	})
  	// Avec des options à valeur zéro, HandleItem lit les variables ANTHROPIC_* que le script
  	// de lancement a transmises, y compris ANTHROPIC_WORK_SECRET.
  	if err := worker.HandleItem(ctx, environments.HandleItemOptions{}); err != nil {
  		log.Fatalf("worker: %v", err)
  	}
  }
  ```

  <CodeGroupItem language="Java">
    Le SDK Java ne dispose pas de `EnvironmentWorker`.
  </CodeGroupItem>

  <CodeGroupItem language="PHP">
    Le SDK PHP ne dispose pas de `EnvironmentWorker`.
  </CodeGroupItem>

  <CodeGroupItem language="Ruby">
    Le SDK Ruby ne dispose pas de `EnvironmentWorker`.
  </CodeGroupItem>
</CodeGroup>

## Préparer des fichiers pour une session

Anthropic ne monte pas de fichiers ni de dépôts GitHub dans les sandboxes auto-hébergées. Pour rendre disponibles des fichiers propres à une session :

1. Transmettez des références de fichiers, comme un chemin S3 ou un SHA de commit, dans le champ `metadata` de la session.
2. Dans votre script de lancement ou votre gestionnaire `--on-work`, récupérez la session (`GET /v1/sessions/{session_id}`) et lisez `metadata`. L'élément de travail réclamé contient l'ID de session, mais pas les métadonnées.
3. Placez les fichiers dans le répertoire de travail avant le début de l'exécution des outils.

<CodeGroup>
  ```bash cURL
  curl -sS --fail-with-body https://api.anthropic.com/v1/sessions \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    -d '{
      "agent": "'"$AGENT_ID"'",
      "environment_id": "'"$ANTHROPIC_ENVIRONMENT_ID"'",
      "metadata": {"input_file": "s3://my-bucket/data.csv"}
    }'
  ```

  ```bash CLI
  ant beta:sessions create \
    --agent "$AGENT_ID" \
    --environment-id "$ANTHROPIC_ENVIRONMENT_ID" \
    --metadata '{"input_file": "s3://my-bucket/data.csv"}'
  ```

  ```python Python
  session = client.beta.sessions.create(
      agent=agent.id,
      environment_id=environment.id,
      metadata={"input_file": "s3://my-bucket/data.csv"},
  )
  ```

  ```typescript TypeScript
  const session = await client.beta.sessions.create({
    agent: agent.id,
    environment_id: environment.id,
    metadata: { input_file: "s3://my-bucket/data.csv" }
  });
  ```

  ```csharp C#
  var session = await client.Beta.Sessions.Create(new()
  {
      Agent = agent.ID,
      EnvironmentID = environment.ID,
      Metadata = new Dictionary<string, string> { ["input_file"] = "s3://my-bucket/data.csv" },
  });
  ```

  ```go Go
  session, err := client.Beta.Sessions.New(ctx, anthropic.BetaSessionNewParams{
  	Agent:         anthropic.BetaSessionNewParamsAgentUnion{OfString: anthropic.String(agent.ID)},
  	EnvironmentID: environment.ID,
  	Metadata: map[string]string{
  		"input_file": "s3://my-bucket/data.csv",
  	},
  })
  if err != nil {
  	panic(err)
  }
  ```

  ```java Java
  var session = client.beta().sessions().create(SessionCreateParams.builder()
      .agent(agent.id())
      .environmentId(environment.id())
      .metadata(SessionCreateParams.Metadata.builder()
          .putAdditionalProperty("input_file", JsonValue.from("s3://my-bucket/data.csv"))
          .build())
      .build());
  ```

  ```php PHP
  $session = $client->beta->sessions->create(
      agent: $agent->id,
      environmentID: $environment->id,
      metadata: ['input_file' => 's3://my-bucket/data.csv'],
  );
  ```

  ```ruby Ruby
  session = client.beta.sessions.create(
    agent: agent.id,
    environment_id: environment.id,
    metadata: {input_file: "s3://my-bucket/data.csv"}
  )
  ```
</CodeGroup>

## Étapes suivantes

<CardGroup cols={2}>
  <Card title="Surveiller et dépanner" icon="lightning" href="https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-operations">
    Consultez la profondeur de la file, arrêtez proprement les sessions et les workers, et corrigez les défaillances courantes.
  </Card>

  <Card title="Modèle de sécurité" icon="lock" href="https://platform.claude.com/docs/fr/managed-agents/self-hosted-sandboxes-security">
    Modèle de responsabilité partagée pour les environnements de sandbox auto-hébergés.
  </Card>
</CardGroup>
