---
title: Outils serveur
url: https://platform.claude.com/docs/fr/agents-and-tools/tool-use/server-tools
description: "Travaillez avec les outils exécutés par Anthropic : blocs server_tool_use, continuation pause_turn, tours mêlant outils serveur et outils client, et filtrage de domaines."
---

Les outils exécutés côté serveur partagent ces mécanismes : le bloc `server_tool_use`, la continuation `pause_turn`, les tours qui mêlent outils serveur et outils client, l'éligibilité au « Zero Data Retention » (rétention zéro des données), ou ZDR, et le filtrage de domaines. Pour les outils individuels, consultez la [référence des outils](https://platform.claude.com/docs/fr/agents-and-tools/tool-use/tool-reference).

## Le bloc server\_tool\_use

Le bloc `server_tool_use` apparaît dans la réponse de Claude lorsqu'un outil exécuté côté serveur s'exécute. Son champ `id` utilise le préfixe `srvtoolu_` pour le distinguer des appels d'outils client :

```json
{
  "type": "server_tool_use",
  "id": "srvtoolu_01A2B3C4D5E6F7G8H9",
  "name": "web_search",
  "input": { "query": "latest quantum computing breakthroughs" }
}
```

L'API exécute l'outil en interne. Vous voyez l'appel et son résultat dans la réponse, mais vous ne gérez pas l'exécution. Contrairement aux blocs `tool_use` client, vous n'avez pas besoin de répondre avec un `tool_result`. Le bloc de résultat de l'outil (par exemple, `web_search_tool_result` pour la recherche web) suit le bloc `server_tool_use` dans le même tour de l'assistant, apparié par `tool_use_id`. Si Claude appelle l'un de vos outils client en même temps, le bloc `server_tool_use` apparaît sans son résultat, et la réponse se termine avec `stop_reason: "tool_use"`. L'API exécute l'outil lorsque vous renvoyez les blocs `tool_result` client dans votre requête suivante.

## La boucle côté serveur et pause\_turn

Lors de l'utilisation d'outils serveur tels que la recherche web, l'API exécute les appels d'outils dans une boucle agentique côté serveur. Lors d'un tour de longue durée, l'API peut mettre cette boucle en pause et renvoyer un motif d'arrêt `pause_turn`.

Voici comment gérer le motif d'arrêt `pause_turn` :

<CodeGroup>
  ```bash cURL
  # Requête initiale. Si "stop_reason" dans la réponse vaut "pause_turn", poursuivez
  # le tour en renvoyant la requête avec le contenu de l'assistant ajouté à messages.
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "messages": [
        {
          "role": "user",
          "content": "Search for comprehensive information about quantum computing breakthroughs in 2025"
        }
      ],
      "tools": [{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}]
    }'
  ```

  ```bash CLI
  # Requête initiale. Si "stop_reason" dans la sortie vaut "pause_turn", relancez avec
  # le contenu de l'assistant ajouté aux messages (voir les onglets SDK).
  ant messages create <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  tools:
    - {type: web_search_20250305, name: web_search, max_uses: 10}
  messages:
    - {role: user, content: "Search for comprehensive information about quantum computing breakthroughs in 2025"}
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  # Requête initiale avec recherche web.
  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      messages=[
          {
              "role": "user",
              "content": "Search for comprehensive information about quantum computing breakthroughs in 2025",
          }
      ],
      tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}],
  )

  # Vérifier si la réponse a la raison d'arrêt pause_turn.
  if response.stop_reason == "pause_turn":
      # Poursuivre la conversation avec le contenu mis en pause.
      messages = [
          {
              "role": "user",
              "content": "Search for comprehensive information about quantum computing breakthroughs in 2025",
          },
          {"role": "assistant", "content": response.content},
      ]

      # Envoyer la requête de poursuite.
      continuation = client.messages.create(
          model="claude-opus-5-5",
          max_tokens=1024,
          messages=messages,
          tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}],
      )

      print(continuation)
  else:
      print(response)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  // Requête initiale avec recherche web.
  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content:
          "Search for comprehensive information about quantum computing breakthroughs in 2025"
      }
    ],
    tools: [
      {
        type: "web_search_20250305",
        name: "web_search",
        max_uses: 10
      }
    ]
  });

  // Vérifier si la réponse a la raison d'arrêt pause_turn.
  if (response.stop_reason === "pause_turn") {
    // Poursuivre la conversation avec le contenu mis en pause.
    const messages: Anthropic.MessageParam[] = [
      {
        role: "user",
        content:
          "Search for comprehensive information about quantum computing breakthroughs in 2025"
      },
      { role: "assistant", content: response.content }
    ];

    // Envoyer la requête de poursuite.
    const continuation = await client.messages.create({
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages,
      tools: [
        {
          type: "web_search_20250305",
          name: "web_search",
          max_uses: 10
        }
      ]
    });

    console.log(continuation);
  } else {
    console.log(response);
  }
  ```

  ```csharp C#
  AnthropicClient client = new();

  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Messages = [
          new() {
              Role = Role.User,
              Content = "Search for comprehensive information about quantum computing breakthroughs in 2025"
          }
      ],
      Tools = [new ToolUnion(new WebSearchTool20250305 { MaxUses = 10 })]
  };

  var response = await client.Messages.Create(parameters);

  if (response.StopReason?.Value() == StopReason.PauseTurn)
  {
      // Poursuivre la conversation avec le contenu mis en pause.
      var continuationParams = new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          Messages = [
              new() {
                  Role = Role.User,
                  Content = "Search for comprehensive information about quantum computing breakthroughs in 2025"
              },
              new() {
                  Role = Role.Assistant,
                  Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
              }
          ],
          Tools = [new ToolUnion(new WebSearchTool20250305 { MaxUses = 10 })]
      };

      var continuation = await client.Messages.Create(continuationParams);
      Console.WriteLine(continuation);
  }
  else
  {
      Console.WriteLine(response);
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  webSearchTool := []anthropic.ToolUnionParam{
  	{OfWebSearchTool20250305: &anthropic.WebSearchTool20250305Param{
  		MaxUses: anthropic.Int(10),
  	}},
  }

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Search for comprehensive information about quantum computing breakthroughs in 2025")),
  	},
  	Tools: webSearchTool,
  })
  if err != nil {
  	log.Fatal(err)
  }

  if response.StopReason == anthropic.StopReasonPauseTurn {
  	// Renvoyez la réponse mise en pause telle quelle pour que Claude puisse poursuivre le tour.
  	continuation, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  		Model:     anthropic.ModelClaudeOpus5_5,
  		MaxTokens: 1024,
  		Messages: []anthropic.MessageParam{
  			anthropic.NewUserMessage(anthropic.NewTextBlock("Search for comprehensive information about quantum computing breakthroughs in 2025")),
  			response.ToParam(),
  		},
  		Tools: webSearchTool,
  	})
  	if err != nil {
  		log.Fatal(err)
  	}
  	fmt.Println(continuation)
  } else {
  	fmt.Println(response)
  }
  ```

  ```java Java
  import com.anthropic.models.messages.StopReason;
  import com.anthropic.models.messages.WebSearchTool20250305;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024L)
          .addUserMessage("Search for comprehensive information about quantum computing breakthroughs in 2025")
          .addTool(WebSearchTool20250305.builder()
              .maxUses(10L)
              .build())
          .build();

      Message response = client.messages().create(params);

      if (response.stopReason().isPresent()
              && response.stopReason().get().equals(StopReason.PAUSE_TURN)) {
          MessageCreateParams continuationParams = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024L)
              .addUserMessage("Search for comprehensive information about quantum computing breakthroughs in 2025")
              .addMessage(response)
              .addTool(WebSearchTool20250305.builder()
                  .maxUses(10L)
                  .build())
              .build();

          Message continuation = client.messages().create(continuationParams);
          IO.println(continuation);
      } else {
          IO.println(response);
      }
  }
  ```

  ```php PHP
  $client = new Client();

  $response = $client->messages->create(
      maxTokens: 1024,
      messages: [
          [
              'role' => 'user',
              'content' => 'Search for comprehensive information about quantum computing breakthroughs in 2025'
          ]
      ],
      model: 'claude-opus-5-5',
      tools: [
          [
              'type' => 'web_search_20250305',
              'name' => 'web_search',
              'max_uses' => 10
          ]
      ],
  );

  if ($response->stopReason === 'pause_turn') {
      $messages = [
          [
              'role' => 'user',
              'content' => 'Search for comprehensive information about quantum computing breakthroughs in 2025'
          ],
          [
              'role' => 'assistant',
              'content' => $response->content
          ]
      ];

      $continuation = $client->messages->create(
          maxTokens: 1024,
          messages: $messages,
          model: 'claude-opus-5-5',
          tools: [
              [
                  'type' => 'web_search_20250305',
                  'name' => 'web_search',
                  'max_uses' => 10
              ]
          ],
      );

      echo $continuation;
  } else {
      echo $response;
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content:
          "Search for comprehensive information about quantum computing breakthroughs in 2025"
      }
    ],
    tools: [
      {
        type: "web_search_20250305",
        name: "web_search",
        max_uses: 10
      }
    ]
  )

  if response.stop_reason == :pause_turn
    messages = [
      {
        role: "user",
        content: "Search for comprehensive information about quantum computing breakthroughs in 2025"
      },
      {
        role: "assistant",
        content: response.content
      }
    ]

    continuation = client.messages.create(
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: messages,
      tools: [
        {
          type: "web_search_20250305",
          name: "web_search",
          max_uses: 10
        }
      ]
    )

    puts continuation
  else
    puts response
  end
  ```
</CodeGroup>

Lors de la gestion de `pause_turn` :

* **Poursuivez la conversation :** renvoyez la réponse mise en pause telle quelle dans une requête ultérieure pour permettre à Claude de poursuivre son tour.
* **Préservez l'état des outils :** incluez les mêmes outils dans la requête de continuation. Un tour mis en pause peut se terminer par un bloc `server_tool_use` dont l'outil ne s'est pas encore exécuté, et l'API renvoie une erreur de validation si cet outil est absent de la continuation.
* **Répétez si nécessaire :** un tour poursuivi peut être mis en pause à nouveau. Vérifiez `stop_reason` sur chaque réponse et poursuivez jusqu'à obtenir un motif d'arrêt différent, en plafonnant le nombre de continuations comme vous le feriez pour toute boucle de nouvelle tentative.

Pour les autres valeurs de `stop_reason` et les modèles de gestion généraux, consultez [Motifs d'arrêt et repli](https://platform.claude.com/docs/fr/build-with-claude/handling-stop-reasons).

## Mêler outils serveur et outils client dans un même tour

Claude peut appeler un outil serveur et un outil client dans le même groupe d'appels d'outils parallèles, par exemple `web_fetch` avec un outil défini par l'utilisateur. Un outil client est tout outil que votre code exécute et qui produit un bloc `tool_use`, qu'il soit défini par l'utilisateur ou qu'il s'agisse d'un outil client à schéma Anthropic tel que l'[outil Bash](https://platform.claude.com/docs/fr/agents-and-tools/tool-use/bash-tool). Lorsque cela se produit, l'API n'exécute pas l'outil serveur. Elle renvoie immédiatement la réponse afin que vous puissiez exécuter l'outil client en premier :

* `stop_reason` vaut `"tool_use"`, et non `"pause_turn"`.
* `content` contient le bloc `server_tool_use` et le bloc `tool_use` client, mais aucun bloc de résultat pour l'outil serveur : cet appel n'est pas terminé.
* Il n'y a aucun autre marqueur. Détectez cet état en recherchant un bloc `server_tool_use` dont l'`id` n'a pas de bloc de résultat correspondant dans la réponse. Un bloc `mcp_tool_use` provenant du [connecteur MCP](https://platform.claude.com/docs/fr/agents-and-tools/mcp-connector) se comporte de la même manière. Les appels d'outils serveur qui ont déjà leur bloc de résultat dans la même réponse sont terminés et ne nécessitent rien de votre part.

<Note>
  Avec l'[appel d'outils programmatique](https://platform.claude.com/docs/fr/agents-and-tools/tool-use/programmatic-tool-calling), la même forme de réponse signifie quelque chose de différent. Le bloc `tool_use` client provient du code qui s'exécute dans l'outil `code_execution` plutôt que de Claude directement, et son champ `caller` désigne le bloc `code_execution` qui l'a appelé. Ce code a déjà démarré : il est en pause en attente de vos blocs `tool_result`, et leur envoi reprend l'exécution au lieu de démarrer un outil différé. Le propre bloc de résultat du bloc `code_execution` arrive une fois le code terminé, ce qui peut nécessiter plus d'un cycle de résultats d'outils. Le message utilisateur de suivi lui-même est identique dans les deux cas ; avec l'appel d'outils programmatique, renvoyez également l'`id` du champ `container` de la réponse, comme le montre cette page.
</Note>

```json
{
  "stop_reason": "tool_use",
  "content": [
    {
      "type": "text",
      "text": "I'll fetch the article and check your system at the same time."
    },
    {
      "type": "server_tool_use",
      "id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",
      "name": "web_fetch",
      "input": { "url": "https://example.com/article" }
    },
    {
      "type": "tool_use",
      "id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
      "name": "run_command",
      "input": { "command": "uname -a" }
    }
  ]
}
```

Pour poursuivre le tour, exécutez les outils client et envoyez un message utilisateur dont le contenu se compose uniquement des blocs `tool_result`, un pour chaque bloc `tool_use` de cette réponse. Conservez le même tableau `tools` : une requête de reprise qui ne définit plus l'outil serveur en attente échoue avec une erreur 400 dont le message se termine par ``but no `web_fetch` tool was provided``.

```json
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
      "content": "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"
    }
  ]
}
```

L'API rattache vos résultats au tour de l'assistant encore ouvert, exécute l'outil serveur différé (pour une exécution de code en pause, la reprend), puis laisse Claude poursuivre. Pour un outil serveur que Claude a appelé directement, la réponse suivante commence par le bloc de résultat qui répond à l'`id` `server_tool_use` de la réponse précédente, suivi du contenu nouvellement généré et d'un nouveau `stop_reason` :

```json
{
  "stop_reason": "end_turn",
  "content": [
    {
      "type": "web_fetch_tool_result",
      "tool_use_id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",
      "content": {
        "type": "web_fetch_result",
        "url": "https://example.com/article",
        "content": {
          "type": "document",
          "source": {
            "type": "text",
            "media_type": "text/plain",
            "data": "Full text content of the article..."
          }
        }
      }
    },
    {
      "type": "text",
      "text": "The article argues that... and your machine is running Linux..."
    }
  ]
}
```

Un bloc `server_tool_use` et son bloc de résultat s'apparient par `tool_use_id`, et non par position : dans ce flux, ils arrivent dans deux réponses différentes, et le bloc `server_tool_use` n'est pas répété dans la seconde. Lors des requêtes ultérieures, conservez l'intégralité de l'échange dans votre tableau `messages`, dans l'ordre : la première réponse en tant que message `assistant`, le message utilisateur `tool_result`, puis la réponse suivante en tant qu'autre message `assistant`, de la même manière que vous accumulez tout autre échange d'utilisation d'outils.

<Warning>
  Le message utilisateur de suivi ne doit contenir rien d'autre que des blocs `tool_result`. Un bloc ajouté après les résultats, tel que du texte, indique à l'API que le tour de l'assistant est terminé. Pour un outil serveur que Claude a appelé directement, cela laisse le tour avec un appel d'outil serveur non résolu, et la requête échoue avec une erreur 400 `invalid_request_error` :

  ```text wrap
  `web_fetch` tool use with id `srvtoolu_01HxbWnMRmbWyMfUtJKC45rA` was found without a corresponding `web_fetch_tool_result` block
  ```

  Un suivi qui place du contenu avant les résultats, qui ne répond qu'à certains des ID `tool_use` client, ou qui ne contient aucun bloc `tool_result` échoue plus tôt, avec l'erreur d'outil client décrite dans [Gérer les appels d'outils](https://platform.claude.com/docs/fr/agents-and-tools/tool-use/handle-tool-calls) :

  ```text wrap
  `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01PjgRJLbXrXEMZwDNYLnBqk. Each `tool_use` block must have a corresponding `tool_result` block in the next message.
  ```

  Pour fournir davantage d'entrées à Claude, envoyez-les dans un message utilisateur distinct une fois le tour terminé.
</Warning>

**En quoi cela diffère de `pause_turn` :** une [réponse `pause_turn`](https://platform.claude.com/docs/fr/agents-and-tools/tool-use/server-tools#the-server-side-loop-and-pause-turn) peut également se terminer par un bloc `server_tool_use` qui ne s'est pas exécuté, mais elle ne laisse jamais un bloc `tool_use` client en attente de votre part ; vous la poursuivez donc en renvoyant le contenu de l'assistant tel quel. Une réponse qui laisse un bloc `tool_use` client en attente de votre part n'a jamais un `stop_reason` de `pause_turn` : lorsque Claude s'arrête pour appeler vos outils, `stop_reason` vaut `tool_use`, et vous la poursuivez en envoyant les blocs `tool_result` client plutôt qu'en renvoyant la réponse. Dans les deux cas, l'API exécute l'outil serveur en attente au début de la requête suivante.

L'exemple suivant active la récupération web avec un outil `run_command` défini par l'utilisateur et gère la réponse mixte :

<CodeGroup>
  ```bash cURL
  # Si "stop_reason" vaut "tool_use" et qu'un bloc server_tool_use n'a pas de bloc
  # de résultat correspondant, cet appel n'est pas terminé. Exécutez les outils client, puis
  # refaites un POST avec un message user de plus contenant uniquement leurs blocs tool_result
  # et le même tableau tools (voir les onglets SDK).
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "messages": [
        {
          "role": "user",
          "content": "Summarize https://example.com/article and run uname -a to tell me what system this is on."
        }
      ],
      "tools": [
        {"type": "web_fetch_20250910", "name": "web_fetch", "max_uses": 5},
        {
          "name": "run_command",
          "description": "Run a shell command on this computer and return its output.",
          "input_schema": {
            "type": "object",
            "properties": {"command": {"type": "string", "description": "The command to run"}},
            "required": ["command"]
          }
        }
      ]
    }'
  ```

  ```bash CLI
  # Si "stop_reason" vaut "tool_use" et qu'un bloc server_tool_use n'a pas de bloc
  # de résultat correspondant, exécutez les outils client et relancez avec un message utilisateur
  # contenant uniquement leurs blocs tool_result ajoutés (voir les onglets SDK).
  ant messages create <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  messages:
    - role: user
      content: "Summarize https://example.com/article and run uname -a to tell me what system this is on."
  tools:
    - {type: web_fetch_20250910, name: web_fetch, max_uses: 5}
    - name: run_command
      description: Run a shell command on this computer and return its output.
      input_schema:
        type: object
        properties:
          command: {type: string, description: The command to run}
        required: [command]
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  tools = [
      {"type": "web_fetch_20250910", "name": "web_fetch", "max_uses": 5},
      {
          "name": "run_command",
          "description": "Run a shell command on this computer and return its output.",
          "input_schema": {
              "type": "object",
              "properties": {
                  "command": {"type": "string", "description": "The command to run"}
              },
              "required": ["command"],
          },
      },
  ]
  messages = [
      {
          "role": "user",
          "content": "Summarize https://example.com/article and run uname -a to tell me what system this is on.",
      }
  ]

  response = client.messages.create(
      model="claude-opus-5-5", max_tokens=1024, tools=tools, messages=messages
  )

  tool_results = [
      {
          "type": "tool_result",
          "tool_use_id": block.id,
          # Exécutez votre outil ici. Cet exemple renvoie une chaîne fixe.
          "content": "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux",
      }
      for block in response.content
      if block.type == "tool_use"
  ]

  if response.stop_reason == "tool_use" and tool_results:
      # Un bloc server_tool_use sans bloc de résultat dans cette réponse n'est pas terminé ; son résultat arrive dans une réponse ultérieure.
      # Renvoyez uniquement les blocs tool_result client, avec les mêmes outils.
      continuation = client.messages.create(
          model="claude-opus-5-5",
          max_tokens=1024,
          tools=tools,
          messages=[
              *messages,
              {"role": "assistant", "content": response.content},
              {"role": "user", "content": tool_results},
          ],
      )
      # Si un web_fetch a été différé, il s'exécute lors de cette requête et son
      # web_fetch_tool_result est le premier bloc de continuation.content.
      print(continuation)
  else:
      print(response)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const webFetchTool = {
    type: "web_fetch_20250910",
    name: "web_fetch",
    max_uses: 5
  } as const;
  const runCommandTool: Anthropic.Tool = {
    name: "run_command",
    description: "Run a shell command on this computer and return its output.",
    input_schema: {
      type: "object" as const,
      properties: {
        command: { type: "string", description: "The command to run" }
      },
      required: ["command"]
    }
  };
  const messages: Anthropic.MessageParam[] = [
    {
      role: "user",
      content:
        "Summarize https://example.com/article and run uname -a to tell me what system this is on."
    }
  ];

  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    tools: [webFetchTool, runCommandTool],
    messages
  });

  const toolResults: Anthropic.ToolResultBlockParam[] = [];
  for (const block of response.content) {
    if (block.type === "tool_use") {
      toolResults.push({
        type: "tool_result",
        tool_use_id: block.id,
        // Exécutez votre outil ici. Cet exemple renvoie une chaîne fixe.
        content: "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"
      });
    }
  }

  if (response.stop_reason === "tool_use" && toolResults.length > 0) {
    // Un bloc server_tool_use sans bloc de résultat dans cette réponse n'est pas terminé ; son résultat arrive dans une réponse ultérieure.
    // Renvoyez uniquement les blocs tool_result client, avec les mêmes outils.
    const continuation = await client.messages.create({
      model: "claude-opus-5-5",
      max_tokens: 1024,
      tools: [webFetchTool, runCommandTool],
      messages: [
        ...messages,
        { role: "assistant", content: response.content },
        { role: "user", content: toolResults }
      ]
    });
    // Si un web_fetch a été différé, il s'exécute lors de cette requête et son
    // web_fetch_tool_result est le premier bloc de continuation.content.
    console.log(continuation);
  } else {
    console.log(response);
  }
  ```

  ```csharp C#
  AnthropicClient client = new();

  List<ToolUnion> tools =
  [
      new ToolUnion(new WebFetchTool20250910() { MaxUses = 5 }),
      new ToolUnion(new Tool()
      {
          Name = "run_command",
          Description = "Run a shell command on this computer and return its output.",
          InputSchema = new InputSchema()
          {
              Properties = new Dictionary<string, JsonElement>
              {
                  ["command"] = JsonSerializer.SerializeToElement(
                      new { type = "string", description = "The command to run" }
                  ),
              },
              Required = ["command"],
          },
      }),
  ];
  MessageParam userMessage = new()
  {
      Role = Role.User,
      Content = "Summarize https://example.com/article and run uname -a to tell me what system this is on."
  };

  var response = await client.Messages.Create(new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Tools = tools,
      Messages = [userMessage]
  });

  var toolResults = new List<ContentBlockParam>();
  foreach (var block in response.Content)
  {
      if (block.TryPickToolUse(out var toolUse))
      {
          toolResults.Add(new ContentBlockParam(new ToolResultBlockParam()
          {
              ToolUseID = toolUse.ID,
              // Exécutez votre outil ici. Cet exemple renvoie une chaîne fixe.
              Content = "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux",
          }));
      }
  }

  if (response.StopReason?.Value() == StopReason.ToolUse && toolResults.Count > 0)
  {
      // Un bloc server_tool_use sans bloc de résultat dans cette réponse n'est pas terminé ; son résultat arrive dans une réponse ultérieure.
      // Renvoyez uniquement les blocs tool_result client, avec les mêmes outils.
      var continuation = await client.Messages.Create(new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          Tools = tools,
          Messages =
          [
              userMessage,
              new()
              {
                  Role = Role.Assistant,
                  Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
              },
              new() { Role = Role.User, Content = new MessageParamContent(toolResults) }
          ]
      });
      // Si un web_fetch a été différé, il s'exécute lors de cette requête et son
      // web_fetch_tool_result est le premier bloc de continuation.Content.
      Console.WriteLine(continuation);
  }
  else
  {
      Console.WriteLine(response);
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  tools := []anthropic.ToolUnionParam{
  	{OfWebFetchTool20250910: &anthropic.WebFetchTool20250910Param{
  		MaxUses: anthropic.Int(5),
  	}},
  	{OfTool: &anthropic.ToolParam{
  		Name:        "run_command",
  		Description: anthropic.String("Run a shell command on this computer and return its output."),
  		InputSchema: anthropic.ToolInputSchemaParam{
  			Properties: map[string]any{
  				"command": map[string]any{
  					"type":        "string",
  					"description": "The command to run",
  				},
  			},
  			Required: []string{"command"},
  		},
  	}},
  }
  userMessage := anthropic.NewUserMessage(anthropic.NewTextBlock("Summarize https://example.com/article and run uname -a to tell me what system this is on."))

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Tools:     tools,
  	Messages:  []anthropic.MessageParam{userMessage},
  })
  if err != nil {
  	log.Fatal(err)
  }

  var toolResults []anthropic.ContentBlockParamUnion
  for _, block := range response.Content {
  	if toolUse, ok := block.AsAny().(anthropic.ToolUseBlock); ok {
  		// Exécutez votre outil ici. Cet exemple renvoie une chaîne fixe.
  		output := "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"
  		toolResults = append(toolResults, anthropic.NewToolResultBlock(toolUse.ID, output, false))
  	}
  }

  if response.StopReason == anthropic.StopReasonToolUse && len(toolResults) > 0 {
  	// Un bloc server_tool_use sans bloc de résultat dans cette réponse n'est pas terminé ; son résultat arrive dans une réponse ultérieure.
  	// Renvoyez uniquement les blocs tool_result client, avec les mêmes outils.
  	continuation, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  		Model:     anthropic.ModelClaudeOpus5_5,
  		MaxTokens: 1024,
  		Tools:     tools,
  		Messages: []anthropic.MessageParam{
  			userMessage,
  			response.ToParam(),
  			anthropic.NewUserMessage(toolResults...),
  		},
  	})
  	if err != nil {
  		log.Fatal(err)
  	}
  	// Si un web_fetch a été différé, il s'exécute lors de cette requête et son
  	// web_fetch_tool_result est le premier bloc de continuation.Content.
  	fmt.Println(continuation)
  } else {
  	fmt.Println(response)
  }
  ```

  ```java Java
  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      Tool runCommandTool = Tool.builder()
          .name("run_command")
          .description("Run a shell command on this computer and return its output.")
          .inputSchema(Tool.InputSchema.builder()
              .properties(JsonValue.from(Map.of(
                  "command", Map.of("type", "string", "description", "The command to run")
              )))
              .putAdditionalProperty("required", JsonValue.from(List.of("command")))
              .build())
          .build();
      String prompt = "Summarize https://example.com/article and run uname -a to tell me what system this is on.";

      Message response = client.messages().create(MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024L)
          .addTool(WebFetchTool20250910.builder().maxUses(5L).build())
          .addTool(runCommandTool)
          .addUserMessage(prompt)
          .build());

      List<ContentBlockParam> toolResults = new ArrayList<>();
      for (ContentBlock block : response.content()) {
          block.toolUse().ifPresent(toolUse -> toolResults.add(ContentBlockParam.ofToolResult(
              ToolResultBlockParam.builder()
                  .toolUseId(toolUse.id())
                  // Exécutez votre outil ici. Cet exemple renvoie une chaîne fixe.
                  .content("Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux")
                  .build()
          )));
      }

      boolean isToolUse = response.stopReason()
          .map(StopReason.TOOL_USE::equals)
          .orElse(false);
      if (isToolUse && !toolResults.isEmpty()) {
          // Un bloc server_tool_use sans bloc de résultat dans cette réponse n'est pas terminé ; son résultat arrive dans une réponse ultérieure.
          // Renvoyez uniquement les blocs tool_result client, avec les mêmes outils.
          Message continuation = client.messages().create(MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024L)
              .addTool(WebFetchTool20250910.builder().maxUses(5L).build())
              .addTool(runCommandTool)
              .addUserMessage(prompt)
              .addMessage(response)
              .addUserMessageOfBlockParams(toolResults)
              .build());
          // Si un web_fetch a été différé, il s'exécute lors de cette requête et son
          // web_fetch_tool_result est le premier bloc de continuation.content().
          IO.println(continuation);
      } else {
          IO.println(response);
      }
  }
  ```

  ```php PHP
  $client = new Client();

  $tools = [
      ['type' => 'web_fetch_20250910', 'name' => 'web_fetch', 'max_uses' => 5],
      [
          'name' => 'run_command',
          'description' => 'Run a shell command on this computer and return its output.',
          'input_schema' => [
              'type' => 'object',
              'properties' => [
                  'command' => ['type' => 'string', 'description' => 'The command to run']
              ],
              'required' => ['command']
          ]
      ]
  ];
  $userMessage = ['role' => 'user', 'content' => 'Summarize https://example.com/article and run uname -a to tell me what system this is on.'];

  $response = $client->messages->create(
      maxTokens: 1024,
      messages: [$userMessage],
      model: 'claude-opus-5-5',
      tools: $tools,
  );

  $toolResults = [];
  foreach ($response->content as $block) {
      if ($block->type === 'tool_use') {
          $toolResults[] = [
              'type' => 'tool_result',
              'tool_use_id' => $block->id,
              // Exécutez votre outil ici. Cet exemple renvoie une chaîne fixe.
              'content' => 'Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux'
          ];
      }
  }

  if ($response->stopReason === 'tool_use' && count($toolResults) > 0) {
      // Un bloc server_tool_use sans bloc de résultat dans cette réponse n'est pas terminé ; son résultat arrive dans une réponse ultérieure.
      // Renvoyez uniquement les blocs tool_result client, avec les mêmes outils.
      $continuation = $client->messages->create(
          maxTokens: 1024,
          messages: [
              $userMessage,
              ['role' => 'assistant', 'content' => $response->content],
              ['role' => 'user', 'content' => $toolResults],
          ],
          model: 'claude-opus-5-5',
          tools: $tools,
      );
      // Si un web_fetch a été différé, il s'exécute lors de cette requête et son
      // web_fetch_tool_result est le premier bloc de $continuation->content.
      echo $continuation;
  } else {
      echo $response;
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  tools = [
    { type: "web_fetch_20250910", name: "web_fetch", max_uses: 5 },
    {
      name: "run_command",
      description: "Run a shell command on this computer and return its output.",
      input_schema: {
        type: "object",
        properties: {
          command: { type: "string", description: "The command to run" }
        },
        required: ["command"]
      }
    }
  ]
  user_message = {
    role: "user",
    content: "Summarize https://example.com/article and run uname -a to tell me what system this is on."
  }

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    tools: tools,
    messages: [user_message]
  )

  tool_results = []
  response.content.each do |block|
    next unless block.type == :tool_use

    tool_results << {
      type: "tool_result",
      tool_use_id: block.id,
      # Exécutez votre outil ici. Cet exemple renvoie une chaîne fixe.
      content: "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"
    }
  end

  if response.stop_reason == :tool_use && !tool_results.empty?
    # Un bloc server_tool_use sans bloc de résultat dans cette réponse n'est pas terminé ; son résultat arrive dans une réponse ultérieure.
    # Renvoyez uniquement les blocs tool_result client, avec les mêmes outils.
    continuation = client.messages.create(
      model: "claude-opus-5-5",
      max_tokens: 1024,
      tools: tools,
      messages: [
        user_message,
        { role: "assistant", content: response.content },
        { role: "user", content: tool_results }
      ]
    )
    # Si un web_fetch a été différé, il s'exécute lors de cette requête et son
    # web_fetch_tool_result est le premier bloc de continuation.content.
    puts continuation
  else
    puts response
  end
  ```
</CodeGroup>

Ce code est également correct lorsque Claude ne mêle pas les deux types d'appels. Un tour ne comportant que des blocs `tool_use` client suit le même chemin de continuation, et un tour ne comportant que des appels d'outils serveur ne nécessite aucun bloc `tool_result` client de votre part : ses blocs de résultat sont normalement déjà présents, et un tour qui revient suspendu, tel qu'une [réponse `pause_turn`](https://platform.claude.com/docs/fr/agents-and-tools/tool-use/server-tools#the-server-side-loop-and-pause-turn), est renvoyé tel quel à la place.

## ZDR et allowed\_callers

Les versions de base de la recherche web (`web_search_20250305`) et de la récupération web (`web_fetch_20250910`) sont éligibles au [Zero Data Retention (ZDR)](https://platform.claude.com/docs/fr/manage-claude/api-and-data-retention).

Les versions `_20260209` et ultérieures avec filtrage dynamique ne sont **pas** éligibles au ZDR par défaut, car le filtrage dynamique repose en interne sur l'exécution de code.

Pour utiliser un outil serveur `_20260209` ou ultérieur avec le ZDR, désactivez le filtrage dynamique en définissant `"allowed_callers": ["direct"]` sur l'outil :

```json
{
  "type": "web_search_20260209",
  "name": "web_search",
  "allowed_callers": ["direct"]
}
```

Cela restreint l'outil à l'invocation directe uniquement, en contournant l'étape interne d'exécution de code.

`allowed_callers` contrôle la manière dont un outil peut être invoqué : directement par Claude (`"direct"`), depuis l'intérieur d'un conteneur d'exécution de code (par exemple, `"code_execution_20260120"`), ou les deux. Les versions `_20260209` des outils web utilisent par défaut uniquement l'appelant d'exécution de code ; les versions antérieures utilisent par défaut `["direct"]`. Sur les modèles qui ne prennent pas en charge l'appel d'outils programmatique, ces versions nécessitent `allowed_callers: ["direct"]` ; sans cela, l'API renvoie une erreur de validation indiquant de le définir.

<Note>
  Même lorsque la récupération web est utilisée dans une configuration éligible au ZDR, les éditeurs de sites web peuvent conserver tous les paramètres transmis à l'URL si Claude récupère du contenu depuis leur site.
</Note>

## Filtrage de domaines

Les outils serveur qui accèdent au web acceptent les paramètres `allowed_domains` et `blocked_domains` pour contrôler les domaines que Claude peut atteindre. Tous deux sont des champs de l'objet outil :

```json
{
  "type": "web_search_20250305",
  "name": "web_search",
  "allowed_domains": ["example.com", "docs.python.org"]
}
```

Lors de l'utilisation de filtres de domaines :

* Les domaines ne doivent pas inclure le schéma HTTP/HTTPS (utilisez `example.com` au lieu de `https://example.com`).
* Les sous-domaines sont automatiquement inclus (`example.com` couvre `docs.example.com`).
* Les sous-domaines spécifiques restreignent les résultats à ce seul sous-domaine (`docs.example.com` ne renvoie que les résultats de ce sous-domaine, et non de `example.com` ou `api.example.com`).
* Les sous-chemins sont pris en charge pour la recherche web et correspondent à tout ce qui suit le chemin (`example.com/blog` correspond à `example.com/blog/post-1`).
* La récupération web ne fait correspondre que le domaine : une entrée qui inclut un chemin ne correspond jamais à une URL de récupération web.
* Vous pouvez utiliser soit `allowed_domains`, soit `blocked_domains`, mais pas les deux dans la même requête.

**Prise en charge des caractères génériques :**

* Les caractères génériques (`*`) ne sont pas autorisés dans le domaine lui-même, uniquement dans le chemin qui le suit.
* Valide : `example.com/*`, `example.com/*/articles`
* Invalide : `*.example.com`, `ex*.com`

Les formats de domaine invalides sont rejetés au moment de la requête avec une erreur 400 `invalid_request_error`.

<Note>
  Les restrictions de domaines au niveau de la requête fonctionnent conjointement avec toutes les restrictions de domaines au niveau de l'organisation configurées dans la Claude Console. Les `allowed_domains` au niveau de la requête doivent être un sous-ensemble de la liste autorisée au niveau de l'organisation ; les entrées en dehors de celle-ci amènent l'API à renvoyer une erreur de validation. Une liste autorisée au niveau de la requête qui inclut un domaine bloqué par votre organisation est rejetée avec une erreur `400` qui nomme les entrées en conflit.
</Note>

<Warning>
  Les caractères Unicode dans les noms de domaine peuvent contourner les filtres de domaines par le biais d'attaques homographes : `аmazon.com` (avec un `а` cyrillique) semble identique à `amazon.com` mais constitue un domaine différent. Utilisez des noms de domaine uniquement ASCII dans les listes d'autorisation et de blocage, et auditez les entrées existantes à la recherche de caractères non ASCII.
</Warning>

[Claude Managed Agents](https://platform.claude.com/docs/fr/managed-agents/overview) utilise les mêmes champs `allowed_domains` et `blocked_domains` sur les entrées `web_search` et `web_fetch` de l'ensemble d'outils de l'agent. Sur Managed Agents, chaque liste contient au maximum 64 entrées, les domaines listés pour `web_fetch` ne peuvent pas inclure de chemin, et les champs propres aux outils de l'API Messages, tels que `max_uses`, `citations` et `cache_control`, ne sont pas disponibles. Consultez [Règles des listes de domaines](https://platform.claude.com/docs/fr/managed-agents/tools-web-restrictions#domain-list-rules) pour l'ensemble des règles.

Les paramètres de recherche web et de récupération web au niveau de l'organisation dans la Claude Console s'appliquent uniquement aux requêtes de l'API Messages. Ils ne s'appliquent pas aux sessions Managed Agents, qui utilisent à la place les listes par outil de l'ensemble d'outils de l'agent. Pour une session dans un environnement cloud avec une mise en réseau `limited`, le paramètre `allowed_hosts` de l'environnement s'applique également à `web_search` et `web_fetch` ; consultez [Réseau](https://platform.claude.com/docs/fr/managed-agents/environments#networking). Les listes par outil restreignent davantage ces outils, au sein des hôtes autorisés par `allowed_hosts`.

## Filtrage dynamique avec exécution de code

Les versions `_20260209` et ultérieures de la recherche web et de la récupération web utilisent l'exécution de code en interne pour appliquer des filtres dynamiques aux résultats de recherche.

<Note>
  Vous n'avez pas besoin d'ajouter un outil `code_execution` pour ces versions : lorsque le filtrage dynamique s'exécute, l'API provisionne automatiquement l'exécution de code pour la requête, et les deux outils partagent un seul conteneur d'exécution. Si vous en incluez un, utilisez `code_execution_20260120` ou ultérieur ; l'API rejette les versions d'exécution de code plus anciennes aux côtés de ces versions d'outils web.
</Note>

## Streaming des événements d'outils serveur

Les événements d'outils serveur sont diffusés en « streaming » (flux continu) dans le cadre du flux normal de « server-sent events » (événements envoyés par le serveur), ou SSE. Un bloc `server_tool_use` que Claude appelle directement est diffusé comme un bloc `tool_use` client : un événement `content_block_start` suivi d'événements `input_json_delta`. Le bloc de résultat arrive complet dans un seul événement `content_block_start`, sans deltas.

Consultez [Streaming](https://platform.claude.com/docs/fr/build-with-claude/streaming) pour la référence complète des événements. Les pages des outils individuels documentent les noms d'événements spécifiques aux outils lorsqu'ils diffèrent.

## Requêtes par lots

Tous les outils serveur prennent en charge le traitement par lots. Dans un lot, la boucle agentique s'exécute exactement comme pour les requêtes synchrones, avec une limite d'itérations par tour plus élevée. Si la boucle atteint cette limite, la réponse se termine avec `stop_reason: "pause_turn"` ; vous pouvez la poursuivre en soumettant une requête de suivi avec le contenu renvoyé. Consultez [Outils serveur et boucle agentique](https://platform.claude.com/docs/fr/build-with-claude/batch-processing#server-tools-and-the-agentic-loop) pour plus de détails.

Les charges de travail par lots courantes incluent l'enrichissement d'un jeu de données avec des informations provenant du web, la vérification d'un grand ensemble de documents par rapport à des sources actuelles, et l'exécution de code d'analyse sur de nombreux fichiers.

## Étapes suivantes

<CardGroup cols={2}>
  <Card title="Dépannage de l'utilisation d'outils" icon="wrench" href="https://platform.claude.com/docs/fr/agents-and-tools/tool-use/troubleshooting-tool-use">
    Corrigez les erreurs d'utilisation d'outils les plus courantes grâce à des tableaux de diagnostic symptôme-correction.
  </Card>

  <Card title="Outil de recherche web" icon="magnifying-glass" href="https://platform.claude.com/docs/fr/agents-and-tools/tool-use/web-search-tool">
    Recherchez sur le web et citez les résultats.
  </Card>

  <Card title="Outil de récupération web" icon="download" href="https://platform.claude.com/docs/fr/agents-and-tools/tool-use/web-fetch-tool">
    Récupérez et lisez le contenu d'URL spécifiques pour enrichir le contexte de Claude avec du contenu web en direct.
  </Card>

  <Card title="Outil d'exécution de code" icon="terminal" href="https://platform.claude.com/docs/fr/agents-and-tools/tool-use/code-execution-tool">
    Exécutez du code Python et bash dans un conteneur isolé pour analyser des données, générer des fichiers et itérer sur des solutions.
  </Card>

  <Card title="Outil de recherche d'outils" icon="compass" href="https://platform.claude.com/docs/fr/agents-and-tools/tool-use/tool-search-tool">
    Découvrez et chargez des outils à la demande.
  </Card>
</CardGroup>
