---
title: Mensagens de sistema e alterações de ferramentas no meio da conversa
url: https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages
description: Altere instruções de sistema ou a disponibilidade de ferramentas no meio de uma conversa sem invalidar o prefixo em cache que veio antes delas.
---

<Note>
  Para saber como a "zero data retention" (retenção zero de dados), ou ZDR, se aplica a este recurso, consulte [API e retenção de dados](https://platform.claude.com/docs/pt-BR/manage-claude/api-and-data-retention).
</Note>

As instruções de sistema normalmente ficam no campo `system` de nível superior, antes de todas as mensagens da conversa. Essa posição é ótima para o [prompt caching](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching) (cache de prompt): o "system prompt" (prompt do sistema) faz parte do prefixo estável, então os turnos subsequentes atingem o cache. Mas é uma posição ruim para instruções cuja necessidade você só descobre no meio de uma sessão. Editar o campo `system` de nível superior altera o próprio início do prompt e invalida o cache de tudo o que vem depois.

As mensagens de sistema no meio da conversa resolvem esse problema. Em vez de editar o campo `system` de nível superior, você anexa uma mensagem `{"role": "system"}` no ponto da conversa em que a nova instrução se torna relevante. O prefixo em cache permanece o mesmo, então a próxima requisição ainda o lê do cache. A nova instrução continua sendo aplicada como uma instrução de sistema, e não como texto comum do usuário.

<Note>
  As mensagens de sistema no meio da conversa estão disponíveis na Claude API, no [Claude no Amazon Bedrock](https://platform.claude.com/docs/pt-BR/build-with-claude/claude-in-amazon-bedrock) e no [Google Cloud](https://platform.claude.com/docs/pt-BR/build-with-claude/claude-on-vertex-ai).

  Este recurso está disponível no Claude Fable 5.1, [Claude Mythos 5.1](https://platform.claude.com/docs/pt-BR/models/mythos-5-1/overview), Claude Fable 5, [Claude Mythos 5](https://platform.claude.com/docs/pt-BR/models/mythos-5/overview), Claude Opus 5.5, Claude Opus 4.8, Claude Opus 5, Claude Sonnet 5.5 e Claude Haiku 5.5. Nenhum cabeçalho beta é necessário para mensagens do sistema no meio da conversa. Este recurso não está disponível no Claude Sonnet 5. Nesse caso, use o campo `system` de nível superior.

  As [alterações de ferramentas no meio da conversa](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes) estão em beta nos mesmos modelos. Na Claude API, envie o cabeçalho beta `inline-tools-2026-09-15`, que também abrange [definir uma ferramenta dentro de um bloco `tool_addition`](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta). [Adicionar um servidor "Model Context Protocol", ou MCP, dessa forma](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages#add-an-mcp-server-mid-conversation-beta) requer um segundo cabeçalho beta, `mcp-client-2026-09-15`, que está disponível na Claude API. O cabeçalho `mid-conversation-tool-changes-2026-07-01` funciona para alterações que nomeiam uma ferramenta por referência, na Claude API, no Amazon Bedrock e no Google Cloud.

  As [mensagens de sistema com escopo de turno](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) (`clear_at`) estão em beta e exigem o cabeçalho beta `mid-conversation-system-clear-at-2026-08-21`. Elas estão disponíveis nos mesmos modelos e plataformas que as mensagens de sistema no meio da conversa.
</Note>

## Alterações de ferramentas no meio da conversa

O array `tools` fica ainda mais cedo no prefixo da requisição usado no hash do que o campo `system` de nível superior, então editá-lo invalida o [cache de prompt](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching) da conversa inteira. As alterações de ferramentas no meio da conversa são o equivalente, para ferramentas, das mensagens do sistema no meio da conversa. Em vez de fixar a lista de ferramentas durante toda a vida da conversa, você altera quais ferramentas são oferecidas ao modelo entre os turnos: declare o conjunto completo de ferramentas em `tools` desde o início e, em seguida, use blocos `tool_addition` e `tool_removal` para oferecer uma ferramenta ao modelo, ou retirá-la, a partir de um ponto específico da conversa em diante. O próprio array `tools` nunca muda, então o prefixo em cache permanece intacto. As alterações de ferramentas no meio da conversa estão em beta e usam o cabeçalho beta `inline-tools-2026-09-15` na Claude API.

`tool_addition` e `tool_removal` são blocos de conteúdo no array `content` de uma mensagem `role: "system"`, e podem ser combinados com blocos `text` na mesma mensagem. A mensagem segue as regras de posicionamento de qualquer mensagem do sistema no meio da conversa, com uma restrição extra após um turno pausado (consulte [Limitações](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages#limitations)), e a alteração se aplica daquele ponto da conversa em diante. O campo `tool` de cada bloco referencia uma ferramenta em vez de defini-la: `{"type": "tool_reference", "name": "..."}` nomeia uma ferramenta declarada no array `tools` da requisição, e as ferramentas do [conector MCP](https://platform.claude.com/docs/pt-BR/agents-and-tools/mcp-connector) podem ser referenciadas individualmente com `mcp_tool_reference` (`server_name` e `name`) ou como um conjunto de ferramentas inteiro com `mcp_toolset_reference` (`server_name`). Referenciar um nome que não está declarado em `tools` retorna um erro 400 (na Claude API, com `error.details.error_code` definido como `tool_reference_unresolved`). Um bloco `tool_addition` pode, em vez disso, [conter a definição completa da ferramenta](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta), o que o cabeçalho `mid-conversation-tool-changes-2026-07-01` não suporta.

Toda ferramenta declarada em `tools` é oferecida ao modelo desde o início da conversa, a menos que seja declarada com `defer_loading: true`, o que a mantém retida até que um bloco `tool_addition` a exponha. `tool_addition` também volta a oferecer uma ferramenta que um `tool_removal` anterior retirou.

A requisição a seguir declara `get_weather` em `tools` e, em seguida, a retira após o primeiro turno do usuário com um bloco `tool_removal`. A requisição envia o cabeçalho beta `inline-tools-2026-09-15`.

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: inline-tools-2026-09-15" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "tools": [
        {
          "name": "get_weather",
          "description": "Get the current weather for a location.",
          "input_schema": {
            "type": "object",
            "properties": {
              "location": {"type": "string", "description": "City name"}
            },
            "required": ["location"]
          }
        }
      ],
      "messages": [
        {
          "role": "user",
          "content": "Say OK."
        },
        {
          "role": "system",
          "content": [
            {
              "type": "tool_removal",
              "tool": {"type": "tool_reference", "name": "get_weather"}
            }
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create --beta inline-tools-2026-09-15 \
    --transform 'content.#(type=="text").text' --raw-output <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  tools:
    - name: get_weather
      description: Get the current weather for a location.
      input_schema:
        type: object
        properties:
          location:
            type: string
            description: City name
        required:
          - location
  messages:
    - role: user
      content: Say OK.
    - role: system
      content:
        - type: tool_removal
          tool:
            type: tool_reference
            name: get_weather
  YAML
  ```

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

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      betas=["inline-tools-2026-09-15"],
      # O conjunto completo de ferramentas é declarado de antemão e nunca muda, então o
      # prefixo em cache permanece intacto.
      tools=[
          {
              "name": "get_weather",
              "description": "Get the current weather for a location.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string", "description": "City name"},
                  },
                  "required": ["location"],
              },
          },
      ],
      messages=[
          {
              "role": "user",
              "content": "Say OK.",
          },
          # Retire get_weather a partir deste ponto. O bloco referencia
          # a ferramenta pelo nome em vez de editar `tools`, então os turnos anteriores ficam
          # idênticos byte a byte e o cache continua sendo aproveitado.
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_removal",
                      "tool": {"type": "tool_reference", "name": "get_weather"},
                  },
              ],
          },
      ],
  )

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

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

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    betas: ["inline-tools-2026-09-15"],
    // O conjunto completo de ferramentas é declarado de antemão e nunca muda, então o
    // prefixo em cache permanece intacto.
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: {
              type: "string",
              description: "City name"
            }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "Say OK." },
      // Retire get_weather a partir deste ponto. O bloco referencia a
      // ferramenta pelo nome em vez de editar `tools`, então os turnos anteriores ficam
      // idênticos byte a byte e o cache ainda é aproveitado.
      {
        role: "system",
        content: [
          {
            type: "tool_removal",
            tool: { type: "tool_reference", name: "get_weather" }
          }
        ]
      }
    ]
  });

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

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Betas = [AnthropicBeta.InlineTools2026_09_15],
      // O conjunto completo de ferramentas é declarado de antemão e nunca muda, então o
      // prefixo em cache permanece intacto.
      Tools =
      [
          new BetaTool
          {
              Name = "get_weather",
              Description = "Get the current weather for a location.",
              InputSchema = new InputSchema
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["location"] = JsonSerializer.SerializeToElement(new { type = "string", description = "City name" }),
                  },
                  Required = ["location"],
              },
          },
      ],
      Messages =
      [
          new() { Role = Role.User, Content = "Say OK." },
          // Retira get_weather a partir deste ponto. O bloco referencia
          // a ferramenta pelo nome em vez de editar `Tools`, então os turnos anteriores ficam
          // idênticos byte a byte e o cache continua sendo atingido.
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolRemovalBlock
                  {
                      Tool = new BetaToolChangeToolReference { Name = "get_weather" },
                  },
              ]),
          },
      ],
  });

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

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

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaInlineTools2026_09_15},
  	// O conjunto completo de ferramentas é declarado de antemão e nunca muda, então o
  	// prefixo em cache permanece intacto.
  	Tools: []anthropic.BetaToolUnionParam{
  		{OfTool: &anthropic.BetaToolParam{
  			Name:        "get_weather",
  			Description: anthropic.String("Get the current weather for a location."),
  			InputSchema: anthropic.BetaToolInputSchemaParam{
  				Properties: map[string]any{
  					"location": map[string]any{
  						"type":        "string",
  						"description": "City name",
  					},
  				},
  				Required: []string{"location"},
  			},
  		}},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Say OK.")),
  		// Retira get_weather a partir deste ponto. O bloco referencia
  		// a ferramenta pelo nome em vez de editar Tools, então os turnos anteriores ficam
  		// idênticos byte a byte e o cache continua sendo atingido.
  		{
  			Role: anthropic.BetaMessageParamRoleSystem,
  			Content: []anthropic.BetaContentBlockParamUnion{
  				anthropic.NewBetaToolRemovalBlock(anthropic.BetaToolChangeToolReferenceParam{
  					Name: "get_weather",
  				}),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

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

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaContentBlockParam;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaMessageParam;
  import com.anthropic.models.beta.messages.BetaRequestToolRemovalBlock;
  import com.anthropic.models.beta.messages.BetaTool;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  // ...
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      // O conjunto completo de ferramentas é declarado de antemão e nunca muda, então o
      // prefixo em cache permanece intacto.
      BetaTool weatherTool = BetaTool.builder()
          .name("get_weather")
          .description("Get the current weather for a location.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("location", JsonValue.from(Map.of(
                      "type", "string",
                      "description", "City name")))
                  .build())
              .addRequired("location")
              .build())
          .build();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addBeta(AnthropicBeta.INLINE_TOOLS_2026_09_15)
          .addTool(weatherTool)
          .addUserMessage("Say OK.")
          // Retire get_weather a partir deste ponto. O bloco referencia
          // a ferramenta pelo nome em vez de editar `tools`, então os turnos anteriores ficam
          // idênticos byte a byte e o cache ainda é aproveitado.
          .addMessage(BetaMessageParam.builder()
              .role(BetaMessageParam.Role.SYSTEM)
              .contentOfBetaContentBlockParams(List.of(
                  BetaContentBlockParam.ofToolRemoval(BetaRequestToolRemovalBlock.builder()
                      .referenceTool("get_weather")
                      .build())))
              .build())
          .build();

      BetaMessage response = client.beta().messages().create(params);
      response.content().stream()
          .flatMap(block -> block.text().stream())
          .forEach(textBlock -> IO.println(textBlock.text()));
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  // ...

  $client = new Client();

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      betas: [AnthropicBeta::INLINE_TOOLS_2026_09_15],
      // O conjunto completo de ferramentas é declarado de antemão e nunca muda, então o
      // prefixo em cache permanece intacto.
      tools: [
          [
              'name' => 'get_weather',
              'description' => 'Get the current weather for a location.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'location' => [
                          'type' => 'string',
                          'description' => 'City name',
                      ],
                  ],
                  'required' => ['location'],
              ],
          ],
      ],
      messages: [
          ['role' => 'user', 'content' => 'Say OK.'],
          // Retira get_weather a partir deste ponto. O bloco referencia
          // a ferramenta pelo nome em vez de editar `tools`, então os turnos anteriores ficam
          // idênticos byte a byte e o cache continua sendo atingido.
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_removal',
                      'tool' => ['type' => 'tool_reference', 'name' => 'get_weather'],
                  ],
              ],
          ],
      ],
  );

  foreach ($response->content as $block) {
      if ($block->type === 'text') {
          echo $block->text, PHP_EOL;
      }
  }
  ```

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

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    max_tokens: 1024,
    betas: [Anthropic::AnthropicBeta::INLINE_TOOLS_2026_09_15],
    # O conjunto completo de ferramentas é declarado de antemão e nunca muda, então o
    # prefixo em cache permanece intacto.
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "Say OK." },
      # Retire get_weather a partir deste ponto. O bloco referencia
      # a ferramenta pelo nome em vez de editar `tools`, então os turnos anteriores ficam
      # idênticos byte a byte e o cache continua sendo aproveitado.
      {
        role: "system",
        content: [
          {
            type: "tool_removal",
            tool: { type: "tool_reference", name: "get_weather" }
          }
        ]
      }
    ]
  )

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

### Definir ferramentas em uma mensagem (beta)

Com o cabeçalho beta `inline-tools-2026-09-15`, um bloco `tool_addition` pode definir uma ferramenta por valor, contendo sua definição completa, em vez de nomeá-la por referência. Isso permite introduzir uma ferramenta que é desconhecida no início da conversa, ou cujo schema muda depois, acrescentando uma mensagem `role: "system"`. O array `tools` e todas as mensagens anteriores permanecem exatamente como foram enviados, então o cache de prompt continua sendo atingido e apenas a mensagem acrescentada é processada como nova entrada. A única exceção, um array `tools` sem nenhuma ferramenta não adiada, é tratada nas regras abaixo. O cabeçalho também cobre a adição e a remoção de ferramentas por referência, então você não precisa enviar também `mid-conversation-tool-changes-2026-07-01`.

Envolva a definição em um objeto `tool` do tipo `tool_definition`. A `definition` é uma entrada de `tools`, como uma ferramenta personalizada ou uma ferramenta de cliente ou de servidor definida pela Anthropic, com sua configuração habitual, incluindo `cache_control` e `defer_loading`. Durante o beta, alguns tipos de ferramenta (entre eles a ferramenta de uso do computador) ainda não podem ser definidos em uma mensagem e retornam um erro 400 informando isso; declare-os em `tools` e adicione-os por referência. Por exemplo, para definir uma ferramenta personalizada no meio da conversa:

```json
{
  "role": "system",
  "content": [
    {
      "type": "tool_addition",
      "tool": {
        "type": "tool_definition",
        "definition": {
          "name": "db_query",
          "description": "Run a read-only SQL query against the analytics database.",
          "input_schema": {
            "type": "object",
            "properties": { "sql": { "type": "string" } },
            "required": ["sql"]
          }
        }
      }
    }
  ]
}
```

Dessa posição em diante, o modelo pode chamar a ferramenta da mesma forma que chama uma ferramenta declarada em `tools`. Enviar novamente uma definição idêntica não altera nada, então um cliente pode reenviá-la com segurança, por exemplo em uma nova tentativa.

A requisição a seguir mantém `get_weather` em `tools` e define `db_query` após o primeiro turno do usuário:

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: inline-tools-2026-09-15" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "tools": [
        {
          "name": "get_weather",
          "description": "Get the current weather for a location.",
          "input_schema": {
            "type": "object",
            "properties": {
              "location": {"type": "string", "description": "City name"}
            },
            "required": ["location"]
          }
        }
      ],
      "messages": [
        {
          "role": "user",
          "content": "How many orders shipped yesterday?"
        },
        {
          "role": "system",
          "content": [
            {
              "type": "tool_addition",
              "tool": {
                "type": "tool_definition",
                "definition": {
                  "name": "db_query",
                  "description": "Run a read-only SQL query against the analytics database.",
                  "input_schema": {
                    "type": "object",
                    "properties": {"sql": {"type": "string"}},
                    "required": ["sql"]
                  }
                }
              }
            }
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create --beta inline-tools-2026-09-15 <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  # Mantenha ao menos uma ferramenta não adiada em `tools`, para que uma ferramenta definida
  # depois não altere o início do prompt renderizado.
  tools:
    - name: get_weather
      description: Get the current weather for a location.
      input_schema:
        type: object
        properties:
          location:
            type: string
            description: City name
        required:
          - location
  messages:
    - role: user
      content: How many orders shipped yesterday?
    # Defina db_query por valor a partir daqui. `tools` e as
    # mensagens anteriores ficam exatamente como enviadas, então o cache ainda é atingido.
    - role: system
      content:
        - type: tool_addition
          tool:
            type: tool_definition
            definition:
              name: db_query
              description: Run a read-only SQL query against the analytics database.
              input_schema:
                type: object
                properties:
                  sql:
                    type: string
                required:
                  - sql
  YAML
  ```

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

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      betas=["inline-tools-2026-09-15"],
      # Mantenha pelo menos uma ferramenta não adiada em `tools`, para que uma ferramenta definida
      # depois não altere o início do prompt renderizado.
      tools=[
          {
              "name": "get_weather",
              "description": "Get the current weather for a location.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string", "description": "City name"},
                  },
                  "required": ["location"],
              },
          },
      ],
      messages=[
          {"role": "user", "content": "How many orders shipped yesterday?"},
          # Defina db_query por valor a partir daqui. `tools` e as
          # mensagens anteriores ficam exatamente como enviadas, então o cache ainda é atingido.
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_addition",
                      "tool": {
                          "type": "tool_definition",
                          "definition": {
                              "name": "db_query",
                              "description": "Run a read-only SQL query against the analytics database.",
                              "input_schema": {
                                  "type": "object",
                                  "properties": {"sql": {"type": "string"}},
                                  "required": ["sql"],
                              },
                          },
                      },
                  },
              ],
          },
      ],
  )

  for block in response.content:
      if block.type == "tool_use":
          print(block.name, block.input)
  ```

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

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    betas: ["inline-tools-2026-09-15"],
    // Mantenha pelo menos uma ferramenta não adiada em `tools`, para que uma ferramenta definida
    // depois não altere o início do prompt renderizado.
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "How many orders shipped yesterday?" },
      // Defina db_query por valor a partir daqui. `tools` e as
      // mensagens anteriores ficam exatamente como enviadas, então o cache ainda é atingido.
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: {
                name: "db_query",
                description: "Run a read-only SQL query against the analytics database.",
                input_schema: {
                  type: "object",
                  properties: { sql: { type: "string" } },
                  required: ["sql"]
                }
              }
            }
          }
        ]
      }
    ]
  });

  for (const block of response.content) {
    if (block.type === "tool_use") {
      console.log(block.name, JSON.stringify(block.input));
    }
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Betas = [AnthropicBeta.InlineTools2026_09_15],
      // Mantenha pelo menos uma ferramenta não adiada em `Tools`, para que uma ferramenta definida
      // depois não altere o início do prompt renderizado.
      Tools =
      [
          new BetaTool
          {
              Name = "get_weather",
              Description = "Get the current weather for a location.",
              InputSchema = new InputSchema
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["location"] = JsonSerializer.SerializeToElement(new { type = "string", description = "City name" }),
                  },
                  Required = ["location"],
              },
          },
      ],
      Messages =
      [
          new() { Role = Role.User, Content = "How many orders shipped yesterday?" },
          // Defina db_query por valor a partir deste ponto. `Tools` e as
          // mensagens anteriores permanecem exatamente como enviadas, então o cache ainda é atingido.
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolAdditionBlock
                  {
                      Tool = new BetaToolChangeToolDefinitionParam
                      {
                          Definition = new BetaTool
                          {
                              Name = "db_query",
                              Description = "Run a read-only SQL query against the analytics database.",
                              InputSchema = new InputSchema
                              {
                                  Properties = new Dictionary<string, JsonElement>
                                  {
                                      ["sql"] = JsonSerializer.SerializeToElement(new { type = "string" }),
                                  },
                                  Required = ["sql"],
                              },
                          },
                      },
                  },
              ]),
          },
      ],
  });

  foreach (var block in response.Content)
  {
      if (block.TryPickToolUse(out var toolUse))
      {
          Console.WriteLine($"{toolUse.Name} {JsonSerializer.Serialize(toolUse.Input)}");
      }
  }
  ```

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

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaInlineTools2026_09_15},
  	// Mantenha ao menos uma ferramenta não adiada em Tools, para que uma ferramenta definida
  	// depois não altere o início do prompt renderizado.
  	Tools: []anthropic.BetaToolUnionParam{
  		{OfTool: &anthropic.BetaToolParam{
  			Name:        "get_weather",
  			Description: anthropic.String("Get the current weather for a location."),
  			InputSchema: anthropic.BetaToolInputSchemaParam{
  				Properties: map[string]any{
  					"location": map[string]any{
  						"type":        "string",
  						"description": "City name",
  					},
  				},
  				Required: []string{"location"},
  			},
  		}},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("How many orders shipped yesterday?")),
  		// Defina db_query por valor a partir daqui. Tools e as
  		// mensagens anteriores ficam exatamente como enviadas, então o cache ainda é atingido.
  		{
  			Role: anthropic.BetaMessageParamRoleSystem,
  			Content: []anthropic.BetaContentBlockParamUnion{
  				anthropic.NewBetaToolAdditionBlock(anthropic.BetaToolChangeToolDefinitionParam{
  					Definition: anthropic.BetaToolUnionParam{OfTool: &anthropic.BetaToolParam{
  						Name:        "db_query",
  						Description: anthropic.String("Run a read-only SQL query against the analytics database."),
  						InputSchema: anthropic.BetaToolInputSchemaParam{
  							Properties: map[string]any{
  								"sql": map[string]any{"type": "string"},
  							},
  							Required: []string{"sql"},
  						},
  					}},
  				}),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  for _, block := range response.Content {
  	if toolUse, ok := block.AsAny().(anthropic.BetaToolUseBlock); ok {
  		fmt.Println(toolUse.Name, toolUse.Input)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaContentBlockParam;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaRequestToolAdditionBlock;
  import com.anthropic.models.beta.messages.BetaTool;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  // ...

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

      BetaTool weatherTool = BetaTool.builder()
          .name("get_weather")
          .description("Get the current weather for a location.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("location", JsonValue.from(Map.of(
                      "type", "string",
                      "description", "City name")))
                  .build())
              .addRequired("location")
              .build())
          .build();

      BetaTool dbQueryTool = BetaTool.builder()
          .name("db_query")
          .description("Run a read-only SQL query against the analytics database.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("sql", JsonValue.from(Map.of("type", "string")))
                  .build())
              .addRequired("sql")
              .build())
          .build();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addBeta(AnthropicBeta.INLINE_TOOLS_2026_09_15)
          // Mantenha pelo menos uma ferramenta não adiada em `tools`, para que uma ferramenta definida
          // depois não altere o início do prompt renderizado.
          .addTool(weatherTool)
          .addUserMessage("How many orders shipped yesterday?")
          // Defina db_query por valor a partir daqui. `tools` e as
          // mensagens anteriores ficam exatamente como enviadas, então o cache ainda é atingido.
          .addSystemMessageOfBetaContentBlockParams(List.of(
              BetaContentBlockParam.ofToolAddition(BetaRequestToolAdditionBlock.builder()
                  .definitionTool(dbQueryTool)
                  .build())))
          .build();

      BetaMessage response = client.beta().messages().create(params);
      response.content().stream()
          .flatMap(block -> block.toolUse().stream())
          .forEach(toolUse -> IO.println(toolUse.name() + " " + toolUse._input()));
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaToolUseBlock;
  // ...

  $client = new Client();

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      betas: [AnthropicBeta::INLINE_TOOLS_2026_09_15],
      // Mantenha pelo menos uma ferramenta não adiada em `tools`, para que uma ferramenta definida
      // depois não altere o início do prompt renderizado.
      tools: [
          [
              'name' => 'get_weather',
              'description' => 'Get the current weather for a location.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'location' => [
                          'type' => 'string',
                          'description' => 'City name',
                      ],
                  ],
                  'required' => ['location'],
              ],
          ],
      ],
      messages: [
          ['role' => 'user', 'content' => 'How many orders shipped yesterday?'],
          // Defina db_query por valor a partir deste ponto. `tools` e as
          // mensagens anteriores ficam exatamente como enviadas, então o cache ainda é aproveitado.
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_addition',
                      'tool' => [
                          'type' => 'tool_definition',
                          'definition' => [
                              'name' => 'db_query',
                              'description' => 'Run a read-only SQL query against the analytics database.',
                              'input_schema' => [
                                  'type' => 'object',
                                  'properties' => ['sql' => ['type' => 'string']],
                                  'required' => ['sql'],
                              ],
                          ],
                      ],
                  ],
              ],
          ],
      ],
  );

  foreach ($response->content as $block) {
      if ($block instanceof BetaToolUseBlock) {
          echo $block->name, ' ', json_encode($block->input), PHP_EOL;
      }
  }
  ```

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

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    max_tokens: 1024,
    betas: [Anthropic::AnthropicBeta::INLINE_TOOLS_2026_09_15],
    # Mantenha ao menos uma ferramenta não adiada em `tools`, para que uma ferramenta definida
    # depois não altere o início do prompt renderizado.
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "How many orders shipped yesterday?" },
      # Defina db_query por valor a partir daqui. `tools` e as
      # mensagens anteriores ficam exatamente como enviadas, então o cache ainda é atingido.
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: {
                name: "db_query",
                description: "Run a read-only SQL query against the analytics database.",
                input_schema: {
                  type: "object",
                  properties: { sql: { type: "string" } },
                  required: ["sql"]
                }
              }
            }
          }
        ]
      }
    ]
  )

  response.content.each do |block|
    puts "#{block.name} #{block.input}" if block.is_a?(Anthropic::Beta::BetaToolUseBlock)
  end
  ```
</CodeGroup>

O `content` da resposta inclui um bloco `tool_use` para a nova ferramenta, por exemplo:

```json
{
  "type": "tool_use",
  "id": "toolu_01A09q90qw90lq917835lq9",
  "name": "db_query",
  "input": {
    "sql": "SELECT COUNT(*) FROM orders WHERE shipped_at::date = CURRENT_DATE - 1"
  }
}
```

Para alterar o schema de uma ferramenta, ou para mover uma ferramenta de servidor para uma versão mais recente, envie uma definição diferente com o mesmo nome. A nova definição substitui a anterior dessa posição em diante. Uma definição que reutiliza o nome de um tipo diferente de ferramenta retorna um erro 400 com `error.details.error_code` definido como `tool_name_conflict`. Uma versão mais recente da mesma ferramenta não conta como um tipo diferente. `tool_removal` continua recebendo uma referência, e uma ferramenta removida pode ser definida ou oferecida novamente mais tarde.

Algumas regras decorrem de onde a definição é renderizada:

* **Declare desde o início o que você já sabe.** Uma ferramenta que você conhece na primeira requisição pertence a `tools`, com `defer_loading: true` e uma referência `tool_addition` posterior se o modelo ainda não deve vê-la. Defina por valor apenas o que é desconhecido na primeira requisição ou muda depois.
* **Mantenha pelo menos uma ferramenta não adiada em `tools`.** Uma conversa cujo array `tools` não tem nenhuma ferramenta não adiada é aceita, mas a primeira ferramenta que ela define por valor altera o início do prompt renderizado, o que custa uma falha completa de cache nessa requisição. Uma [ferramenta de busca de ferramentas](https://platform.claude.com/docs/pt-BR/agents-and-tools/tool-use/tool-search-tool) conta como não adiada.
* **Tipos de ferramenta com data mantêm seus próprios cabeçalhos beta.** Se uma ferramenta de servidor que você define por valor exige seu próprio cabeçalho beta, envie esse cabeçalho em todas as requisições posteriores da conversa.
* **`cache_control` vai no bloco ou na definição, não em ambos,** e conta para o limite de pontos de interrupção da requisição. Uma definição adiada não pode conter `cache_control`.

Uma requisição retorna um erro 400 com `error.details.error_code` definido como `available_tools_limit_exceeded` quando qualquer um destes limites é excedido:

* Mais de 10.000 ferramentas adiadas estão disponíveis após qualquer mensagem.
* Mais de 10.000 ferramentas definidas após a primeira mensagem do usuário estão disponíveis após qualquer mensagem.
* As definições de ferramentas enviadas após a primeira mensagem do usuário que ainda estão disponíveis após qualquer mensagem totalizam mais de 4 MB (4.194.304 bytes).
* O texto renderizado das ferramentas é maior que 4 MB (4.194.304 bytes).

### Adicionar um servidor MCP no meio da conversa (beta)

Para adicionar um servidor do [conector MCP](https://platform.claude.com/docs/pt-BR/agents-and-tools/mcp-connector) no meio de uma conversa, envie o cabeçalho beta `mcp-client-2026-09-15` junto com `inline-tools-2026-09-15`. A `definition` em um bloco `tool_addition` pode então ser um `mcp_toolset`, de modo que as ferramentas do servidor ficam disponíveis sem editar `tools`. Liste os detalhes de conexão do servidor em `mcp_servers` como de costume e, em seguida, acrescente o conjunto de ferramentas no ponto em que o servidor ficou disponível:

```json
{
  "role": "system",
  "content": [
    {
      "type": "tool_addition",
      "tool": {
        "type": "tool_definition",
        "definition": { "type": "mcp_toolset", "mcp_server_name": "calendar" }
      }
    }
  ]
}
```

O objeto `mcp_toolset` é o mesmo que você colocaria em `tools`, incluindo `default_config` e `configs`. Um bloco `tool_addition` nunca contém uma URL ou um token de servidor. Esses ficam em `mcp_servers`.

A requisição a seguir mantém `get_weather` em `tools`, lista o servidor de calendário em `mcp_servers` e adiciona o conjunto de ferramentas do servidor após o primeiro turno do usuário:

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: inline-tools-2026-09-15,mcp-client-2026-09-15" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "mcp_servers": [
        {
          "type": "url",
          "url": "https://mcp.example.com/calendar",
          "name": "calendar",
          "authorization_token": "YOUR_TOKEN"
        }
      ],
      "tools": [
        {
          "name": "get_weather",
          "description": "Get the current weather for a location.",
          "input_schema": {
            "type": "object",
            "properties": {
              "location": {"type": "string", "description": "City name"}
            },
            "required": ["location"]
          }
        }
      ],
      "messages": [
        {
          "role": "user",
          "content": "What'\''s on my calendar tomorrow?"
        },
        {
          "role": "system",
          "content": [
            {
              "type": "tool_addition",
              "tool": {
                "type": "tool_definition",
                "definition": {
                  "type": "mcp_toolset",
                  "mcp_server_name": "calendar"
                }
              }
            }
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create \
    --beta inline-tools-2026-09-15,mcp-client-2026-09-15 <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  mcp_servers:
    - type: url
      url: https://mcp.example.com/calendar
      name: calendar
      authorization_token: YOUR_TOKEN
  tools:
    - name: get_weather
      description: Get the current weather for a location.
      input_schema:
        type: object
        properties:
          location:
            type: string
            description: City name
        required:
          - location
  messages:
    - role: user
      content: What's on my calendar tomorrow?
    # Disponibiliza as ferramentas do servidor de calendário a partir deste ponto.
    # O bloco nomeia o servidor; ele nunca contém uma URL ou token.
    - role: system
      content:
        - type: tool_addition
          tool:
            type: tool_definition
            definition:
              type: mcp_toolset
              mcp_server_name: calendar
  YAML
  ```

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

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      betas=["inline-tools-2026-09-15", "mcp-client-2026-09-15"],
      mcp_servers=[
          {
              "type": "url",
              "url": "https://mcp.example.com/calendar",
              "name": "calendar",
              "authorization_token": "YOUR_TOKEN",
          },
      ],
      tools=[
          {
              "name": "get_weather",
              "description": "Get the current weather for a location.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string", "description": "City name"},
                  },
                  "required": ["location"],
              },
          },
      ],
      messages=[
          {"role": "user", "content": "What's on my calendar tomorrow?"},
          # Disponibiliza as ferramentas do servidor de calendário a partir deste ponto.
          # O bloco nomeia o servidor; ele nunca contém uma URL ou token.
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_addition",
                      "tool": {
                          "type": "tool_definition",
                          "definition": {
                              "type": "mcp_toolset",
                              "mcp_server_name": "calendar",
                          },
                      },
                  },
              ],
          },
      ],
  )

  # A resposta começa com um bloco mcp_tool_listing para o servidor de calendário,
  # então verifique o tipo de cada bloco em vez de ler content[0].
  for block in response.content:
      match block.type:
          case "mcp_tool_listing":
              print(block.mcp_server_name, [tool.name for tool in block.tools])
          case "text":
              print(block.text)
  ```

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

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    betas: ["inline-tools-2026-09-15", "mcp-client-2026-09-15"],
    mcp_servers: [
      {
        type: "url",
        url: "https://mcp.example.com/calendar",
        name: "calendar",
        authorization_token: "YOUR_TOKEN"
      }
    ],
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "What's on my calendar tomorrow?" },
      // Disponibiliza as ferramentas do servidor de calendário a partir deste ponto.
      // O bloco nomeia o servidor; ele nunca contém uma URL ou token.
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: { type: "mcp_toolset", mcp_server_name: "calendar" }
            }
          }
        ]
      }
    ]
  });

  // A resposta começa com um bloco mcp_tool_listing para o servidor de calendário,
  // então verifique o tipo de cada bloco em vez de ler content[0].
  for (const block of response.content) {
    switch (block.type) {
      case "mcp_tool_listing":
        console.log(
          block.mcp_server_name,
          block.tools.map((tool) => tool.name)
        );
        break;
      case "text":
        console.log(block.text);
        break;
    }
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Betas = [AnthropicBeta.InlineTools2026_09_15, AnthropicBeta.McpClient2026_09_15],
      McpServers =
      [
          new BetaRequestMcpServerUrlDefinition
          {
              Url = "https://mcp.example.com/calendar",
              Name = "calendar",
              AuthorizationToken = "YOUR_TOKEN",
          },
      ],
      Tools =
      [
          new BetaTool
          {
              Name = "get_weather",
              Description = "Get the current weather for a location.",
              InputSchema = new InputSchema
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["location"] = JsonSerializer.SerializeToElement(new { type = "string", description = "City name" }),
                  },
                  Required = ["location"],
              },
          },
      ],
      Messages =
      [
          new() { Role = Role.User, Content = "What's on my calendar tomorrow?" },
          // Disponibiliza as ferramentas do servidor de calendário a partir deste ponto.
          // O bloco nomeia o servidor; ele nunca contém uma URL ou token.
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolAdditionBlock
                  {
                      Tool = new BetaToolChangeToolDefinitionParam
                      {
                          Definition = new BetaMcpToolset("calendar"),
                      },
                  },
              ]),
          },
      ],
  });

  // A resposta começa com um bloco mcp_tool_listing para o servidor de calendário,
  // então verifique o tipo de cada bloco em vez de ler Content[0].
  foreach (var block in response.Content)
  {
      if (block.TryPickMcpToolListing(out var listing))
      {
          Console.WriteLine($"{listing.McpServerName} {JsonSerializer.Serialize(listing.Tools.Select(tool => tool.Name))}");
      }
      else if (block.TryPickText(out var text))
      {
          Console.WriteLine(text.Text);
      }
  }
  ```

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

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Betas: []anthropic.AnthropicBeta{
  		anthropic.AnthropicBetaInlineTools2026_09_15,
  		anthropic.AnthropicBetaMCPClient2026_09_15,
  	},
  	MCPServers: []anthropic.BetaRequestMCPServerURLDefinitionParam{
  		{
  			URL:                "https://mcp.example.com/calendar",
  			Name:               "calendar",
  			AuthorizationToken: anthropic.String("YOUR_TOKEN"),
  		},
  	},
  	Tools: []anthropic.BetaToolUnionParam{
  		{OfTool: &anthropic.BetaToolParam{
  			Name:        "get_weather",
  			Description: anthropic.String("Get the current weather for a location."),
  			InputSchema: anthropic.BetaToolInputSchemaParam{
  				Properties: map[string]any{
  					"location": map[string]any{
  						"type":        "string",
  						"description": "City name",
  					},
  				},
  				Required: []string{"location"},
  			},
  		}},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What's on my calendar tomorrow?")),
  		// Disponibiliza as ferramentas do servidor de calendário a partir deste ponto.
  		// O bloco nomeia o servidor; ele nunca contém uma URL ou token.
  		{
  			Role: anthropic.BetaMessageParamRoleSystem,
  			Content: []anthropic.BetaContentBlockParamUnion{
  				anthropic.NewBetaToolAdditionBlock(anthropic.BetaToolChangeToolDefinitionParam{
  					Definition: anthropic.BetaToolUnionParam{OfMCPToolset: &anthropic.BetaMCPToolsetParam{
  						MCPServerName: "calendar",
  					}},
  				}),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  // A resposta começa com um bloco mcp_tool_listing para o servidor de calendário,
  // então verifique o tipo de cada bloco em vez de ler Content[0].
  for _, block := range response.Content {
  	switch variant := block.AsAny().(type) {
  	case anthropic.BetaMCPToolListingBlock:
  		var toolNames []string
  		for _, tool := range variant.Tools {
  			toolNames = append(toolNames, tool.Name)
  		}
  		fmt.Println(variant.MCPServerName, toolNames)
  	case anthropic.BetaTextBlock:
  		fmt.Println(variant.Text)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaContentBlockParam;
  import com.anthropic.models.beta.messages.BetaMcpTool;
  import com.anthropic.models.beta.messages.BetaMcpToolset;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaRequestMcpServerUrlDefinition;
  import com.anthropic.models.beta.messages.BetaRequestToolAdditionBlock;
  import com.anthropic.models.beta.messages.BetaTool;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  // ...

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

      BetaTool weatherTool = BetaTool.builder()
          .name("get_weather")
          .description("Get the current weather for a location.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("location", JsonValue.from(Map.of(
                      "type", "string",
                      "description", "City name")))
                  .build())
              .addRequired("location")
              .build())
          .build();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addBeta(AnthropicBeta.INLINE_TOOLS_2026_09_15)
          .addBeta(AnthropicBeta.MCP_CLIENT_2026_09_15)
          .addMcpServer(BetaRequestMcpServerUrlDefinition.builder()
              .url("https://mcp.example.com/calendar")
              .name("calendar")
              .authorizationToken("YOUR_TOKEN")
              .build())
          .addTool(weatherTool)
          .addUserMessage("What's on my calendar tomorrow?")
          // Disponibiliza as ferramentas do servidor de calendário a partir deste ponto.
          // O bloco nomeia o servidor; ele nunca contém uma URL ou token.
          .addSystemMessageOfBetaContentBlockParams(List.of(
              BetaContentBlockParam.ofToolAddition(BetaRequestToolAdditionBlock.builder()
                  .definitionTool(BetaMcpToolset.builder()
                      .mcpServerName("calendar")
                      .build())
                  .build())))
          .build();

      BetaMessage response = client.beta().messages().create(params);

      // A resposta começa com um bloco mcp_tool_listing para o servidor de calendário,
      // então verifique o tipo de cada bloco em vez de ler o primeiro bloco.
      for (var block : response.content()) {
          switch (block.type().value()) {
              case MCP_TOOL_LISTING -> {
                  var listing = block.asMcpToolListing();
                  var toolNames = listing.tools().stream().map(BetaMcpTool::name).toList();
                  IO.println(listing.mcpServerName() + " " + toolNames);
              }
              case TEXT -> IO.println(block.asText().text());
          }
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaMCPTool;
  use Anthropic\Beta\Messages\BetaMCPToolListingBlock;
  use Anthropic\Beta\Messages\BetaTextBlock;
  // ...

  $client = new Client();

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      betas: [
          AnthropicBeta::INLINE_TOOLS_2026_09_15,
          AnthropicBeta::MCP_CLIENT_2026_09_15,
      ],
      mcpServers: [
          [
              'type' => 'url',
              'url' => 'https://mcp.example.com/calendar',
              'name' => 'calendar',
              'authorization_token' => 'YOUR_TOKEN',
          ],
      ],
      tools: [
          [
              'name' => 'get_weather',
              'description' => 'Get the current weather for a location.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'location' => [
                          'type' => 'string',
                          'description' => 'City name',
                      ],
                  ],
                  'required' => ['location'],
              ],
          ],
      ],
      messages: [
          ['role' => 'user', 'content' => "What's on my calendar tomorrow?"],
          // Disponibiliza as ferramentas do servidor de calendário a partir deste ponto.
          // O bloco nomeia o servidor; ele nunca contém uma URL ou token.
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_addition',
                      'tool' => [
                          'type' => 'tool_definition',
                          'definition' => [
                              'type' => 'mcp_toolset',
                              'mcp_server_name' => 'calendar',
                          ],
                      ],
                  ],
              ],
          ],
      ],
  );

  // A resposta começa com um bloco mcp_tool_listing para o servidor de calendário,
  // então verifique o tipo de cada bloco em vez de ler content[0].
  foreach ($response->content as $block) {
      switch (true) {
          case $block instanceof BetaMCPToolListingBlock:
              $toolNames = array_map(fn (BetaMCPTool $tool) => $tool->name, $block->tools);
              echo $block->mcpServerName, ' ', json_encode($toolNames), PHP_EOL;
              break;
          case $block instanceof BetaTextBlock:
              echo $block->text, PHP_EOL;
              break;
      }
  }
  ```

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

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    max_tokens: 1024,
    betas: [
      Anthropic::AnthropicBeta::INLINE_TOOLS_2026_09_15,
      Anthropic::AnthropicBeta::MCP_CLIENT_2026_09_15
    ],
    mcp_servers: [
      {
        type: "url",
        url: "https://mcp.example.com/calendar",
        name: "calendar",
        authorization_token: "YOUR_TOKEN"
      }
    ],
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "What's on my calendar tomorrow?" },
      # Disponibiliza as ferramentas do servidor de calendário a partir deste ponto.
      # O bloco nomeia o servidor; ele nunca contém uma URL ou token.
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: { type: "mcp_toolset", mcp_server_name: "calendar" }
            }
          }
        ]
      }
    ]
  )

  # A resposta começa com um bloco mcp_tool_listing para o servidor de calendário,
  # então verifique o tipo de cada bloco em vez de ler content[0].
  response.content.each do |block|
    case block
    when Anthropic::Beta::BetaMCPToolListingBlock
      puts "#{block.mcp_server_name} #{block.tools.map(&:name)}"
    when Anthropic::Beta::BetaTextBlock
      puts block.text
    end
  end
  ```
</CodeGroup>

Com `mcp-client-2026-09-15`, uma resposta para a qual a API buscou a lista de ferramentas de um servidor começa com um bloco `mcp_tool_listing`, um para cada servidor buscado. Se o seu código lê `content[0]`, ignore esses blocos. Envie a mensagem do assistente de volta sem alterações, incluindo esse bloco, e continue enviando `mcp-client-2026-09-15` em todas as requisições que o contêm. As requisições posteriores passam então a usar a lista registrada em vez de consultar o servidor novamente. Para fixar um conjunto de ferramentas você mesmo, copie essa lista para o campo `tools` do `mcp_toolset`, conforme descrito em [Fixar a lista de ferramentas de um servidor MCP](https://platform.claude.com/docs/pt-BR/agents-and-tools/mcp-connector#pin-mcp-tool-list).

`mcp-client-2026-09-15` inclui tudo o que `mcp-client-2025-11-20` inclui, então você não precisa enviar ambos. Esses recursos estão disponíveis na Claude API. As requisições que usam o conector MCP mantêm os termos de [retenção de dados](https://platform.claude.com/docs/pt-BR/agents-and-tools/mcp-connector#data-retention) do conector.

## Quando usar uma mensagem de sistema no meio da conversa

O [cache de prompt](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching) calcula o hash do prefixo da requisição em ordem: `tools`, depois `system`, depois `messages`. Um acerto de cache exige que o prefixo corresponda exatamente a uma requisição recente, byte a byte, até o ponto de interrupção do cache.

Essa ordenação significa que o campo `system` de nível superior fica perto do início do prefixo com hash. Qualquer alteração nele, mesmo anexar uma frase, produz um hash diferente, e a requisição perde o cache do prompt do sistema e de todas as mensagens em cache depois dele.

As mensagens de sistema no meio da conversa permitem que você adicione a instrução no **final** do histórico de mensagens. Tudo antes da nova instrução permanece inalterado, então a entrada de cache existente ainda corresponde, e apenas a nova mensagem é processada como entrada nova.

Algumas situações em que isso importa:

* **Mudanças de política ou persona no meio da sessão.** Uma longa sessão agêntica precisa de uma nova restrição ("de agora em diante, escreva todo SQL como consultas parametrizadas") após dezenas de turnos em cache. Adicioná-la ao campo `system` de nível superior reprocessaria todo o histórico.
* **Contexto por turno que precisa ser autoritativo.** Você quer injetar uma nota de atualidade, um prazo de sessão ou uma mudança de disponibilidade de ferramentas com peso de nível de sistema, e isso muda com frequência demais para ficar no prefixo em cache.
* **Lembretes por turno que não devem se acumular.** Um harness dá um toque no modelo após cada lote de resultados de ferramentas ("solicite leituras independentes juntas", "o usuário não recebe notícias suas há algum tempo") e quer que o modelo veja apenas a cópia mais recente. Uma [mensagem de sistema com escopo de turno](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) é renderizada por um turno e depois não custa nada, sem excluir nada do histórico.
* **Mudanças de estado que sua aplicação observa.** Sua aplicação percebe algo que Claude deve tratar como um fato de nível de operador: arquivos mudaram no disco, o usuário alternou uma configuração de aprovação automática, as ferramentas disponíveis mudaram ou o orçamento de tokens restante caiu abaixo de um limite.
* **Entrada do usuário que não deve interromper um loop agêntico.** Um usuário digita uma mensagem de acompanhamento enquanto Claude ainda está executando ferramentas para a requisição anterior. Repassá-la como uma mensagem do sistema após o próximo resultado de ferramenta permite que Claude incorpore a nova entrada ao trabalho que já está fazendo, em vez de tratá-la como uma nova requisição para a qual mudar. No Claude Sonnet 5.5 e no Claude Haiku 5.5, em vez disso, anexe as palavras do usuário como um bloco `text` após o último `tool_result` na mesma mensagem `user`. Consulte [Posicionamento após resultados de ferramentas](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages#placement-after-tool-results).
* **Mudanças de modo que concedem permissões permanentes.** Um modo de nível de sessão pode usar uma mensagem de sistema no meio da conversa para conceder consentimento permanente a uma capacidade cara, como iniciar automaticamente fluxos de trabalho multiagente, com um breve lembrete a cada vários turnos e um aviso de saída quando o modo é desativado. Para um exemplo completo, consulte [Construir um modo de orquestração](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-effort-example).

Em todos esses casos, você poderia colocar a instrução em uma mensagem `user` comum, e Claude segue instruções que chegam em turnos de usuário. A diferença é a prioridade: uma mensagem `user` é tratada como vinda do usuário final, enquanto uma mensagem `system` é tratada como vinda de você, o operador da aplicação. Quando as duas entram em conflito, as instruções de sistema têm precedência, então use o papel `system` para fatos e restrições de nível de operador que devem valer mesmo que o usuário final peça algo diferente. Uma mensagem de sistema no meio da conversa mantém essa prioridade de nível de operador sem pagar o custo de perda de cache de editar o campo `system` de nível superior.

## Como funciona

Adicione uma mensagem com `"role": "system"` ao array `messages`. Use uma string simples ou blocos de conteúdo para `content`, da mesma forma que em um turno `user` ou `assistant`. A instrução se aplica daquele ponto da conversa em diante. Quando as instruções entram em conflito, mensagens de sistema posteriores têm precedência sobre as anteriores, e as mensagens de sistema no meio da conversa têm precedência sobre o campo `system` de nível superior nos turnos que as seguem.

Você ainda pode definir o campo `system` de nível superior para instruções que devem se aplicar à conversa inteira. Reserve as mensagens de sistema no meio da conversa para instruções que só se tornam relevantes mais tarde, ou que você quer adicionar sem invalidar o prefixo em cache.

Uma mensagem `role: "system"` também pode conter `output_config.effort` para alterar o nível de [esforço](https://platform.claude.com/docs/pt-BR/build-with-claude/effort) no meio de uma conversa. Isso está em beta no Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5.5 e Claude Haiku 5.5 na Claude API e no Google Cloud, e exige o cabeçalho beta `mid-conversation-output-config-2026-07-01`. No Amazon Bedrock, está em beta no Claude Fable 5.1, Claude Mythos 5.1 e Claude Opus 5.5, com o mesmo valor beta. O Claude Opus 5 não oferece suporte a isso no Amazon Bedrock. Consulte [Esforço por mensagem](https://platform.claude.com/docs/pt-BR/build-with-claude/effort#change-effort-mid-conversation-beta).

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "cache_control": {"type": "ephemeral"},
      "system": "You are a code review assistant. Be concise.",
      "messages": [
        {
          "role": "user",
          "content": "Review process() in utils.py for performance issues."
        },
        {
          "role": "assistant",
          "content": "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list."
        },
        {
          "role": "user",
          "content": "Now review the calling code that invokes process()."
        },
        {
          "role": "system",
          "content": "From now on, every suggestion must include explicit type annotations."
        }
      ]
    }'
  ```

  ```bash CLI
  ant messages create --transform 'content.#(type=="text").text' --raw-output <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  cache_control:
    type: ephemeral
  system: You are a code review assistant. Be concise.
  messages:
    - role: user
      content: Review process() in utils.py for performance issues.
    - role: assistant
      content: >-
        The list comprehension is fine for small inputs. For large inputs,
        consider a generator to avoid materializing the full list.
    - role: user
      content: Now review the calling code that invokes process().
    - role: system
      content: From now on, every suggestion must include explicit type annotations.
  YAML
  ```

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

  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      # Cache de prompt automático: cada requisição armazena em cache a conversa até aqui,
      # e a próxima requisição lê do cache o prefixo inalterado.
      cache_control={"type": "ephemeral"},
      system="You are a code review assistant. Be concise.",
      messages=[
          {
              "role": "user",
              "content": "Review process() in utils.py for performance issues.",
          },
          {
              "role": "assistant",
              "content": "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.",
          },
          {
              "role": "user",
              "content": "Now review the calling code that invokes process().",
          },
          # O revisor percebe no meio da sessão que todas as sugestões também
          # precisam passar pela política de tipagem estrita da equipe. Anexar a
          # instrução aqui mantém os turnos anteriores idênticos byte a byte, então o
          # prefixo armazenado em cache pela requisição anterior ainda é lido do cache.
          {
              "role": "system",
              "content": "From now on, every suggestion must include explicit type annotations.",
          },
      ],
  )

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

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

  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    // Cache de prompt automático ("prompt caching"): cada requisição armazena em cache a conversa até aqui,
    // e a próxima requisição lê do cache o prefixo inalterado.
    cache_control: { type: "ephemeral" },
    system: "You are a code review assistant. Be concise.",
    messages: [
      {
        role: "user",
        content: "Review process() in utils.py for performance issues."
      },
      {
        role: "assistant",
        content:
          "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list."
      },
      {
        role: "user",
        content: "Now review the calling code that invokes process()."
      },
      // O revisor percebe no meio da sessão que todas as sugestões também devem passar
      // pela política de tipagem estrita da equipe. Anexar a instrução aqui mantém
      // os turnos anteriores idênticos byte a byte, então o prefixo armazenado em cache pela
      // requisição anterior ainda é lido do cache.
      {
        role: "system",
        content: "From now on, every suggestion must include explicit type annotations."
      }
    ]
  });

  const textBlock = response.content.find(
    (block): block is Anthropic.TextBlock => block.type === "text"
  );
  console.log(textBlock?.text);
  ```

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

  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      // "Prompt caching" (cache de prompt) automático: cada requisição armazena em cache a conversa até aqui,
      // e a próxima requisição lê do cache o prefixo inalterado.
      CacheControl = new CacheControlEphemeral(),
      System = "You are a code review assistant. Be concise.",
      Messages =
      [
          new()
          {
              Role = Role.User,
              Content = "Review process() in utils.py for performance issues."
          },
          new()
          {
              Role = Role.Assistant,
              Content = "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list."
          },
          new()
          {
              Role = Role.User,
              Content = "Now review the calling code that invokes process()."
          },
          // No meio da sessão, o revisor percebe que todas as sugestões também devem seguir
          // a política de tipagem estrita da equipe. Anexar a instrução aqui mantém
          // os turnos anteriores idênticos byte a byte, então o prefixo armazenado pela requisição
          // anterior ainda é lido do cache.
          new()
          {
              Role = Role.System,
              Content = "From now on, every suggestion must include explicit type annotations."
          }
      ]
  };

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

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

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	// Cache de prompt automático: cada requisição armazena em cache a conversa até aqui,
  	// e a próxima requisição lê do cache o prefixo inalterado.
  	CacheControl: anthropic.NewCacheControlEphemeralParam(),
  	System: []anthropic.TextBlockParam{
  		{Text: "You are a code review assistant. Be concise."},
  	},
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Review process() in utils.py for performance issues.")),
  		anthropic.NewAssistantMessage(anthropic.NewTextBlock("The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.")),
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Now review the calling code that invokes process().")),
  		// No meio da sessão, o revisor percebe que todas as sugestões também devem
  		// seguir a política de tipagem estrita da equipe. Anexar a instrução
  		// aqui mantém os turnos anteriores idênticos byte a byte, então o prefixo em cache
  		// da requisição anterior ainda é lido do cache.
  		{
  			Role: anthropic.MessageParamRoleSystem,
  			Content: []anthropic.ContentBlockParamUnion{
  				anthropic.NewTextBlock("From now on, every suggestion must include explicit type annotations."),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  for _, block := range response.Content {
  	if textBlock, ok := block.AsAny().(anthropic.TextBlock); ok {
  		fmt.Println(textBlock.Text)
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.messages.CacheControlEphemeral;
  // ...
  import com.anthropic.models.messages.MessageParam;
  // ...
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          // "Prompt caching" (cache de prompt) automático: cada requisição armazena em cache a conversa até aqui,
          // e a próxima requisição lê do cache o prefixo inalterado.
          .cacheControl(CacheControlEphemeral.builder().build())
          .system("You are a code review assistant. Be concise.")
          .addUserMessage("Review process() in utils.py for performance issues.")
          .addAssistantMessage("The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.")
          .addUserMessage("Now review the calling code that invokes process().")
          // O revisor percebe no meio da sessão que todas as sugestões também devem passar
          // pela política de tipagem estrita da equipe. Adicionar a instrução aqui mantém
          // os turnos anteriores idênticos byte a byte, então o prefixo armazenado em cache pela
          // requisição anterior ainda é lido do cache.
          .addMessage(MessageParam.builder()
              .role(MessageParam.Role.SYSTEM)
              .content("From now on, every suggestion must include explicit type annotations.")
              .build())
          .build();

      Message response = client.messages().create(params);
      response.content().stream()
          .flatMap(block -> block.text().stream())
          .forEach(textBlock -> IO.println(textBlock.text()));
  ```

  ```php PHP
  use Anthropic\Messages\CacheControlEphemeral;
  // ...
  $client = new Client();

  $response = $client->messages->create(
      maxTokens: 1024,
      messages: [
          ['role' => 'user', 'content' => 'Review process() in utils.py for performance issues.'],
          ['role' => 'assistant', 'content' => 'The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.'],
          ['role' => 'user', 'content' => 'Now review the calling code that invokes process().'],
          // O revisor percebe no meio da sessão que todas as sugestões também devem seguir
          // a política de tipagem estrita da equipe. Anexar a instrução aqui mantém
          // os turnos anteriores idênticos byte a byte, então o prefixo armazenado em cache pela
          // requisição anterior ainda é lido do cache.
          ['role' => 'system', 'content' => 'From now on, every suggestion must include explicit type annotations.']
      ],
      model: 'claude-opus-5-5',
      // "Prompt caching" (cache de prompt) automático: cada requisição armazena em cache a conversa até aqui,
      // e a próxima requisição lê do cache o prefixo inalterado.
      cacheControl: CacheControlEphemeral::with(),
      system: 'You are a code review assistant. Be concise.',
  );

  foreach ($response->content as $block) {
      if ($block->type === 'text') {
          echo $block->text, PHP_EOL;
      }
  }
  ```

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

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    # "Prompt caching" (cache de prompt) automático: cada requisição armazena em cache a conversa até aqui,
    # e a próxima requisição lê do cache o prefixo inalterado.
    cache_control: { type: "ephemeral" },
    system: "You are a code review assistant. Be concise.",
    messages: [
      { role: "user", content: "Review process() in utils.py for performance issues." },
      { role: "assistant", content: "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list." },
      { role: "user", content: "Now review the calling code that invokes process()." },
      # No meio da sessão, o revisor percebe que todas as sugestões também devem atender
      # à política de tipagem estrita da equipe. Anexar a instrução aqui mantém
      # os turnos anteriores idênticos byte a byte, então o prefixo armazenado em cache pela
      # requisição anterior ainda é lido do cache.
      { role: "system", content: "From now on, every suggestion must include explicit type annotations." }
    ]
  )

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

Este exemplo ativa o [cache automático](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching#automatic-caching) com o campo `cache_control` de nível superior. O cache de prompt é opcional: se uma requisição não tem nenhum campo `cache_control` (automático ou um [ponto de interrupção explícito](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching#explicit-cache-breakpoints)), nada é armazenado em cache e cada requisição paga o preço normal de tokens de entrada pela conversa completa. Com o cache ativado, acrescentar a mensagem de sistema deixa inalterados os turnos já em cache, então a requisição que contém a nova instrução ainda os lê do cache em vez de processá-los novamente. O cache também exige que a conversa atinja o [tamanho mínimo de prompt armazenável em cache](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching#cache-limitations); um exemplo tão curto quanto este fica abaixo dele, então `cache_creation_input_tokens` e `cache_read_input_tokens` permanecem em 0 até que a conversa cresça.

Uma mensagem de sistema no meio da conversa que contém conteúdo (blocos `text`, `tool_addition` ou `tool_removal`) deve vir imediatamente após um turno `user` (ou um turno `assistant` que termina em um resultado de ferramenta de servidor) e deve ser a última entrada em `messages` ou ser imediatamente seguida por um turno `assistant`. Uma mensagem `user` que contém blocos `tool_result` conta: em um loop agêntico, você pode colocar a mensagem de sistema logo após os resultados das ferramentas, antes do próximo turno de Claude. Qualquer outra posição para uma mensagem que contém conteúdo, incluindo entre um bloco `tool_use` de `assistant` e o `tool_result` que o responde, retorna um erro 400. Uma mensagem com `content` vazio que apenas define [`output_config.effort`](https://platform.claude.com/docs/pt-BR/build-with-claude/effort#change-effort-mid-conversation-beta) é aceita em qualquer lugar de `messages`. Mensagens `system` consecutivas são avaliadas em conjunto, então uma mensagem apenas de esforço ao lado de uma que contém conteúdo segue a regra de conteúdo.

### Posicionamento após resultados de ferramentas

Em um [loop agêntico](https://platform.claude.com/docs/pt-BR/agents-and-tools/tool-use/overview), a mensagem do sistema vai após a mensagem `user` que entrega os resultados das ferramentas. Na maioria dos modelos, este também é o lugar onde sua aplicação pode repassar a entrada que o usuário digitou enquanto Claude estava trabalhando, para que o novo contexto seja absorvido sem reiniciar o turno (para o Claude Sonnet 5.5 e o Claude Haiku 5.5, consulte o final desta seção):

```json
[
  { "role": "user", "content": "Run the test suite and fix any failures." },
  {
    "role": "assistant",
    "content": [{ "type": "tool_use", "id": "toolu_01", "name": "run_tests", "input": {} }]
  },
  {
    "role": "user",
    "content": [
      { "type": "tool_result", "tool_use_id": "toolu_01", "content": "12 passed, 0 failed" }
    ]
  },
  {
    "role": "system",
    "content": "The user sent the following message while you were working: also update the changelog before you finish."
  }
]
```

Formule o conteúdo de sistema como contexto, e não como um comando que sobrepõe o usuário. Declare o fato ("nova entrada chegou do usuário: X", "o orçamento de tokens restante agora é Y") e deixe Claude agir com base nele. Claude é treinado para resistir a instruções que parecem agir contra o usuário, e essa proteção ainda se aplica ao papel de sistema, então linguagem como "ignore o que o usuário disse" é menos eficaz do que declarar o que mudou.

Esse padrão serve para repassar entrada do próprio usuário final da conversa. Não o use para passar saída de ferramentas, documentos recuperados ou outro conteúdo de terceiros; mantenha esse conteúdo em blocos `tool_result` (consulte [Limitações](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages#limitations)).

No Claude Sonnet 5.5 e no Claude Haiku 5.5, entregue as palavras do usuário no turno do usuário em vez disso. Esses modelos são treinados para resistir a injeção de prompt por meio de resultados de ferramentas, então podem tratar uma mensagem do sistema colocada logo após um resultado de ferramenta como texto não confiável e ignorá-la. Anexe as palavras do usuário como um bloco `text` após o último `tool_result` na mesma mensagem `user`. Mantenha os avisos do harness, como lembretes, em uma mensagem do sistema no meio da conversa separada após essa mensagem `user`, e nunca coloque um aviso e as palavras do usuário no mesmo bloco:

```json
[
  { "role": "user", "content": "Run the test suite and fix any failures." },
  {
    "role": "assistant",
    "content": [{ "type": "tool_use", "id": "toolu_01", "name": "run_tests", "input": {} }]
  },
  {
    "role": "user",
    "content": [
      { "type": "tool_result", "tool_use_id": "toolu_01", "content": "12 passed, 0 failed" },
      { "type": "text", "text": "Also update the changelog before you finish." }
    ]
  }
]
```

Para saber mais sobre esse comportamento, consulte [Como escrever prompts para o Claude Sonnet 5.5](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#mid-turn-user-messages-and-task-budgets) e [Prompting do Claude Haiku 5.5](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#mid-turn-user-messages).

### Mensagens de sistema com escopo de turno

Para limitar o escopo de uma mensagem `role: "system"` ao turno atual, defina seu campo `clear_at`. Ele aceita um de dois valores:

* `"never"` (o padrão): a mensagem é renderizada em sua posição em todas as requisições que a incluem. Omitir o campo tem o mesmo efeito.
* `"next_user_message"`: a mensagem tem **escopo de turno**. Seu texto é renderizado apenas enquanto nenhuma mensagem `role: "user"` vier depois dela em `messages`. Uma mensagem do usuário que contém apenas blocos `tool_result` conta como mensagem do usuário aqui. Assim que existe uma mensagem do usuário posterior, a mensagem é **limpa**: ela permanece no array, mas não renderiza nada e não custa tokens de entrada, nessa requisição e em todas as posteriores.

As mensagens de sistema com escopo de turno estão em beta. Inclua o [cabeçalho beta](https://platform.claude.com/docs/pt-BR/api/beta-headers) `mid-conversation-system-clear-at-2026-08-21`. Sem ele, `clear_at` é rejeitado como campo desconhecido.

```json
{
  "role": "system",
  "clear_at": "next_user_message",
  "content": "First privately list what you need next; then request every item that doesn't depend on another's result in this one response."
}
```

O uso principal é um lembrete por turno em um loop de ferramentas. Anexe o lembrete após a mensagem `tool_result` sempre que quiser que o modelo o veja, e deixe todas as cópias anteriores onde estão. O modelo vê apenas as cópias que vêm após a última mensagem do usuário, então o lembrete nunca se acumula. Nada anterior em `messages` muda, então o [cache de prompt](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching) continua correspondendo. No Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 e Claude Haiku 5.5, isso também mantém os [blocos de pensamento posteriores válidos](https://platform.claude.com/docs/pt-BR/build-with-claude/thinking#preserved-in-conversation): excluir um lembrete anterior alteraria a conversa antes desses blocos e faria a verificação da conversa falhar, enquanto uma mensagem limpa permanece no array e deixa essa conversa inalterada.

A requisição a seguir é uma etapa posterior de um loop de agente. `messages[3]` foi renderizada na requisição anterior, quando era a última mensagem do array. Assim que `messages[5]` (uma mensagem do usuário posterior) existe, `messages[3]` é limpa: a mensagem limpa permanece no array, então a conversa antes do bloco de pensamento em `messages[4]` fica inalterada, mas o modelo não vê mais seu texto. `messages[6]` e `messages[7]` são ambas renderizadas, em ordem.

```json
{
  "model": "claude-fable-5-1",
  "max_tokens": 16000,
  "messages": [
    { "role": "user", "content": "Fix the failing test." },
    {
      "role": "assistant",
      "content": [
        { "type": "thinking", "thinking": "", "signature": "..." },
        {
          "type": "tool_use",
          "id": "toolu_01",
          "name": "read_file",
          "input": { "path": "test_auth.py" }
        }
      ]
    },
    {
      "role": "user",
      "content": [{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "..." }]
    },
    {
      "role": "system",
      "clear_at": "next_user_message",
      "content": "Request independent reads in one turn."
    },
    {
      "role": "assistant",
      "content": [
        { "type": "thinking", "thinking": "", "signature": "..." },
        {
          "type": "tool_use",
          "id": "toolu_02",
          "name": "read_file",
          "input": { "path": "auth.py" }
        },
        {
          "type": "tool_use",
          "id": "toolu_03",
          "name": "read_file",
          "input": { "path": "tokens.py" }
        }
      ]
    },
    {
      "role": "user",
      "content": [
        { "type": "tool_result", "tool_use_id": "toolu_02", "content": "..." },
        {
          "type": "tool_result",
          "tool_use_id": "toolu_03",
          "content": "...",
          "cache_control": { "type": "ephemeral" }
        }
      ]
    },
    {
      "role": "system",
      "clear_at": "next_user_message",
      "content": "Request independent reads in one turn."
    },
    {
      "role": "system",
      "clear_at": "next_user_message",
      "content": "The shell exited with status 137."
    }
  ]
}
```

Regras para mensagens com escopo de turno:

* **Reenvie as mensagens limpas literalmente.** Uma mensagem limpa ainda faz parte do histórico da conversa. Reconstruí-la a partir do estado atual (uma nova contagem de tokens, um timestamp), descartá-la como redundante ou alterar seu valor de `clear_at` é uma edição de uma mensagem anterior. O cache de prompt falha a partir desse ponto e, no Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 e Claude Haiku 5.5, todo bloco de pensamento produzido depois dela falha na [verificação da conversa](https://platform.claude.com/docs/pt-BR/build-with-claude/thinking#preserved-in-conversation).
* **Somente texto.** `content` é um ou mais blocos `text` (ou uma string). Blocos `tool_addition` e `tool_removal` retornam um erro 400 em uma mensagem com escopo de turno, assim como `output_config`. Para esses, use uma mensagem `role: "system"` separada, sem `clear_at`.
* **Sem `cache_control` em seus blocos.** Uma mensagem limpa nunca faz parte de uma chave de cache, então um breakpoint nela nunca poderia corresponder. Coloque o breakpoint no último bloco do turno do usuário anterior, como faz o exemplo. O campo de [cache automático](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching#automatic-caching) de nível superior ignora mensagens com escopo de turno ao escolher um breakpoint. Na requisição que limpa uma mensagem, o prefixo em cache reutilizável termina no turno do usuário anterior a ela, então apenas o único turno do assistente entre essa mensagem e a nova mensagem do usuário é reprocessado.
* **As regras de posicionamento continuam valendo**, limpa ou não. Uma mensagem com escopo de turno deve vir após um turno `user` (ou um turno `assistant` que termina em um resultado de ferramenta de servidor) e preceder um turno `assistant` ou encerrar o array, como qualquer mensagem do sistema no meio da conversa. Uma que encerra o array é sempre renderizada. Uma seguida diretamente por outra mensagem `user` é um erro 400, e não uma mensagem limpa: coloque todos os resultados de uma rodada de ferramentas em uma única mensagem do usuário e os lembretes depois dela.
* **Turnos do assistente não a limpam.** Um turno do assistente pré-preenchido ou [pausado](https://platform.claude.com/docs/pt-BR/build-with-claude/handling-stop-reasons#pause-turn) após a mensagem, ou um loop de ferramentas do lado do servidor, não adiciona nenhuma mensagem do usuário, então a mensagem continua sendo renderizada nessa continuação. Para manter um lembrete visível ao longo de um loop de ferramentas do lado do cliente, acrescente-o novamente após cada mensagem `tool_result`.
* **A contagem de tokens segue o que é renderizado.** Uma mensagem limpa não adiciona nada a `usage.input_tokens` nem a uma [contagem de tokens](https://platform.claude.com/docs/pt-BR/build-with-claude/token-counting).
* **Histórico importado.** Em uma transcrição que você constrói de uma só vez (exemplos few-shot, uma conversa migrada), uma mensagem com escopo de turno que já tem um turno do assistente e uma mensagem do usuário depois dela é limpa desde a primeira requisição e nunca é renderizada. Esse é o estado correto para um lembrete por turno que você está trazendo. Deixe `clear_at` sem definir apenas em uma mensagem que o modelo deve ver em todas as requisições.

Os erros de validação são:

```text wrap
messages.3.clear_at: Extra inputs are not permitted
messages.3.clear_at: clear_at is only permitted on role 'system' messages
messages.3.clear_at: Input should be 'next_user_message' or 'never'
messages.3: a turn-scoped system message supports text blocks only (clear_at: 'next_user_message')
messages.3: output_config is not permitted on a turn-scoped system message (clear_at: 'next_user_message')
messages.3.content.0: cache_control is not permitted on a turn-scoped system message (clear_at: 'next_user_message')
```

O primeiro é o erro retornado sem o cabeçalho beta. No Google Cloud e no [Claude no Amazon Bedrock](https://platform.claude.com/docs/pt-BR/build-with-claude/claude-in-amazon-bedrock), envie o valor beta no cabeçalho `anthropic-beta`, como na Claude API (consulte [Cabeçalhos beta](https://platform.claude.com/docs/pt-BR/api/beta-headers)). Com a [InvokeModel API](https://platform.claude.com/docs/pt-BR/build-with-claude/claude-on-amazon-bedrock-legacy) do Amazon Bedrock, coloque-o no array `anthropic_beta` do corpo da requisição.

Pelo SDK, defina `clear_at` (csharp, go: `ClearAt`; java: `.clearAt()`; php: `clearAt`) na entrada `role: "system"` em `messages` e envie o cabeçalho beta. O exemplo a seguir anexa um lembrete com escopo de turno após o turno do usuário; na próxima requisição, assim que existir uma mensagem do usuário posterior, o lembrete permanece no array, mas não é mais renderizado:

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: mid-conversation-system-clear-at-2026-08-21" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-fable-5-1",
      "max_tokens": 4096,
      "messages": [
        {"role": "user", "content": "Draft a short status update on the database migration for the team channel."},
        {"role": "system", "clear_at": "next_user_message", "content": "The reader is on call: keep this reply under 50 words."}
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create --beta mid-conversation-system-clear-at-2026-08-21 \
    --transform 'content.#(type=="text").text' --raw-output <<'YAML'
  model: claude-fable-5-1
  max_tokens: 4096
  messages:
    - role: user
      content: Draft a short status update on the database migration for the team channel.
    # Lembrete com escopo de turno: é renderizado neste turno e removido quando houver uma mensagem posterior do usuário.
    - role: system
      clear_at: next_user_message
      content: "The reader is on call: keep this reply under 50 words."
  YAML
  ```

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

  response = client.beta.messages.create(
      model="claude-fable-5-1",
      max_tokens=4096,
      messages=[
          {
              "role": "user",
              "content": "Draft a short status update on the database migration for the team channel.",
          },
          # Lembrete com escopo de turno: é renderizado neste turno e removido quando houver uma mensagem posterior do usuário.
          {
              "role": "system",
              "clear_at": "next_user_message",
              "content": "The reader is on call: keep this reply under 50 words.",
          },
      ],
      betas=["mid-conversation-system-clear-at-2026-08-21"],
  )

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

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

  const response = await client.beta.messages.create({
    model: "claude-fable-5-1",
    max_tokens: 4096,
    messages: [
      {
        role: "user",
        content: "Draft a short status update on the database migration for the team channel."
      },
      // Lembrete com escopo de turno: é renderizado neste turno e limpo quando houver uma mensagem posterior do usuário.
      {
        role: "system",
        clear_at: "next_user_message",
        content: "The reader is on call: keep this reply under 50 words."
      }
    ],
    betas: ["mid-conversation-system-clear-at-2026-08-21"]
  });

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

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeFable5_1,
      MaxTokens = 4096,
      Messages =
      [
          new() { Role = Role.User, Content = "Draft a short status update on the database migration for the team channel." },
          // Lembrete com escopo de turno: é renderizado neste turno e é limpo quando houver uma mensagem posterior do usuário.
          new()
          {
              Role = Role.System,
              ClearAt = ClearAt.NextUserMessage,
              Content = "The reader is on call: keep this reply under 50 words.",
          },
      ],
      Betas = [AnthropicBeta.MidConversationSystemClearAt2026_08_21],
  });

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

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

  response, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeFable5_1,
  	MaxTokens: 4096,
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Draft a short status update on the database migration for the team channel.")),
  		// Lembrete com escopo de turno: é renderizado neste turno e é limpo quando houver uma mensagem posterior do usuário.
  		{
  			Role:    anthropic.BetaMessageParamRoleSystem,
  			ClearAt: anthropic.BetaMessageParamClearAtNextUserMessage,
  			Content: []anthropic.BetaContentBlockParamUnion{anthropic.NewBetaTextBlock("The reader is on call: keep this reply under 50 words.")},
  		},
  	},
  	Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaMidConversationSystemClearAt2026_08_21},
  })
  if err != nil {
  	log.Fatal(err)
  }

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

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaMessageParam;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  import com.anthropic.models.messages.Model;

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

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_FABLE_5_1)
          .maxTokens(4096L)
          .addBeta(AnthropicBeta.MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21)
          .addUserMessage("Draft a short status update on the database migration for the team channel.")
          // Lembrete com escopo de turno: é renderizado neste turno e é limpo quando houver uma mensagem posterior do usuário.
          .addMessage(BetaMessageParam.builder()
              .role(BetaMessageParam.Role.SYSTEM)
              .clearAt(BetaMessageParam.ClearAt.NEXT_USER_MESSAGE)
              .content("The reader is on call: keep this reply under 50 words.")
              .build())
          .build();

      BetaMessage response = client.beta().messages().create(params);
      response.content().stream()
          .flatMap(block -> block.text().stream())
          .forEach(textBlock -> IO.println(textBlock.text()));
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaMessageParam;
  use Anthropic\Client;

  $client = new Client();

  $response = $client->beta->messages->create(
      model: 'claude-fable-5-1',
      maxTokens: 4096,
      messages: [
          BetaMessageParam::with(role: 'user', content: 'Draft a short status update on the database migration for the team channel.'),
          // Lembrete com escopo de turno: é renderizado neste turno e removido quando houver uma mensagem posterior do usuário.
          BetaMessageParam::with(
              role: 'system',
              clearAt: 'next_user_message',
              content: 'The reader is on call: keep this reply under 50 words.',
          ),
      ],
      betas: [AnthropicBeta::MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21],
  );

  foreach ($response->content as $block) {
      if ($block->type === 'text') {
          echo $block->text, PHP_EOL;
      }
  }
  ```

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

  response = client.beta.messages.create(
    model: "claude-fable-5-1",
    max_tokens: 4096,
    messages: [
      {role: "user", content: "Draft a short status update on the database migration for the team channel."},
      # Lembrete com escopo de turno: é renderizado neste turno e removido quando houver uma mensagem posterior do usuário.
      {role: "system", clear_at: :next_user_message, content: "The reader is on call: keep this reply under 50 words."}
    ],
    betas: [Anthropic::AnthropicBeta::MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21]
  )

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

## Combinando com cache de prompt

As mensagens de sistema no meio da conversa e o [cache de prompt](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching) foram projetados para serem usados em conjunto:

* **Habilite o cache explicitamente.** O cache só acontece quando a requisição inclui `cache_control`, seja o campo de nível superior de [cache automático](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching#automatic-caching) ou um [ponto de interrupção explícito](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching#explicit-cache-breakpoints) em um bloco de conteúdo. Uma mensagem de sistema no meio da conversa não cria uma entrada de cache por conta própria e, sem o cache habilitado, não há economia a preservar.
* **Armazene em cache o prefixo estável como de costume.** Coloque `cache_control` no último bloco que permanece o mesmo entre as requisições, seja o final do campo `system` de nível superior, o final das suas definições de ferramentas ou um ponto estável no histórico de mensagens.
* **Anexe a mensagem de sistema após o ponto de interrupção.** Como ela vem depois do prefixo em cache, ela não altera o hash do prefixo e o cache ainda é atingido.
* **Uma mensagem de sistema no meio da conversa também pode ser armazenada em cache.** Uma vez na conversa, ela passa a fazer parte do histórico estável. No próximo turno, você pode mover seu ponto de interrupção de cache para depois dela (ou contar com o [cache automático](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching#automatic-caching) para fazer isso) e a mensagem de sistema é lida do cache como qualquer outro turno.

Evite editar ou remover uma mensagem do sistema no meio da conversa que já foi enviada. Como qualquer outra alteração em mensagens anteriores, isso invalida o cache a partir desse ponto. No Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 e Claude Haiku 5.5, isso também invalida os [blocos de pensamento](https://platform.claude.com/docs/pt-BR/build-with-claude/thinking#preserved-in-conversation) em todos os turnos posteriores do assistente. Para orientações que devem se aplicar a apenas um turno, use uma [mensagem do sistema com escopo de turno](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) e deixe-a no lugar. Se a instrução precisar evoluir, anexe uma nova mensagem do sistema em vez de reescrever a antiga. Mensagens do sistema consecutivas são aceitas e tratadas como uma única seção de sistema, que segue a mesma regra de posicionamento como um todo.

## Limitações

* **Não serve para a primeira mensagem.** Uma mensagem `system` que contém conteúdo não pode ser a primeira entrada em `messages`. Use o campo `system` de nível superior para instruções que se aplicam desde o início.
* **O posicionamento é restrito.** Uma mensagem `system` que contém conteúdo (blocos `text`, `tool_addition` ou `tool_removal`) deve vir imediatamente após um turno `user` (incluindo um turno `user` que contém blocos `tool_result`) ou um turno `assistant` que termina em um resultado de ferramenta de servidor, e deve preceder um turno `assistant` ou encerrar o array. Ela não pode ficar entre um bloco `tool_use` e seu `tool_result`. Colocá-la em outro lugar retorna um erro 400. Uma exceção: blocos `tool_addition` e `tool_removal` não são aceitos imediatamente após um turno `assistant` [pausado](https://platform.claude.com/docs/pt-BR/build-with-claude/handling-stop-reasons#pause-turn) (um que termina em um resultado de ferramenta de servidor), embora blocos `text` sejam; retome primeiro o turno pausado e, em seguida, envie a alteração de ferramenta na próxima mensagem `system`. Uma mensagem com `content` vazio que apenas define [`output_config.effort`](https://platform.claude.com/docs/pt-BR/build-with-claude/effort#change-effort-mid-conversation-beta) não renderiza nada em sua posição e é aceita em qualquer lugar de `messages`, inclusive como primeira entrada ou entre um turno `assistant` e um turno `user`. Mensagens `system` consecutivas são avaliadas em conjunto, então adicionar uma mensagem com texto ao lado de uma que define apenas o esforço faz com que o grupo inteiro siga a regra de conteúdo.
* **Mensagens com escopo de turno contêm apenas texto e são reenviadas literalmente.** Uma mensagem `clear_at: "next_user_message"` não contém `tool_addition`, `tool_removal`, `output_config` nem `cache_control` e, depois de limpa, deve permanecer em `messages` byte a byte nas requisições posteriores. Consulte [Mensagens do sistema com escopo de turno](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages).
* **Não é lugar para conteúdo não confiável.** O Claude trata o conteúdo do sistema como instruções do operador e as segue. Não coloque texto de fora da conversa, como saídas brutas de ferramentas, documentos recuperados ou conteúdo da web, diretamente em uma mensagem do sistema; fazer isso dá a esse texto autoridade de nível de operador. Mantenha esses dados em blocos `tool_result` e continue seguindo [Mitigar jailbreaks e injeções de prompt](https://platform.claude.com/docs/pt-BR/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks).

## Relacionado

<CardGroup cols={2}>
  <Card title="Cache de prompt" icon="bolt" href="https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching">
    Como o cache funciona, onde colocar pontos de interrupção e como ler os campos de uso de cache.
  </Card>

  <Card title="Diagnóstico de cache" icon="magnifying-glass" href="https://platform.claude.com/docs/pt-BR/build-with-claude/cache-diagnostics">
    Descubra exatamente onde duas requisições divergiram quando um acerto de cache que você esperava não acontece.
  </Card>

  <Card title="Usando a Messages API" icon="message" href="https://platform.claude.com/docs/pt-BR/build-with-claude/working-with-messages">
    Estrutura de mensagens, conversas de múltiplos turnos e o campo `system`.
  </Card>

  <Card title="Melhores práticas de prompting" icon="text" href="https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-engineering/claude-prompting-best-practices">
    Escrevendo prompts e instruções de sistema eficazes.
  </Card>

  <Card title="Uso de ferramentas com Claude" icon="wrench" href="https://platform.claude.com/docs/pt-BR/agents-and-tools/tool-use/overview">
    Como os blocos `tool_use` e `tool_result` são estruturados no array `messages`.
  </Card>
</CardGroup>
