---
title: Fils de messages
url: https://platform.claude.com/docs/fr/build-with-claude/message-threads
description: Offrez aux agents de longue durée un délai avant le premier token plus court, en particulier dans les longues conversations, en n'envoyant que les nouveaux messages à chaque requête.
featureMetadata:
  status: beta
  betaHeader: message-threads-2026-08-12
  zdr:
    eligibility: not-eligible
    note: Le contenu d’un fil (la conversation, l’invite système et les outils) est conservé en mémoire, chiffré avec une clé gérée par le serveur, jamais écrit dans un stockage durable, et supprimé au plus tard 1 heure après la dernière utilisation du fil. L’utilisation de cette fonctionnalité n’affecte pas votre utilisation des autres fonctionnalités éligibles à la ZDR.
  supportedModels:
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-fable-5
    - claude-mythos-5
    - claude-mythos-preview
    - claude-opus-5-5
    - claude-opus-5
    - claude-sonnet-5-5
    - claude-sonnet-5
    - claude-haiku-5-5
    - claude-haiku-4-5-20251001
    - claude-opus-4-8
    - claude-opus-4-7
    - claude-opus-4-6
    - claude-sonnet-4-6
    - claude-opus-4-5-20251101
    - claude-sonnet-4-5-20250929
  supportedPlatforms:
    Claude API: beta
    Claude Platform on AWS: beta
    Claude Models on Google Cloud (Anthropic managed): beta
    Microsoft Foundry: beta
---

Avec un « message thread » (fil de messages), les requêtes sont plus petites, et le « time to first token » (délai avant le premier token) reste plus faible et plus stable à mesure que la conversation s’allonge. Les fils sont surtout utiles dans les longues boucles d’agent. Sans fil, chaque tour téléverse à nouveau toute la conversation, et l’API la valide et la tokenise à nouveau entièrement. Avec un fil, l’essentiel de ce travail ne porte que sur le nouveau tour.

Un « message thread » (fil de messages) conserve une conversation sur le serveur pendant une courte durée. Vous envoyez la conversation complète une seule fois, avec votre « system prompt » (invite système) et vos outils. À chaque tour suivant, vous n’envoyez que les nouveaux messages et l’`id` de la réponse précédente. L’API reconstruit la conversation avant d’appeler le modèle. Vous ajoutez un seul paramètre, `thread`, à une requête de l’[API Messages](https://platform.claude.com/docs/fr/api/messages). La réponse est le message habituel.

<Note>
  Les fils de messages sont différents des [fils de session](https://platform.claude.com/docs/fr/managed-agents/session-threads) dans Claude Managed Agents.
</Note>

## Fonctionnement des fils de messages

* **Créer.** Envoyez votre première requête comme vous le faites aujourd’hui, avec la conversation complète, `system` et `tools`, et ajoutez `"thread": {"type": "create"}`. L’API stocke la conversation, y compris la réponse de Claude, sous l’`id` de la réponse.
* **Continuer.** Envoyez uniquement les messages depuis la réponse précédente, et ajoutez `"thread": {"type": "continue", "previous_message_id": "<previous id>"}`. Omettez `system` et `tools` de la requête. Le fil conserve les valeurs de la requête de création. Utilisez chaque nouvel `id` de réponse pour le tour suivant.
* **Rejouer.** Un fil fonctionne au mieux. Il expire 5 minutes après sa dernière requête, et l’API le supprime au plus tard 1 heure après sa dernière utilisation. Chaque réponse que l’API stocke relance les 5 minutes. Si l’API ne peut plus continuer le fil, une requête de continuation renvoie une erreur 404. Envoyez à nouveau la conversation complète dans une nouvelle requête de création, et continuez à partir de l’`id` de cette réponse. L’assistant de fil du SDK effectue ce rejeu pour vous (consultez [Comportement de l’assistant du SDK](https://platform.claude.com/docs/fr/build-with-claude/message-threads#sdk-helper-handles)). Après une réponse d’un modèle de repli, consultez [Utiliser des replis avec un fil](https://platform.claude.com/docs/fr/build-with-claude/message-threads#fallbacks).

Votre application reste la source de vérité pour la conversation. Conservez votre propre copie de chaque message, et construisez le [chemin de rejeu](https://platform.claude.com/docs/fr/build-with-claude/message-threads#recover) dès le départ. Aucune réponse, qu’il s’agisse d’une requête de création ou de continuation, n’indique si l’API a stocké ce tour. Vous le découvrez lors de la requête de continuation suivante. L’assistant de fil du SDK conserve cette copie en mémoire tant que l’objet assistant existe, et ne l’enregistre nulle part ailleurs. Si la conversation doit survivre à votre processus, conservez votre propre copie.

## Utiliser un fil avec un SDK

Le SDK dispose d’un assistant de fil qui construit les requêtes de fil pour vous. Créez-le avec les mêmes champs qu’une requête Messages, puis envoyez-lui un tour à la fois. L’assistant conserve la conversation complète en mémoire.

Cet exemple comporte deux tours. L’assistant crée un fil au premier tour et le continue au second, et il ajoute l’en-tête bêta pour vous. Le `cache_control` de niveau supérieur est facultatif. Il demande la « prompt caching » (mise en cache des prompts) à chaque tour (voir [Mise en cache des prompts sur un fil](https://platform.claude.com/docs/fr/build-with-claude/message-threads#prompt-caching)). Sans lui, chaque tour suivant n’envoie toujours que les nouveaux messages, mais rien n’est mis en cache à moins que vous n’ajoutiez vous-même des points d’arrêt de cache.

<CodeGroup exclude="shell">
  ```python Python
  client = anthropic.Anthropic()

  # Créez le helper. Cet appel n'envoie aucune requête.
  thread = client.beta.messages.thread(
      model="claude-opus-5-5",
      max_tokens=1024,
      cache_control={"type": "ephemeral"},
      system="You are a support agent for Acme. Keep replies short.",
  )

  # Tour 1 : le helper crée un fil et envoie la conversation complète
  thread.send({"role": "user", "content": "Hi! I have a question about an order."})

  # Tour 2 : le helper poursuit le fil et n'envoie que le nouveau message
  second = thread.send(
      {"role": "user", "content": "How long does standard shipping usually take?"}
  )

  for block in second.content:
      if block.type == "text":
          print(block.text)
  ```

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

  // Créez le helper. Cet appel n'envoie aucune requête.
  const thread = client.beta.messages.thread({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    cache_control: { type: "ephemeral" },
    system: "You are a support agent for Acme. Keep replies short."
  });

  // Tour 1 : le helper crée un fil et envoie la conversation complète
  await thread.send({ role: "user", content: "Hi! I have a question about an order." });

  // Tour 2 : le helper poursuit le fil et n'envoie que le nouveau message
  const second = await thread.send({
    role: "user",
    content: "How long does standard shipping usually take?"
  });

  for (const block of second.content) {
    if (block.type === "text") {
      console.log(block.text);
    }
  }
  ```

  ```csharp C#
  using Anthropic.Helpers.Beta;

  AnthropicClient client = new();

  // Créez le helper. Cet appel n'envoie aucune requête.
  var thread = client.Beta.Messages.Thread(
      new ThreadCreateParams
      {
          Model = Messages::Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          Messages = [],
          CacheControl = new(),
          System = "You are a support agent for Acme. Keep replies short.",
      }
  );

  // Tour 1 : le helper crée un fil et envoie la conversation complète
  await thread.Send(
      new BetaUserMessageParam { Content = "Hi! I have a question about an order." }
  );

  // Tour 2 : le helper poursuit le fil et n'envoie que le nouveau message
  var second = await thread.Send(
      new BetaUserMessageParam { Content = "How long does standard shipping usually take?" }
  );

  foreach (var block in second.Content)
  {
      if (block.TryPickText(out var textBlock))
      {
          Console.WriteLine(textBlock.Text);
      }
  }
  ```

  ```go Go
  client := anthropic.NewClient()
  ctx := context.Background()

  // Créez le helper. Cet appel n'envoie aucune requête.
  thread := client.Beta.Messages.NewThread(anthropic.BetaMessageThreadCreateParams{
  	Model:        anthropic.ModelClaudeOpus5_5,
  	MaxTokens:    1024,
  	CacheControl: anthropic.NewBetaCacheControlEphemeralParam(),
  	System: []anthropic.BetaTextBlockParam{
  		{Text: "You are a support agent for Acme. Keep replies short."},
  	},
  })

  // Tour 1 : le helper crée un fil et envoie la conversation complète
  _, err := thread.Send(ctx, anthropic.BetaMessageThreadSendParams{
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Hi! I have a question about an order.")),
  	},
  })
  if err != nil {
  	panic(err)
  }

  // Tour 2 : le helper poursuit le fil et n'envoie que le nouveau message
  second, err := thread.Send(ctx, anthropic.BetaMessageThreadSendParams{
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("How long does standard shipping usually take?")),
  	},
  })
  if err != nil {
  	panic(err)
  }

  for _, block := range second.Content {
  	if textBlock, ok := block.AsAny().(anthropic.BetaTextBlock); ok {
  		fmt.Println(textBlock.Text)
  	}
  }
  ```

  ```java Java
  var client = AnthropicOkHttpClient.fromEnv();

  // Créez le helper. Cet appel n'envoie aucune requête.
  var thread = client.beta().messages().thread(
      ThreadCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .cacheControl(BetaCacheControlEphemeral.builder().build())
          .system("You are a support agent for Acme. Keep replies short.")
          .build()
  );

  // Tour 1 : le helper crée un fil et envoie la conversation complète
  thread.send("Hi! I have a question about an order.");

  // Tour 2 : le helper poursuit le fil et n'envoie que le nouveau message
  var second = thread.send("How long does standard shipping usually take?");

  second.content().stream()
      .flatMap(block -> block.text().stream())
      .forEach(textBlock -> IO.println(textBlock.text()));
  ```

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

  // Créez le helper. Cet appel n'envoie aucune requête.
  $thread = $client->beta->messages->thread(
      maxTokens: 1024,
      model: Model::CLAUDE_OPUS_5_5,
      cacheControl: new BetaCacheControlEphemeral,
      system: 'You are a support agent for Acme. Keep replies short.',
  );

  // Tour 1 : le helper crée un fil et envoie la conversation complète.
  $thread->send(['role' => 'user', 'content' => 'Hi! I have a question about an order.']);

  // Tour 2 : le helper poursuit le fil et n'envoie que le nouveau message.
  $second = $thread->send(['role' => 'user', 'content' => 'How long does standard shipping usually take?']);

  foreach ($second->content as $block) {
      if ($block instanceof BetaTextBlock) {
          echo $block->text, PHP_EOL;
      }
  }
  ```

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

  # Créez le helper. Cet appel n'envoie aucune requête.
  thread = client.beta.messages.thread(
    model: :"claude-opus-5-5",
    max_tokens: 1024,
    cache_control: {type: "ephemeral"},
    system_: "You are a support agent for Acme. Keep replies short."
  )

  # Tour 1 : le helper crée un fil et envoie la conversation complète
  thread.send_message({role: "user", content: "Hi! I have a question about an order."})

  # Tour 2 : le helper poursuit le fil et n'envoie que le nouveau message
  second = thread.send_message({role: "user", content: "How long does standard shipping usually take?"})

  second.content.each do |block|
    puts block.text if block.type == :text
  end
  ```
</CodeGroup>

## Envoyer vous-même le champ `thread`

Pour construire vous-même les requêtes de fil, par exemple avec cURL, la CLI ou la méthode `create` habituelle d’un SDK, ajoutez le champ `thread` à chaque requête.

Envoyez l’en-tête bêta `message-threads-2026-08-12` sur chaque requête d’un fil.

Cet exemple crée un fil au premier tour et le continue au second. Le `cache_control` de niveau supérieur demande la mise en cache des prompts à chaque tour. Il prend effet une fois que la conversation dépasse la [longueur minimale pouvant être mise en cache](https://platform.claude.com/docs/fr/build-with-claude/prompt-caching).

<CodeGroup>
  ```bash cURL
  # Tour 1 : envoyer la conversation complète et créer un fil.
  curl -sS --fail-with-body https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: message-threads-2026-08-12" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "cache_control": {"type": "ephemeral"},
      "system": "You are a support agent for Acme. Keep replies short.",
      "messages": [{"role": "user", "content": "Hi! I have a question about an order."}],
      "thread": {"type": "create"}
    }'

  # Tour 2 : envoyer uniquement le nouveau message. Définir message_id sur l'id de la réponse du tour 1.
  # Omettre system et tools : le fil les conserve.
  curl -sS --fail-with-body https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: message-threads-2026-08-12" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "cache_control": {"type": "ephemeral"},
      "messages": [{"role": "user", "content": "How long does standard shipping usually take?"}],
      "thread": {"type": "continue", "previous_message_id": "'"$message_id"'"}
    }'
  ```

  ```bash CLI
  # Tour 1 : envoyer la conversation complète et créer un fil.
  ant beta:messages create --beta message-threads-2026-08-12 <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  cache_control:
    type: ephemeral
  system: "You are a support agent for Acme. Keep replies short."
  messages:
    - role: user
      content: "Hi! I have a question about an order."
  thread:
    type: create
  YAML

  # Tour 2 : envoyer uniquement le nouveau message. Définir message_id sur l'id de la réponse du tour 1.
  # Omettre system et tools : le fil les conserve.
  ant beta:messages create --beta message-threads-2026-08-12 <<YAML
  model: claude-opus-5-5
  max_tokens: 1024
  cache_control:
    type: ephemeral
  messages:
    - role: user
      content: "How long does standard shipping usually take?"
  thread:
    type: continue
    previous_message_id: $message_id
  YAML
  ```

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

  # Tour 1 : envoyer la conversation complète et créer un fil
  first = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      cache_control={"type": "ephemeral"},
      system="You are a support agent for Acme. Keep replies short.",
      messages=[{"role": "user", "content": "Hi! I have a question about an order."}],
      thread={"type": "create"},
      betas=["message-threads-2026-08-12"],
  )

  # Tour 2 : envoyer uniquement le nouveau message et l'id de la réponse du tour 1.
  # Omettez system et tools : le fil les conserve.
  second = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      cache_control={"type": "ephemeral"},
      messages=[
          {"role": "user", "content": "How long does standard shipping usually take?"}
      ],
      thread={"type": "continue", "previous_message_id": first.id},
      betas=["message-threads-2026-08-12"],
  )

  for block in second.content:
      if block.type == "text":
          print(block.text)
  ```

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

  // Tour 1 : envoyer la conversation complète et créer un fil
  const first = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    cache_control: { type: "ephemeral" },
    system: "You are a support agent for Acme. Keep replies short.",
    messages: [{ role: "user", content: "Hi! I have a question about an order." }],
    thread: { type: "create" },
    betas: ["message-threads-2026-08-12"]
  });

  // Tour 2 : envoyer uniquement le nouveau message et l'id de la réponse du tour 1.
  // Omettez system et tools : le fil les conserve.
  const second = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    cache_control: { type: "ephemeral" },
    messages: [{ role: "user", content: "How long does standard shipping usually take?" }],
    thread: { type: "continue", previous_message_id: first.id },
    betas: ["message-threads-2026-08-12"]
  });

  for (const block of second.content) {
    if (block.type === "text") {
      console.log(block.text);
    }
  }
  ```

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

  // Tour 1 : envoyer la conversation complète et créer un fil
  var first = await client.Beta.Messages.Create(
      new()
      {
          Model = Messages::Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          CacheControl = new(),
          System = "You are a support agent for Acme. Keep replies short.",
          Messages =
          [
              new BetaUserMessageParam { Content = "Hi! I have a question about an order." },
          ],
          Thread = new BetaThreadCreateParams(),
          Betas = [AnthropicBeta.MessageThreads2026_08_12],
      }
  );

  // Tour 2 : envoyer uniquement le nouveau message et l'id de la réponse du tour 1.
  // Omettre System et Tools : le fil les conserve.
  var second = await client.Beta.Messages.Create(
      new()
      {
          Model = Messages::Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          CacheControl = new(),
          Messages =
          [
              new BetaUserMessageParam { Content = "How long does standard shipping usually take?" },
          ],
          Thread = new BetaThreadContinueParams(first.ID),
          Betas = [AnthropicBeta.MessageThreads2026_08_12],
      }
  );

  foreach (var block in second.Content)
  {
      if (block.TryPickText(out var textBlock))
      {
          Console.WriteLine(textBlock.Text);
      }
  }
  ```

  ```go Go
  client := anthropic.NewClient()
  ctx := context.Background()

  // Tour 1 : envoyer la conversation complète et créer un fil
  threadCreate := anthropic.NewBetaThreadCreateParams()
  first, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
  	Model:        anthropic.ModelClaudeOpus5_5,
  	MaxTokens:    1024,
  	CacheControl: anthropic.NewBetaCacheControlEphemeralParam(),
  	System: []anthropic.BetaTextBlockParam{
  		{Text: "You are a support agent for Acme. Keep replies short."},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Hi! I have a question about an order.")),
  	},
  	Thread: anthropic.BetaMessageThreadParamUnion{OfCreate: &threadCreate},
  	Betas:  []anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageThreads2026_08_12},
  })
  if err != nil {
  	panic(err)
  }

  // Tour 2 : envoyer uniquement le nouveau message et l'id de la réponse du tour 1.
  // Omettez System et Tools : le fil les conserve.
  second, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
  	Model:        anthropic.ModelClaudeOpus5_5,
  	MaxTokens:    1024,
  	CacheControl: anthropic.NewBetaCacheControlEphemeralParam(),
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("How long does standard shipping usually take?")),
  	},
  	Thread: anthropic.BetaMessageThreadParamOfContinue(first.ID),
  	Betas:  []anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageThreads2026_08_12},
  })
  if err != nil {
  	panic(err)
  }

  for _, block := range second.Content {
  	if textBlock, ok := block.AsAny().(anthropic.BetaTextBlock); ok {
  		fmt.Println(textBlock.Text)
  	}
  }
  ```

  ```java Java
  var client = AnthropicOkHttpClient.fromEnv();

  // Tour 1 : envoyer la conversation complète et créer un fil
  var first = client.beta().messages().create(
      MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .cacheControl(BetaCacheControlEphemeral.builder().build())
          .system("You are a support agent for Acme. Keep replies short.")
          .addUserMessage("Hi! I have a question about an order.")
          .thread(BetaThreadCreateParams.builder().build())
          .addBeta(AnthropicBeta.MESSAGE_THREADS_2026_08_12)
          .build()
  );

  // Tour 2 : envoyer uniquement le nouveau message et l'id de la réponse du tour 1.
  // Omettez system et tools : le fil les conserve.
  var second = client.beta().messages().create(
      MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .cacheControl(BetaCacheControlEphemeral.builder().build())
          .addUserMessage("How long does standard shipping usually take?")
          .continueThread(first.id())
          .addBeta(AnthropicBeta.MESSAGE_THREADS_2026_08_12)
          .build()
  );

  second.content().stream()
      .flatMap(block -> block.text().stream())
      .forEach(textBlock -> IO.println(textBlock.text()));
  ```

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

  // Tour 1 : envoyer la conversation complète et créer un fil
  $first = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      cacheControl: new BetaCacheControlEphemeral,
      system: 'You are a support agent for Acme. Keep replies short.',
      messages: [
          ['role' => 'user', 'content' => 'Hi! I have a question about an order.'],
      ],
      thread: BetaThreadCreateParams::with(),
      betas: ['message-threads-2026-08-12'],
  );

  // Tour 2 : envoyer uniquement le nouveau message et l'id de la réponse du tour 1.
  // Omettez system et tools : le fil les conserve.
  $second = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      cacheControl: new BetaCacheControlEphemeral,
      messages: [
          ['role' => 'user', 'content' => 'How long does standard shipping usually take?'],
      ],
      thread: BetaThreadContinueParams::with(previousMessageID: $first->id),
      betas: ['message-threads-2026-08-12'],
  );

  foreach ($second->content as $block) {
      if ($block instanceof BetaTextBlock) {
          echo $block->text, PHP_EOL;
      }
  }
  ```

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

  # Tour 1 : envoyer la conversation complète et créer un fil
  first = client.beta.messages.create(
    model: :"claude-opus-5-5",
    max_tokens: 1024,
    cache_control: {type: "ephemeral"},
    system_: "You are a support agent for Acme. Keep replies short.",
    messages: [{role: "user", content: "Hi! I have a question about an order."}],
    thread: {type: "create"},
    betas: ["message-threads-2026-08-12"]
  )

  # Tour 2 : envoyer uniquement le nouveau message et l'id de la réponse du tour 1.
  # Omettre system_ et tools : le fil les conserve.
  second = client.beta.messages.create(
    model: :"claude-opus-5-5",
    max_tokens: 1024,
    cache_control: {type: "ephemeral"},
    messages: [{role: "user", content: "How long does standard shipping usually take?"}],
    thread: {type: "continue", previous_message_id: first.id},
    betas: ["message-threads-2026-08-12"]
  )

  second.content.each do |block|
    puts block.text if block.type == :text
  end
  ```
</CodeGroup>

## Ce qu’il faut envoyer à chaque requête

| Groupe              | Champs                                                                                                                                                                                                                                                               | Règle                                                                                                                                                                                                                                         |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Création uniquement | `system`, `tools`                                                                                                                                                                                                                                                    | Envoyez-les uniquement sur la requête de création, avec les éventuels points d’arrêt `cache_control` qui les concernent. Envoyer l’un ou l’autre sur une requête de continuation, même avec la valeur `null`, renvoie une erreur 400.         |
| Fixes               | `model`, `tool_choice`, `thinking`, `mcp_servers` (à l’exception du jeton d’autorisation de chaque serveur), `context_management`, `output_config`, les `skills` dans `container`, le `cache_control` de niveau supérieur et l’ensemble des valeurs `anthropic-beta` | Envoyez-les sur chaque requête du fil, avec les mêmes valeurs que sur la requête de création. Une valeur différente renvoie une erreur 400 avec le code `thread_fingerprint_mismatch`, et le message d’erreur nomme les champs qui diffèrent. |
| Libres              | `max_tokens`, `stop_sequences`, `stream`, `metadata`, `service_tier` et les autres champs non mentionnés sur cette page                                                                                                                                              | Ils peuvent changer d’un tour à l’autre.                                                                                                                                                                                                      |

L’API ne stocke pas les URL des serveurs MCP, les jetons d’autorisation MCP ni l’`id` du conteneur. Envoyez `mcp_servers` et `container` sur chaque requête qui les utilise. Un jeton d’autorisation MCP peut changer d’une requête à l’autre.

L’assistant de fil du SDK omet `system` et `tools` des requêtes de continuation pour vous et renvoie les champs fixes à chaque tour.

Si vous utilisez le [repli côté serveur](https://platform.claude.com/docs/fr/build-with-claude/refusals-and-fallback#server-side-fallback), envoyez le champ `fallbacks` sur chaque requête d’un fil ou sur aucune. Consultez [Utiliser des replis avec un fil](https://platform.claude.com/docs/fr/build-with-claude/message-threads#fallbacks).

Pour modifier un champ de création uniquement ou un champ fixe, démarrez un nouveau fil : envoyez la conversation complète dans une requête de création avec les nouvelles valeurs.

Sur Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Sonnet 5.5 et Claude Haiku 5.5, modifier `system` ou `tools` rend invalides les blocs `thinking` et `redacted_thinking` déjà présents dans la conversation, et la requête de création peut renvoyer une erreur 400. Pour l’éviter, omettez tous les blocs `thinking` et `redacted_thinking` de la conversation que vous envoyez. Le modèle répond alors sans ce raisonnement antérieur. Consultez [Ce qui compte comme une modification](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#what-counts-as-an-edit), [Lorsque `prefix_mismatch_behavior` n’est pas défini](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#enforcement) et [Ce que fait l’API avec un bloc invalide](https://platform.claude.com/docs/fr/build-with-claude/preserved-thinking#mismatch-behavior).

N’envoyez que les nouveaux messages sur une requête de continuation. L’API ne les compare pas aux messages dont elle dispose déjà. Un message que vous renvoyez peut apparaître deux fois dans la conversation, ou la requête peut renvoyer une erreur. Par exemple, une requête de continuation qui commence par la réponse précédente renvoie une erreur.

Les nouveaux messages commencent généralement par un message `user` : votre prochain tour utilisateur, ou les blocs `tool_result` qui répondent à un `tool_use` dans la réponse précédente. Si une réponse s’arrête avec [`stop_reason: "pause_turn"`](https://platform.claude.com/docs/fr/build-with-claude/handling-stop-reasons#pause-turn), reprenez-la avec une requête de continuation à partir de l’`id` de cette réponse et une liste `messages` vide (`"messages": []`). Si cette requête renvoie une erreur 404, rejouez la conversation complète, y compris la réponse mise en pause, dans une nouvelle requête de création. N’envoyez pas de nouveau message `user` pendant que le tour est en pause : l’API le rejette. Avec l’assistant de fil du SDK, appelez `send()` (go, csharp: `Send()`; ruby: `send_message()`) sans messages : l’assistant envoie cette requête et effectue le rejeu en cas d’erreur 404.

Un fil fonctionne en ajout seul, et chaque `id` de réponse ne peut être continué qu’une seule fois. Continuez toujours à partir du dernier `id` de réponse du fil. Pour modifier ou créer une branche à partir d’un message antérieur, démarrez un nouveau fil avec une requête de création. Pour remplacer des tours antérieurs par un résumé, consultez [Compacter une conversation](https://platform.claude.com/docs/fr/build-with-claude/message-threads#compaction).

## Mise en cache des prompts sur un fil

Un fil ne met pas votre prompt en cache à votre place. La [mise en cache des prompts](https://platform.claude.com/docs/fr/build-with-claude/prompt-caching) fonctionne comme sans fil : c’est vous qui choisissez l’emplacement des points d’arrêt de cache.

Pour mettre en cache chaque tour, envoyez un `cache_control` de niveau supérieur sur chaque requête du fil, comme dans l’exemple précédent. L’API l’applique au dernier bloc des `messages` de chaque requête pouvant être mis en cache. Chaque tour lit alors la conversation antérieure depuis le cache et y écrit le nouveau tour. Le `cache_control` de niveau supérieur est un champ fixe : envoyez la même valeur sur chaque requête.

Vous pouvez également placer vous-même des points d’arrêt `cache_control` sur des blocs :

* Les points d’arrêt que vous envoyez dans la requête de création continuent de fonctionner à chaque tour ultérieur s’ils se trouvent sur `tools`, sur `system` ou sur un bloc de message antérieur au dernier. Un point d’arrêt sur le dernier bloc des `messages` d’une requête écrit le cache lors de cette requête. Pour mettre en cache chaque nouveau tour, envoyez un point d’arrêt à chaque requête. Une requête sans point d’arrêt peut tout de même lire une partie de la conversation depuis le cache.
* Vous ne pouvez pas déplacer ni supprimer un point d’arrêt après l’avoir envoyé, car une requête de continuation ne peut pas renvoyer un message antérieur.
* Une requête avec `thread` peut comporter au maximum 4 points d’arrêt `cache_control`. Le `cache_control` de niveau supérieur compte pour un. Les points d’arrêt sur `system` et `tools` de la requête de création sont comptés à nouveau à chaque requête de continuation. Les points d’arrêt sur les messages stockés antérieurs ne sont pas comptés. Un point d’arrêt de trop renvoie une erreur 400 avec le code `thread_unsupported_request`.
* Si vous placez vous-même des points d’arrêt sur des blocs de message, supprimez-les des messages antérieurs lorsque vous rejouez la conversation dans une nouvelle requête de création, et conservez-en un sur le dernier bloc, afin que la requête reste dans la limite de 4.

## Streaming

Les fils fonctionnent avec le [streaming](https://platform.claude.com/docs/fr/build-with-claude/streaming). L’`id` de la réponse arrive dans l’événement `message_start`, mais ne continuez à partir de celui-ci qu’après avoir reçu l’événement `message_stop`. Une requête de continuation envoyée plus tôt peut renvoyer une erreur 404.

Si le flux d’une requête de continuation s’interrompt avant `message_stop`, renvoyez la même requête de continuation. Si cette requête renvoie une erreur `thread_already_continued` ou `thread_continue_in_flight`, rejouez la conversation complète dans une nouvelle requête de création.

Votre connexion a pu s’interrompre alors que le serveur générait encore la réponse, ou après que le serveur l’a enregistrée. C’est pourquoi l’API peut rejeter la nouvelle tentative. Le rejeu est toujours sûr.

L’assistant de fil du SDK ne réessaie pas la requête de continuation après un flux interrompu. Consultez [Comportement de l’assistant du SDK](https://platform.claude.com/docs/fr/build-with-claude/message-threads#sdk-helper-handles).

## Récupérer lorsqu’un fil ne peut pas être continué

Une requête de continuation renvoie une erreur 404 avec `error.details.error_code` défini sur `thread_not_found` lorsque l’API ne peut pas continuer le fil. La réponse n’en indique pas la raison. Les causes possibles sont notamment les suivantes :

* Le fil a expiré.
* L’API a servi le tour précédent mais ne l’a pas stocké. Par exemple, l’API ne stocke pas une réponse qui se termine par un appel d’outil interrompu par `max_tokens`.
* Un modèle de repli a rédigé la réponse précédente. Consultez [Utiliser des replis avec un fil](https://platform.claude.com/docs/fr/build-with-claude/message-threads#fallbacks).
* La réponse précédente est toujours en cours de génération.
* La requête provient d’une organisation ou d’un espace de travail différent.
* La requête provient d’un utilisateur ou d’un compte de service différent de celui qui a créé le fil. Un fil créé avec une [clé d’espace de travail (ancienne)](https://platform.claude.com/docs/fr/manage-claude/authentication#key-types) reste lié à cette clé ; utilisez donc la même clé pour l’ensemble du fil.
* Les nouveaux messages ajoutent quelque chose que la conversation stockée ne peut pas accepter. Par exemple, la première image d’une conversation qui n’en contenait aucune peut renvoyer cette erreur.

Pour récupérer, envoyez la conversation complète à partir de votre propre copie dans une nouvelle requête de création, avec `system` et `tools`. L’assistant de fil du SDK envoie cette requête de création une fois de lui-même, et omet alors les points d’arrêt `cache_control` des tours précédents. Si des messages antérieurs de votre copie comportent des points d’arrêt `cache_control`, supprimez-les d’abord (voir [Mise en cache des prompts sur un fil](https://platform.claude.com/docs/fr/build-with-claude/message-threads#prompt-caching)). Poursuivez ensuite à partir du nouvel `id` de réponse. Si c’est un modèle de repli qui a rédigé la réponse précédente, consultez [Utiliser des replis avec un fil](https://platform.claude.com/docs/fr/build-with-claude/message-threads#fallbacks). Pour écarter les causes liées à la propriété, utilisez la même clé API et le même espace de travail pour chaque requête d’un fil. Sur Claude Platform on AWS, signez chaque requête d’un fil avec les identifiants du rôle IAM ou de l’utilisateur IAM qui l’a créé.

Une requête pour un modèle qui n’existe pas renvoie également une erreur 404 ; vérifiez donc `error.details.error_code` avant de rejouer.

Si une requête de continuation renvoie toujours une erreur 404 juste après votre rejeu, l’API peut être incapable de stocker cette conversation, par exemple une conversation très volumineuse. Envoyez-la sans `thread`. L’assistant de fil du SDK le fait lorsque vous le créez avec `unsupported_request_behavior` (typescript, java, php: `unsupportedRequestBehavior`; go, csharp: `UnsupportedRequestBehavior`) défini sur `continue_unthreaded` (ruby: `:continue_unthreaded`; java: `CONTINUE_UNTHREADED`; csharp: `ContinueUnthreaded`; go: `BetaMessageThreadUnsupportedRequestBehaviorContinueUnthreaded`). Sinon, il rejoue à chaque tour.

### Après un refus

Lorsqu’une réponse comporte `stop_reason: "refusal"`, ne poursuivez pas le fil. L’API peut déjà contenir le tour refusé, et une requête de continuation ne peut pas le supprimer. Démarrez un nouveau fil avec une requête de création qui omet ou reformule le tour ayant conduit au refus. Consultez [Refus et repli](https://platform.claude.com/docs/fr/build-with-claude/refusals-and-fallback). L’assistant de fil du SDK le fait pour vous : il ne conserve pas le tour refusé, et son tour suivant démarre un nouveau fil.

### Utiliser des replis avec un fil

Le [repli côté serveur](https://platform.claude.com/docs/fr/build-with-claude/refusals-and-fallback#server-side-fallback) est disponible avec les fils sur l’API Claude. Décidez-en lors de la création du fil : envoyez `fallbacks` sur chaque requête du fil, ou sur aucune. La valeur de `fallbacks` peut changer d’une requête à l’autre. Une requête de continuation qui ajoute ou supprime `fallbacks` renvoie une erreur 400 avec le code `thread_fingerprint_mismatch`.

Un fil conserve un seul modèle ; l’API ne stocke donc pas un tour rédigé par un modèle de repli. Vous recevez la réponse comme d’habitude, mais vous ne pouvez pas continuer à partir de son `id`. Après chaque réponse, suivez ces étapes :

1. Si `stop_reason` vaut `"refusal"`, suivez [Après un refus](https://platform.claude.com/docs/fr/build-with-claude/message-threads#after-a-refusal).

2. Sinon, recherchez une entrée `fallback_message` dans `usage.iterations`. Sur un flux, lisez-la à partir de l’événement `message_delta` final. S’il n’y en a aucune, poursuivez le fil comme d’habitude.

3. S’il y en a une, c’est un modèle de repli qui a rédigé la réponse. Envoyez la conversation complète, y compris cette réponse et votre message suivant, dans une nouvelle requête de création. Conservez l’en-tête bêta `server-side-fallback-2026-07-01` sur celle-ci. Choisissez l’une de ces deux requêtes :

   * **La même requête à nouveau.** Conservez `model`, `fallbacks` et vos autres paramètres tels qu’ils étaient. Si le modèle que vous avez demandé répond, l’API stocke le nouveau fil. Si un modèle de repli répond, la réponse contient à nouveau une entrée `fallback_message` et l’API ne la stocke pas, répétez donc cette étape au tour suivant. Le [routage persistant](https://platform.claude.com/docs/fr/build-with-claude/refusals-and-fallback#sticky-routing) peut envoyer ces requêtes directement au modèle de repli, de sorte que chaque tour peut envoyer la conversation complète. L’assistant de fil du SDK fonctionne de cette manière.
   * **Un nouveau fil sur le modèle de repli.** Définissez `model` sur le `model` de cette entrée `fallback_message`, omettez `fallbacks` et utilisez des paramètres que ce modèle accepte. L’API stocke ce fil immédiatement, et il reste sur le modèle de repli. La tentative de repli a pu s’exécuter avec des paramètres différents de ceux que vous avez envoyés, donc l’API pourrait rejeter des valeurs copiées de votre première requête.

4. Revenez à l’étape 1 avec la réponse à cette requête. Lorsqu’elle ne comporte aucune entrée `fallback_message`, poursuivez le nouveau fil à partir de son `id`.

Le [routage persistant](https://platform.claude.com/docs/fr/build-with-claude/refusals-and-fallback#sticky-routing) commence après qu’une requête a basculé vers un modèle de repli (une requête de création, ou une requête sans `thread`). Pendant environ une heure, il peut envoyer les requêtes de création ultérieures pour la même conversation qui incluent `fallbacks` directement au modèle de repli, sans essayer le modèle que vous avez demandé. L’API ne stocke aucun de ces tours, et chaque tour ayant reçu une réponse relance ce délai d’une heure. Une requête de continuation ne déclenche jamais ce routage et ne l’utilise jamais. Le routage persistant ne s’applique pas si votre organisation ou votre espace de travail utilise la conservation zéro des données ou des clés de chiffrement gérées par le client.

## Compacter une conversation

Un fil fonctionne en ajout seul ; vous ne pouvez donc pas remplacer ses tours antérieurs par un résumé. Pour compacter une conversation, démarrez un nouveau fil à partir du résumé. Rédigez le résumé dans votre code, et envoyez-le comme un message ordinaire dans une nouvelle requête de création, avec `system` et `tools`. La [compaction à la demande](https://platform.claude.com/docs/fr/build-with-claude/compaction-on-demand) n’est pas disponible avec les fils (voir [Fonctionnalités que les fils ne prennent pas en charge](https://platform.claude.com/docs/fr/build-with-claude/message-threads#unsupported)).

## Comportement de l’assistant du SDK

Ce que l’assistant fait pour vous :

* Ajoute l’en-tête bêta `message-threads-2026-08-12` à chaque requête qui utilise le fil.
* Crée un fil au premier tour et le poursuit ensuite, en n’envoyant que les nouveaux messages et en omettant `system` et `tools`.
* Rejoue une fois la conversation complète dans une nouvelle requête de création lorsqu’une requête de continuation renvoie `thread_not_found`, `thread_already_continued` ou `thread_continue_in_flight`.
* Reprend une réponse `pause_turn` lorsque vous appelez `send()` (go, csharp: `Send()`; ruby: `send_message()`) sans messages.
* Démarre un nouveau fil après un refus. Vous recevez la réponse `stop_reason: "refusal"` comme d’habitude, mais l’assistant ne conserve pas ce tour : il reprend les messages que vous avez fournis à cet appel. Les messages que vous avez ajoutés avec `thread.append(...)` (csharp, go: `thread.Append(...)`; php: `$thread->append(...)`), ou fournis lors de la création de l’assistant, restent en attente. Votre tour suivant les envoie avec la conversation antérieure au tour refusé, dans une nouvelle requête de création. Envoyez un message reformulé ou, si un message en attente a conduit au refus, démarrez un nouveau fil à partir des params sans ce message.
* Envoie une nouvelle requête de création après une réponse d’un modèle de repli. Lorsqu’une réponse comporte une entrée `fallback_message` dans `usage.iterations`, l’assistant conserve la réponse et envoie la conversation complète dans une nouvelle requête de création au tour suivant. Il n’attend pas une erreur 404. Cette requête conserve le `model` et les `fallbacks` que vous avez définis.
* Omet les points d’arrêt `cache_control` des tours précédents chaque fois qu’il les renvoie, par exemple lors d’un rejeu ou au premier tour d’une duplication. Vos messages les plus récents, `system`, `tools` et le `cache_control` de niveau supérieur sont envoyés tels que vous les avez fournis.

Ce que vous gérez vous-même :

* **Modèles de repli.** Tant que l’API continue de répondre à partir d’un modèle de repli, l’assistant envoie la conversation complète dans une nouvelle requête de création à chaque tour, car l’API ne stocke aucun de ces tours. Il revient aux requêtes de continuation après une réponse du modèle que vous avez demandé. Pour plutôt déplacer la conversation vers le modèle de repli, démarrez un nouveau fil à partir des params avec ce `model` et sans `fallbacks`, comme dans [Utiliser des replis avec un fil](https://platform.claude.com/docs/fr/build-with-claude/message-threads#fallbacks).
* **Flux interrompus.** Si un flux se termine au milieu d’une réponse, l’assistant conserve les blocs terminés et tout texte reçu, et le tour suivant envoie la conversation complète dans une nouvelle requête de création. L’assistant ne réessaie pas de lui-même : pour renvoyer plutôt le tour interrompu, appelez `send()` (go, csharp: `Send()`; ruby: `send_message()`) sans messages. Si la partie conservée se termine par des appels d’outils, répondez-y dans votre message suivant. Si vous arrêtez de lire un flux après qu’il a indiqué `stop_reason: "refusal"`, l’assistant traite ce tour comme un refus.
* **Autres erreurs.** Les erreurs `thread_fingerprint_mismatch` et `thread_unsupported_request` parviennent à votre code. Pour continuer sans `thread` après une erreur `thread_unsupported_request`, créez l’assistant avec `unsupported_request_behavior` (typescript, java, php: `unsupportedRequestBehavior`; go, csharp: `UnsupportedRequestBehavior`) défini sur `continue_unthreaded` (ruby: `:continue_unthreaded`; java: `CONTINUE_UNTHREADED`; csharp: `ContinueUnthreaded`; go: `BetaMessageThreadUnsupportedRequestBehaviorContinueUnthreaded`). Avec ce paramètre, l’assistant cesse également d’utiliser `thread` lorsque la première requête de continuation après un rejeu renvoie à nouveau `thread_not_found`. L’API peut être incapable de stocker cette conversation. Sans ce paramètre, l’assistant rejoue à chaque tour. Un tool runner qui crée son propre fil utilise ce paramètre par défaut.

Le tool runner bêta du SDK utilise également un fil par défaut, que vous pouvez désactiver lorsque vous créez le runner.

### Autres méthodes de l’assistant

| Pour faire ceci                                                  | Utilisez                                                                                                                                                                                                                                                                                                                             |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Diffuser un tour en streaming                                    | `thread.stream(...)` (csharp: `thread.SendStreaming(...)`; go: `thread.SendStreaming(ctx, params)`; java: `thread.sendStreaming(...)`; php: `$thread->sendStream(...)`)                                                                                                                                                              |
| Réponse finale d’un tour en streaming                            | `stream.get_final_message()` (typescript: `stream.finalMessage()`; csharp: `thread.LastMessage`; go: `thread.LastMessage()`; java: `thread.lastMessage()`; php: `$thread->lastMessage()`; ruby: `stream.accumulated_message`)                                                                                                        |
| Conversation complète                                            | `thread.messages` (csharp: `thread.Messages`; go: `thread.Messages()`; java: `thread.messages()`; php: `$thread->messages()`)                                                                                                                                                                                                        |
| `id` de la réponse à partir de laquelle le tour suivant continue | `thread.previous_message_id` (typescript: `thread.previousMessageId`; csharp: `thread.PreviousMessageID`; go: `thread.PreviousMessageID()`; java: `thread.previousMessageId()`; php: `$thread->previousMessageId()`)                                                                                                                 |
| Ajouter des messages sans les envoyer                            | `thread.append(...)` (csharp, go: `thread.Append(...)`; php: `$thread->append(...)`)                                                                                                                                                                                                                                                 |
| Modifier des champs pour les tours suivants                      | `thread.update(...)` (csharp: `thread.Update(p => p with { ... })`; go: `thread.Params.MaxTokens = ...`; java: `thread.update(b -> ...)`; php: `$thread->update([...])`)                                                                                                                                                             |
| Copier le fil                                                    | `thread.fork()` (csharp, go: `thread.Fork()`; php: `$thread->fork()`; ruby: `thread.fork`)                                                                                                                                                                                                                                           |
| Champs et conversation, pour démarrer un nouveau fil             | `thread.params` (csharp, go: `thread.Params`; java: `thread.params()`; php: `$thread->params()`)                                                                                                                                                                                                                                     |
| Tool runner sur ce fil                                           | `thread.tool_runner()` (typescript, java: `thread.toolRunner()`; csharp: `thread.ToolRunner(tools)`; go: `thread.NewToolRunner(tools)`; php: `$thread->toolRunner()`; ruby: `thread.tool_runner`)                                                                                                                                    |
| Tool runner sans fil                                             | `tool_runner(..., thread=False)` (typescript: `toolRunner({ ..., thread: false })`; csharp: `ToolRunner(parameters, tools, thread: false)`; go: `BetaToolRunnerParams{DisableThread: true}`; java: `ToolRunnerCreateParams.builder().thread(false)`; php: `toolRunner(..., thread: false)`; ruby: `tool_runner(..., thread: false)`) |

**Streaming.** L’assistant enregistre la réponse lorsque le flux atteint `message_stop` ; lisez donc le flux jusqu’à la fin. Si vous arrêtez la lecture plus tôt, terminez le flux afin que le fil soit libre pour le tour suivant :

* Python : quittez le bloc `with`.
* TypeScript : quittez la boucle ou appelez `abort()`.
* Go : appelez `Close`.
* Java et Ruby : appelez `close()`.
* C# : libérez l’énumérateur. Quitter `await foreach` le fait.
* PHP : appelez `close()`.

En C#, la requête est envoyée lorsque vous commencez à lire le flux.

En C#, Go, Java et PHP, après un refus, `thread.LastMessage` (go: `thread.LastMessage()`; java: `thread.lastMessage()`; php: `$thread->lastMessage()`) renvoie toujours la réponse du tour précédent, ou rien lors d’un premier tour. Lisez le refus à partir des événements du flux.

**Modification des champs.** Une mise à jour n’envoie rien et s’applique à chaque tour suivant. Une fois qu’un fil a une réponse, l’assistant refuse un tour qui modifie `system` ou `tools`, et l’API rejette une modification de tout autre champ fixe (voir [Ce qu’il faut envoyer à chaque requête](https://platform.claude.com/docs/fr/build-with-claude/message-threads#what-to-send)). Pour modifier l’un de ces champs, démarrez un nouveau fil à partir des params, ou dupliquez le fil et mettez à jour la copie avant son premier tour.

**Duplication.** Une duplication (fork) copie la conversation, les champs et les options de requête, et n’envoie rien. Son premier tour envoie la conversation complète dans une nouvelle requête de création, et les deux fils sont ensuite indépendants. Une duplication part toujours de la conversation entière, et non d’une réponse antérieure.

**Params.** Les params contiennent les champs de l’assistant et la conversation complète. Transmettez-les à la méthode qui crée un assistant pour démarrer un nouveau fil, par exemple avec un `system` différent (voir [Ce qu’il faut envoyer à chaque requête](https://platform.claude.com/docs/fr/build-with-claude/message-threads#what-to-send)), ou avec des `messages` raccourcis pour supprimer les tours ultérieurs. Un fil que vous démarrez à partir des params envoie chaque message tel que vous l’avez fourni, points d’arrêt `cache_control` compris ; restez donc dans la limite de 4 (voir [Mise en cache des prompts sur un fil](https://platform.claude.com/docs/fr/build-with-claude/message-threads#prompt-caching)). Sauf en Ruby, les params omettent les options de requête ; transmettez-les donc à nouveau.

**Sortie structurée.** Indiquez le format de sortie lorsque vous créez l’assistant. Un tour ultérieur ne peut pas le modifier. La manière d’obtenir le résultat analysé dépend du SDK :

* Python et TypeScript : appelez `thread.parse(...)`.
* C# : créez l’assistant avec `client.Beta.Messages.Thread<T>(...)`.
* Go : `Send` désérialise dans la structure vers laquelle pointe `Params.OutputConfig.Format.Schema`.
* Java : créez l’assistant avec `thread(...)` et `outputConfig(MyClass.class)`.
* PHP : `send()` définit `parsed` sur les blocs de texte lorsque `outputConfig` désigne une classe de modèle.
* Ruby : passez `output_config: {format: MyModel}` à `thread(...)`, puis lisez `reply.parsed_output`.

## Erreurs

L’API renvoie les erreurs de ce tableau avant l’exécution du modèle. La requête ne consomme aucun token, et le fil ainsi que son délai d’expiration ne changent pas. `error.type` vaut `invalid_request_error` pour les erreurs 400 et `not_found_error` pour l’erreur 404.

| Statut | `error_code`                  | Signification                                                                                                                                                            | Que faire                                                                                                     |
| ------ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- |
| 404    | `thread_not_found`            | L’API ne peut pas continuer le fil.                                                                                                                                      | Envoyez la conversation complète dans une nouvelle requête de création.                                       |
| 400    | `thread_fingerprint_mismatch` | Un champ fixe diffère de la valeur stockée avec le fil. Le message d’erreur nomme les champs.                                                                            | Conservez les mêmes champs fixes, ou démarrez un nouveau fil pour en modifier un.                             |
| 400    | `thread_already_continued`    | Chaque `id` de réponse ne peut être continué qu’une seule fois.                                                                                                          | Continuez à partir du dernier `id` de réponse du fil. Si votre client n’a jamais reçu cette réponse, rejouez. |
| 400    | `thread_continue_in_flight`   | Une autre requête de continuation à partir de cet `id` de réponse est toujours en cours. Il s’agit généralement de votre propre tentative précédente.                    | Laissez-la se terminer et continuez à partir de son `id` de réponse, ou rejouez.                              |
| 400    | `thread_unsupported_request`  | La requête utilise une fonctionnalité ou un paramètre d’organisation que les fils ne prennent pas en charge. `error.details.unsupported` le nomme lorsqu’il est présent. | Supprimez cette fonctionnalité de la requête, ou envoyez la conversation complète sans `thread`.              |

Certaines erreurs 400 pour les requêtes de fil ne comportent pas d’`error_code`, par exemple une requête de continuation sans `previous_message_id`, ou une requête qui inclut `system` ou `tools`.

L’exemple suivant montre un corps d’erreur :

```json
{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "thread: a maximum of 4 blocks with cache_control may be provided when `thread` is set. Found 5.",
    "details": {
      "error_code": "thread_unsupported_request",
      "unsupported": ["cache_control"]
    }
  },
  "request_id": "req_011CSHoEeqs5C35K2UUqR7Fy"
}
```

## Fonctionnalités que les fils ne prennent pas en charge

Les fils ne prennent pas en charge ces fonctionnalités :

* [Message Batches](https://platform.claude.com/docs/fr/build-with-claude/batch-processing). Un élément de requête qui inclut `thread` se termine par une `invalid_request_error` dans les résultats du lot.
* [Comptage des tokens](https://platform.claude.com/docs/fr/build-with-claude/token-counting). Une requête de comptage des tokens qui inclut `thread` renvoie une erreur 400. Comptez plutôt la conversation complète, avec `system` et `tools`.
* [Compaction](https://platform.claude.com/docs/fr/build-with-claude/compaction). La [compaction à la demande](https://platform.claude.com/docs/fr/build-with-claude/compaction-on-demand) n’est pas disponible avec les fils. Une requête qui inclut `thread` renvoie une erreur 400 si elle définit le paramètre `compaction`, ou si elle envoie un bloc `compaction` avec l’en-tête bêta `compact-2026-09-04`. Consultez [Compacter une conversation](https://platform.claude.com/docs/fr/build-with-claude/message-threads#compaction).
* [Édition du contexte](https://platform.claude.com/docs/fr/build-with-claude/context-editing), à l’exception de `clear_thinking_20251015` avec `keep: "all"`.
* Les organisations pour lesquelles la [préparation HIPAA](https://platform.claude.com/docs/fr/manage-claude/api-and-data-retention#hipaa-readiness) est activée.
* Les organisations pour lesquelles les [Inference hooks](https://platform.claude.com/docs/fr/manage-claude/inference-hooks) sont activés.

L’API rejette la plupart des requêtes que les fils ne prennent pas en charge avec une erreur 400 et le code `thread_unsupported_request`. Lorsque `error.details.unsupported` est présent, il contient l’une de ces valeurs :

| Valeur               | Signification                                                                                                                                                                                         |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `context_management` | La requête utilise une gestion du contexte ou une compaction que les fils ne prennent pas en charge.                                                                                                  |
| `cache_control`      | La requête comporte plus de 4 points d’arrêt `cache_control`. Consultez [Mise en cache des prompts sur un fil](https://platform.claude.com/docs/fr/build-with-claude/message-threads#prompt-caching). |
| `fallbacks`          | La requête définit `fallbacks`, et votre organisation ne peut pas utiliser `fallbacks` avec les fils.                                                                                                 |
| `hipaa`              | La préparation HIPAA est activée pour votre organisation.                                                                                                                                             |
| `inference_hooks`    | Les Inference hooks sont activés pour votre organisation.                                                                                                                                             |

L’API peut ajouter des valeurs à cette liste. Si vous recevez une valeur que vous ne reconnaissez pas, envoyez la conversation complète sans `thread`. Une requête qui remplit plusieurs de ces conditions reçoit une erreur qui n’en nomme qu’une seule.

## Limitations

* Il n’existe aucune API pour lister, lire ou supprimer un fil.
* Les fils sont disponibles sur l’API Claude, [Claude Platform on AWS](https://platform.claude.com/docs/fr/build-with-claude/claude-platform-on-aws), Claude Models on Google Cloud (Anthropic managed), et [Claude in Microsoft Foundry](https://platform.claude.com/docs/fr/build-with-claude/claude-in-microsoft-foundry).

## Tarification et limites de débit

Les fils ne modifient ni la tarification ni les [limites de débit](https://platform.claude.com/docs/fr/api/rate-limits).

## Conservation des données

Les fils de messages ne sont pas éligibles à la ZDR. L’utilisation de cette fonctionnalité n’affecte pas votre utilisation d’autres fonctionnalités éligibles à la ZDR. L’API conserve un fil en mémoire, chiffré avec une clé gérée par le serveur, ne l’écrit jamais sur un stockage durable, et le supprime au plus tard 1 heure après sa dernière utilisation.

Un fil contient la conversation que l’API envoie au modèle, les `system` et `tools` de la requête de création, ainsi qu’une empreinte des champs fixes, qu’elle utilise pour vérifier les requêtes ultérieures. Il contient les fichiers par référence ; gardez donc disponible chaque fichier utilisé par la conversation tant que vous utilisez le fil.

Pour l’éligibilité à la ZDR de l’ensemble des fonctionnalités, consultez [API et conservation des données](https://platform.claude.com/docs/fr/manage-claude/api-and-data-retention).

## Voir aussi

* [Mise en cache des prompts](https://platform.claude.com/docs/fr/build-with-claude/prompt-caching)
* [Streaming](https://platform.claude.com/docs/fr/build-with-claude/streaming)
* [Erreurs](https://platform.claude.com/docs/fr/api/errors)

## Disponibilité

Fils de messages sont en bêta sur tous les modèles.

### Prise en charge de l’API

#### [Messages API](https://platform.claude.com/docs/fr/build-with-claude/working-with-messages)

* Disponibilité : Disponible

| Statut | Plateformes cloud                                                                                                                                                                                                                                                                                                                                                                      |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Bêta   | Claude API, [Claude Platform on AWS](https://platform.claude.com/docs/fr/build-with-claude/claude-platform-on-aws), [Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/fr/build-with-claude/claude-models-on-google-cloud/anthropic-managed), [Microsoft Foundry](https://platform.claude.com/docs/fr/build-with-claude/claude-in-microsoft-foundry) |

### En-têtes bêta requis

[Présentation des en-têtes bêta](https://platform.claude.com/docs/fr/api/beta-headers)

Les en-têtes bêta vous permettent d’accéder à des fonctionnalités expérimentales et à de nouvelles capacités des modèles avant qu’elles ne fassent partie de l’API standard.

* `message-threads-2026-08-12`

### Traitement des données

[Présentation du traitement des données](https://platform.claude.com/docs/fr/manage-claude/api-and-data-retention#feature-eligibility)

| Élément | Zéro conservation des données                                                                                                                                                                                                                                                                                                                                                                                                                                                       | HIPAA        |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| Statut  | Non éligible                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | Non éligible |
| Détails | Le contenu d’un fil (la conversation, l’invite système et les outils) est conservé en mémoire, chiffré avec une clé gérée par le serveur, jamais écrit dans un stockage durable, et supprimé au plus tard 1 heure après la dernière utilisation du fil. L’utilisation de cette fonctionnalité n’affecte pas votre utilisation des autres fonctionnalités éligibles à la ZDR. [En savoir plus](https://platform.claude.com/docs/fr/build-with-claude/message-threads#data-retention) | —            |

Endpoints concernés :

* `/v1/messages` avec `thread`
