---
title: Compactação sob demanda
url: https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-on-demand
description: Peça ao Claude para resumir uma conversa quando sua aplicação decidir e, em seguida, continue a partir do resumo.
featureMetadata:
  status: beta
  betaHeader: compact-2026-09-04
  supportedModels:
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-fable-5
    - claude-mythos-5
    - claude-mythos-preview
    - claude-opus-5-5
    - claude-opus-5
    - claude-opus-4-8
    - claude-opus-4-7
    - claude-opus-4-6
    - claude-sonnet-5-5
    - claude-sonnet-5
    - claude-sonnet-4-6
    - claude-haiku-5-5
  supportedPlatforms:
    Claude API: beta
    Claude Platform on AWS: beta
    Google Cloud: beta
    Microsoft Foundry: beta
---

Com a "on-demand compaction" (compactação sob demanda), sua aplicação decide quando uma conversa é resumida: você envia uma solicitação com o parâmetro `compaction`, e Claude retorna um resumo no lugar de uma resposta.

## Como a compactação sob demanda funciona

Uma solicitação de compactação é separada dos turnos da sua conversa. Você envia a conversa como está com o parâmetro `compaction`, e a resposta contém um único bloco `compaction`. O bloco contém o resumo como texto que você pode ler, e uma assinatura. Envie-o em solicitações futuras exatamente como ele veio.

A partir daí, o bloco ocupa o lugar das mensagens que ele resume. Ele vai primeiro em `messages`, as mensagens resumidas são removidas, e seu próximo turno vem depois dele. Claude vê o resumo onde essas mensagens estavam.

<Frame>
  ![On-demand compaction (compactação sob demanda): uma solicitação que carrega quatro mensagens e o parâmetro compaction retorna um bloco compaction e nenhuma resposta; na próxima solicitação, o bloco vem primeiro em messages no lugar dessas quatro mensagens, seguido pelo próximo turno do usuário](https://platform.claude.com/docs/pt-BR/images/compaction-on-demand-swap.svg)
</Frame>

## Solicitar um resumo

Envie o cabeçalho beta `compact-2026-09-04` na solicitação que pede o resumo e em todas as solicitações posteriores que carregam o bloco assinado. Para verificar se um modelo oferece suporte à compactação sob demanda, chame a [Models API](https://platform.claude.com/docs/pt-BR/api/beta/models/list) com o cabeçalho beta e leia o `capabilities.compaction` de cada modelo. Você não pode combinar `compaction` com `context_management` em uma mesma solicitação.

Envie a conversa como está com `"compaction": {"type": "summarize"}`. A API resume todas as mensagens da solicitação uma vez, não gera nenhuma resposta depois disso e retorna apenas o bloco com `stop_reason` `"compaction"`. Envie o mesmo prompt `system` e as mesmas `tools` que você usa no restante da conversa. O sumarizador os lê e, se você mantiver turnos após o bloco em um modelo com ["preserved thinking" (pensamento preservado)](https://platform.claude.com/docs/pt-BR/build-with-claude/preserved-thinking), o pensamento nesses turnos permanece válido somente se `system` e `tools` corresponderem. A conversa neste exemplo não tem prompt `system` nem ferramentas, então a solicitação não envia nenhum dos dois:

<CodeGroup>
  ```bash cURL
  # max_tokens limita a chamada inteira, incluindo qualquer pensamento, então reserve vários milhares de tokens.
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: compact-2026-09-04" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 4096,
      "messages": [
        {"role": "user", "content": "I am building a recipe app. Help me name the main entities in the data model."},
        {"role": "assistant", "content": "Start with Recipe, Ingredient, and Step. Add a RecipeIngredient entry that holds the quantity and unit for each ingredient in a recipe."},
        {"role": "user", "content": "Good. Now suggest field names for Recipe."}
      ],
      "compaction": {"type": "summarize"}
    }'
  ```

  ```bash CLI
  ant beta:messages create --beta compact-2026-09-04 <<'YAML'
  model: claude-opus-5-5
  # max_tokens limita a chamada inteira, incluindo qualquer pensamento, então reserve vários milhares de tokens.
  max_tokens: 4096
  messages:
    - role: user
      content: I am building a recipe app. Help me name the main entities in the data model.
    - role: assistant
      content: Start with Recipe, Ingredient, and Step. Add a RecipeIngredient entry that holds the quantity and unit for each ingredient in a recipe.
    - role: user
      content: Good. Now suggest field names for Recipe.
  compaction:
    type: summarize
  YAML
  ```

  ```python Python
  from anthropic.types.beta import BetaMessageParam

  client = anthropic.Anthropic()

  history: list[BetaMessageParam] = [
      {
          "role": "user",
          "content": "I am building a recipe app. Help me name the main entities in the data model.",
      },
      {
          "role": "assistant",
          "content": "Start with Recipe, Ingredient, and Step. Add a RecipeIngredient entry that holds the quantity and unit for each ingredient in a recipe.",
      },
      {"role": "user", "content": "Good. Now suggest field names for Recipe."},
  ]

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      # max_tokens limita a chamada inteira, incluindo qualquer pensamento, então reserve vários milhares de tokens.
      max_tokens=4096,
      betas=["compact-2026-09-04"],
      messages=history,
      compaction={"type": "summarize"},
  )
  print(f"Stop reason: {response.stop_reason}")
  ```

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

  const history: Anthropic.Beta.Messages.BetaMessageParam[] = [
    {
      role: "user",
      content: "I am building a recipe app. Help me name the main entities in the data model."
    },
    {
      role: "assistant",
      content:
        "Start with Recipe, Ingredient, and Step. Add a RecipeIngredient entry that holds the quantity and unit for each ingredient in a recipe."
    },
    { role: "user", content: "Good. Now suggest field names for Recipe." }
  ];

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    // max_tokens limita a chamada inteira, incluindo qualquer pensamento, então reserve vários milhares de tokens.
    max_tokens: 4096,
    betas: ["compact-2026-09-04"],
    messages: history,
    compaction: { type: "summarize" }
  });
  console.log(`Stop reason: ${response.stop_reason}`);
  ```

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

  AnthropicClient client = new();

  List<BetaMessageParam> history =
  [
      new()
      {
          Role = Role.User,
          Content = "I am building a recipe app. Help me name the main entities in the data model.",
      },
      new()
      {
          Role = Role.Assistant,
          Content = "Start with Recipe, Ingredient, and Step. Add a RecipeIngredient entry that holds the quantity and unit for each ingredient in a recipe.",
      },
      new() { Role = Role.User, Content = "Good. Now suggest field names for Recipe." },
  ];

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      // max_tokens limita a chamada inteira, incluindo qualquer pensamento, então reserve vários milhares de tokens.
      MaxTokens = 4096,
      Betas = [AnthropicBeta.Compact2026_09_04],
      Messages = history,
      Compaction = new BetaCompactionConfig(), // type defaults to "summarize"
  });

  Console.WriteLine($"Stop reason: {response.StopReason?.Raw()}");
  ```

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

  history := []anthropic.BetaMessageParam{
  	anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("I am building a recipe app. Help me name the main entities in the data model.")),
  	{
  		Role:    anthropic.BetaMessageParamRoleAssistant,
  		Content: []anthropic.BetaContentBlockParamUnion{anthropic.NewBetaTextBlock("Start with Recipe, Ingredient, and Step. Add a RecipeIngredient entry that holds the quantity and unit for each ingredient in a recipe.")},
  	},
  	anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Good. Now suggest field names for Recipe.")),
  }

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model: anthropic.ModelClaudeOpus5_5,
  	// max_tokens limita a chamada inteira, incluindo qualquer pensamento, então reserve vários milhares de tokens.
  	MaxTokens: 4096,
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaCompact2026_09_04},
  	Messages:  history,
  	Compaction: anthropic.BetaCompactionConfigUnionParam{
  		OfSummarize: &anthropic.BetaSummarizeCompactionParam{},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  fmt.Println("Stop reason:", response.StopReason)
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaCompactionConfig;
  import com.anthropic.models.beta.messages.MessageCreateParams;

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

      var params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          // max_tokens limita a chamada inteira, incluindo qualquer pensamento, então reserve vários milhares de tokens.
          .maxTokens(4096)
          .addBeta(AnthropicBeta.COMPACT_2026_09_04)
          .addUserMessage("I am building a recipe app. Help me name the main entities in the data model.")
          .addAssistantMessage("Start with Recipe, Ingredient, and Step. Add a RecipeIngredient entry that holds the quantity and unit for each ingredient in a recipe.")
          .addUserMessage("Good. Now suggest field names for Recipe.")
          .compaction(BetaCompactionConfig.builder().build()) // type defaults to "summarize"
          .build();

      var response = client.beta().messages().create(params);
      response.stopReason().ifPresent(reason -> IO.println("Stop reason: " + reason));
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaCompactionConfig;
  use Anthropic\Beta\Messages\BetaMessageParam;
  use Anthropic\Beta\Messages\BetaMessageParam\Role;

  $client = new Client();

  $history = [
      BetaMessageParam::with(
          role: Role::USER,
          content: 'I am building a recipe app. Help me name the main entities in the data model.',
      ),
      BetaMessageParam::with(
          role: Role::ASSISTANT,
          content: 'Start with Recipe, Ingredient, and Step. Add a RecipeIngredient entry that holds the quantity and unit for each ingredient in a recipe.',
      ),
      BetaMessageParam::with(role: Role::USER, content: 'Good. Now suggest field names for Recipe.'),
  ];

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      // max_tokens limita a chamada inteira, incluindo qualquer pensamento, então reserve vários milhares de tokens.
      maxTokens: 4096,
      betas: [AnthropicBeta::COMPACT_2026_09_04],
      messages: $history,
      compaction: BetaCompactionConfig::with(), // type defaults to 'summarize'
  );

  echo "Stop reason: {$response->stopReason}", PHP_EOL;
  ```

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

  history = [
    {
      role: "user",
      content: "I am building a recipe app. Help me name the main entities in the data model."
    },
    {
      role: "assistant",
      content: "Start with Recipe, Ingredient, and Step. Add a RecipeIngredient entry that holds the quantity and unit for each ingredient in a recipe."
    },
    { role: "user", content: "Good. Now suggest field names for Recipe." }
  ]

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    # max_tokens limita a chamada inteira, incluindo qualquer pensamento, então reserve vários milhares de tokens.
    max_tokens: 4096,
    betas: [Anthropic::AnthropicBeta::COMPACT_2026_09_04],
    messages: history,
    compaction: { type: "summarize" }
  )
  puts "Stop reason: #{response.stop_reason}"
  ```
</CodeGroup>

```json Response
{
  "id": "msg_013Zva2CMHLNnXjNJJKqJ2EF",
  "type": "message",
  "role": "assistant",
  "model": "claude-opus-5-5",
  "content": [
    {
      "type": "compaction",
      "content": "Summary of the conversation: the user is designing the data model for a recipe app. The entities agreed so far are Recipe, Ingredient, Step, and RecipeIngredient, which holds the quantity and unit. The user then asked for field names for Recipe.",
      "signature": "EuYBCkQY..."
    }
  ],
  "stop_reason": "compaction",
  "usage": {
    "input_tokens": 0,
    "output_tokens": 0,
    "iterations": [{ "type": "compaction", "input_tokens": 144, "output_tokens": 276 }]
  }
}
```

A chamada de sumarização usa o modelo, o `system`, as `tools`, as configurações de pensamento e o `max_tokens` da solicitação. O sumarizador lê as definições de ferramentas, mas nunca executa uma ferramenta, e a resposta não traz nenhum pensamento. `max_tokens` limita a chamada inteira, incluindo qualquer pensamento que o modelo faça antes de escrever o resumo, então reserve vários milhares de tokens. [Contabilizar o uso da compactação](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-on-demand#understanding-usage) mostra como a chamada é cobrada.

Se o último turno `assistant` terminar em uma chamada de ferramenta ainda sem resultado, a API rejeita a solicitação. Envie primeiro os resultados de ferramentas desse turno. Também deixe de fora `stop_sequences`, o `output_config.format` de saída estruturada e um `tool_choice` do tipo `any` ou `tool`. Eles não teriam efeito em uma chamada de sumarização, e a API os rejeita. A conversa ainda precisa caber na "context window" (janela de contexto) do modelo, então compacte antes de ultrapassá-la, não depois.

Quando você faz streaming da resposta, o bloco chega inteiro. Você recebe um evento `content_block_start` carregando o bloco completo, depois `content_block_stop`, sem eventos `content_block_delta`. Eventos `ping` podem chegar antes ou entre eles.

## Continuar a partir do resumo

No seu histórico, substitua as mensagens que você enviou pela mensagem do assistente retornada. Mantenha o bloco `compaction` exatamente como a API o retornou, incluindo sua `signature`. Quaisquer turnos realizados depois que você enviou a solicitação de compactação vêm após o bloco sem alterações, e é nisso que se baseia a [Compactação em segundo plano](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-background). Envie o bloco primeiro em todas as solicitações posteriores, com o cabeçalho beta:

```json
{
  "model": "claude-opus-5-5",
  "max_tokens": 2048,
  "messages": [
    {
      "role": "assistant",
      "content": [
        {
          "type": "compaction",
          "content": "Summary of the conversation: the user is designing the data model for a recipe app. The entities agreed so far are Recipe, Ingredient, Step, and RecipeIngredient, which holds the quantity and unit. The user then asked for field names for Recipe.",
          "signature": "EuYBCkQY..."
        }
      ]
    },
    {
      "role": "assistant",
      "content": "For Recipe, use title, description, servings, prep_minutes, and cook_minutes. Add created_at and updated_at timestamps."
    },
    { "role": "user", "content": "Now do the same for Ingredient." }
  ]
}
```

Este exemplo dá continuidade ao exemplo de solicitação, que terminou em um turno `user`; o diagrama mostra o caso mais simples, em que nenhum turno é realizado enquanto o resumo é escrito. Aqui, a segunda mensagem `assistant` é a resposta ao último turno `user` resumido. Ela chegou enquanto o resumo estava sendo escrito, então não estava entre as mensagens resumidas. Duas mensagens `assistant` seguidas não são um problema aqui, porque o bloco ainda vem primeiro.

A API coloca o resumo onde o bloco está e passa todas as mensagens posteriores para Claude sem alterações. Siga estas regras:

* Coloque o bloco primeiro em `messages`, seja como uma mensagem `assistant` própria ou como o primeiro bloco de conteúdo da primeira mensagem, seja ela uma mensagem `user` ou `assistant`.
* Remova as mensagens resumidas. Se alguma permanecer antes do bloco, a solicitação retorna um erro 400 (`compaction_block_misplaced`).
* Envie exatamente um bloco `compaction` por solicitação, em todas as solicitações posteriores.

<Warning>
  Dois enganos na substituição não geram nenhum erro. Se mensagens resumidas permanecerem após o bloco, a API as envia para Claude novamente. Se uma solicitação posterior deixar o bloco de fora, Claude não recebe nenhum resumo.
</Warning>

A "threshold compaction" (compactação por limite) funciona ao contrário: seu bloco vem depois das mensagens que ele resume, e a API as descarta para você. Consulte [Enviando os blocos de compactação de volta](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-threshold#passing-compaction-blocks-back).

Em Python, use `client.beta.messages`, como fazem os exemplos desta página. Se você chamar `client.messages` e serializar os blocos por conta própria, use `to_dict()` ou `model_dump(exclude_none=True)`: um `model_dump()` simples adiciona `citations: null` e `text: null` ao bloco, e a API o rejeita.

Se você mantiver turnos após o bloco e enviar de volta os blocos de pensamento deles, as condições que mantêm esse pensamento válido estão em [Compactação e pensamento preservado](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-thinking-blocks).

### Compactar novamente

Para compactar uma conversa que já começa com um bloco, envie `compaction` novamente. O novo bloco resume o resumo antigo e tudo o que vem depois dele. A partir daí, envie apenas o bloco mais recente.

## Compactar em um loop

Após cada turno, o loop soma os tokens de entrada e de saída da última resposta, porque a próxima solicitação também envia a resposta. Quando esse total ultrapassa um limite e ainda há outro turno por vir, ele envia uma solicitação de compactação com o mesmo modelo e o mesmo prompt `system`, verifica `stop_reason`, substitui seu histórico pela mensagem retornada e imprime o turno antes do qual compactou. O limite de 2.500 tokens do exemplo é deliberadamente baixo, para que uma conversa curta seja compactada. Defina o seu próximo ao seu orçamento real de entrada.

<CodeGroup exclude="shell">
  ```python Python
  from anthropic.types.beta import BetaMessageParam

  client = anthropic.Anthropic()

  # Defina isto perto do seu orçamento real de entrada. Aqui está baixo para que uma conversa curta seja compactada.
  COMPACT_AT_TOKENS = 2500
  SYSTEM = "You help design a recipe app's data model. Keep answers short."

  QUESTIONS = [
      "What are the main entities in the data model?",
      "Which fields should Recipe have?",
      "Which fields should Ingredient have?",
      "Which fields should RecipeIngredient have?",
      "Which fields should Step have?",
      "Which indexes should these tables have?",
      "Which fields should be required?",
      "Which fields should have default values?",
  ]

  history: list[BetaMessageParam] = []
  for turn, question in enumerate(QUESTIONS, start=1):
      history.append({"role": "user", "content": question})
      response = client.beta.messages.create(
          model="claude-opus-5-5",
          max_tokens=8192,
          system=SYSTEM,
          betas=["compact-2026-09-04"],
          messages=history,
      )
      history.append({"role": "assistant", "content": response.content})

      # A próxima requisição também envia esta resposta, então conte-a.
      conversation_tokens = response.usage.input_tokens + response.usage.output_tokens
      if conversation_tokens > COMPACT_AT_TOKENS and turn < len(QUESTIONS):
          summary = client.beta.messages.create(
              model="claude-opus-5-5",
              max_tokens=4096,
              system=SYSTEM,
              betas=["compact-2026-09-04"],
              messages=history,
              compaction={"type": "summarize"},
          )
          if summary.stop_reason == "compaction":
              history = [{"role": "assistant", "content": summary.content}]
              print(f"Compacted before turn {turn + 1}")
  ```

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

  // Defina isto próximo ao seu orçamento real de entrada. Aqui está baixo para que uma conversa curta seja compactada.
  const compactAtTokens = 2500;
  const systemPrompt = "You help design a recipe app's data model. Keep answers short.";

  const questions = [
    "What are the main entities in the data model?",
    "Which fields should Recipe have?",
    "Which fields should Ingredient have?",
    "Which fields should RecipeIngredient have?",
    "Which fields should Step have?",
    "Which indexes should these tables have?",
    "Which fields should be required?",
    "Which fields should have default values?"
  ];

  let history: Anthropic.Beta.Messages.BetaMessageParam[] = [];
  for (const [index, question] of questions.entries()) {
    const turn = index + 1;
    history.push({ role: "user", content: question });
    const response = await client.beta.messages.create({
      model: "claude-opus-5-5",
      max_tokens: 8192,
      system: systemPrompt,
      betas: ["compact-2026-09-04"],
      messages: history
    });
    history.push({ role: "assistant", content: response.content });

    // A próxima requisição também envia esta resposta, então conte-a.
    const conversationTokens = response.usage.input_tokens + response.usage.output_tokens;
    if (conversationTokens > compactAtTokens && turn < questions.length) {
      const summary = await client.beta.messages.create({
        model: "claude-opus-5-5",
        max_tokens: 4096,
        system: systemPrompt,
        betas: ["compact-2026-09-04"],
        messages: history,
        compaction: { type: "summarize" }
      });
      if (summary.stop_reason === "compaction") {
        history = [{ role: "assistant", content: summary.content }];
        console.log(`Compacted before turn ${turn + 1}`);
      }
    }
  }
  ```

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

  AnthropicClient client = new();

  // Defina isto próximo ao seu orçamento real de entrada. Aqui está baixo para que uma conversa curta seja compactada.
  const int CompactAtTokens = 2500;
  const string SystemPrompt = "You help design a recipe app's data model. Keep answers short.";

  string[] questions =
  [
      "What are the main entities in the data model?",
      "Which fields should Recipe have?",
      "Which fields should Ingredient have?",
      "Which fields should RecipeIngredient have?",
      "Which fields should Step have?",
      "Which indexes should these tables have?",
      "Which fields should be required?",
      "Which fields should have default values?",
  ];

  List<BetaMessageParam> history = [];
  foreach (var (index, question) in questions.Index())
  {
      var turn = index + 1;
      history.Add(new() { Role = Role.User, Content = question });
      var response = await client.Beta.Messages.Create(new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 8192,
          System = SystemPrompt,
          Betas = [AnthropicBeta.Compact2026_09_04],
          Messages = history,
      });
      history.Add(new()
      {
          Role = Role.Assistant,
          Content = response.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
      });

      // A próxima requisição também envia esta resposta, então conte-a.
      var conversationTokens = response.Usage.InputTokens + response.Usage.OutputTokens;
      if (conversationTokens > CompactAtTokens && turn < questions.Length)
      {
          var summary = await client.Beta.Messages.Create(new MessageCreateParams
          {
              Model = Model.ClaudeOpus5_5,
              MaxTokens = 4096,
              System = SystemPrompt,
              Betas = [AnthropicBeta.Compact2026_09_04],
              Messages = history,
              Compaction = new BetaCompactionConfig(), // type defaults to "summarize"
          });
          if (summary.StopReason == BetaStopReason.Compaction)
          {
              history =
              [
                  new()
                  {
                      Role = Role.Assistant,
                      Content = summary.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
                  },
              ];
              Console.WriteLine($"Compacted before turn {turn + 1}");
          }
      }
  }
  ```

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

  // Defina isto próximo ao seu orçamento real de entrada. Aqui está baixo para que uma conversa curta seja compactada.
  const compactAtTokens = 2500
  system := []anthropic.BetaTextBlockParam{{Text: "You help design a recipe app's data model. Keep answers short."}}

  questions := []string{
  	"What are the main entities in the data model?",
  	"Which fields should Recipe have?",
  	"Which fields should Ingredient have?",
  	"Which fields should RecipeIngredient have?",
  	"Which fields should Step have?",
  	"Which indexes should these tables have?",
  	"Which fields should be required?",
  	"Which fields should have default values?",
  }

  var history []anthropic.BetaMessageParam
  for i, question := range questions {
  	turn := i + 1
  	history = append(history, anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock(question)))
  	response, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
  		Model:     anthropic.ModelClaudeOpus5_5,
  		MaxTokens: 8192,
  		System:    system,
  		Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaCompact2026_09_04},
  		Messages:  history,
  	})
  	if err != nil {
  		log.Fatal(err)
  	}
  	history = append(history, response.ToParam())

  	// A próxima requisição também envia esta resposta, então conte-a.
  	conversationTokens := response.Usage.InputTokens + response.Usage.OutputTokens
  	if conversationTokens > compactAtTokens && turn < len(questions) {
  		summary, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
  			Model:     anthropic.ModelClaudeOpus5_5,
  			MaxTokens: 4096,
  			System:    system,
  			Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaCompact2026_09_04},
  			Messages:  history,
  			Compaction: anthropic.BetaCompactionConfigUnionParam{
  				OfSummarize: &anthropic.BetaSummarizeCompactionParam{},
  			},
  		})
  		if err != nil {
  			log.Fatal(err)
  		}
  		if summary.StopReason == anthropic.BetaStopReasonCompaction {
  			history = []anthropic.BetaMessageParam{summary.ToParam()}
  			fmt.Printf("Compacted before turn %d\n", turn+1)
  		}
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaCompactionConfig;
  import com.anthropic.models.beta.messages.BetaMessageParam;
  import com.anthropic.models.beta.messages.BetaStopReason;
  import com.anthropic.models.beta.messages.MessageCreateParams;

  // Defina isto próximo ao seu orçamento real de entrada. Aqui está baixo para que uma conversa curta seja compactada.
  static final long COMPACT_AT_TOKENS = 2500;
  static final String SYSTEM = "You help design a recipe app's data model. Keep answers short.";

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

      var questions = List.of(
          "What are the main entities in the data model?",
          "Which fields should Recipe have?",
          "Which fields should Ingredient have?",
          "Which fields should RecipeIngredient have?",
          "Which fields should Step have?",
          "Which indexes should these tables have?",
          "Which fields should be required?",
          "Which fields should have default values?"
      );

      var history = new ArrayList<BetaMessageParam>();
      for (int turn = 1; turn <= questions.size(); turn++) {
          history.add(BetaMessageParam.builder()
              .role(BetaMessageParam.Role.USER)
              .content(questions.get(turn - 1))
              .build());
          var params = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(8192)
              .system(SYSTEM)
              .addBeta(AnthropicBeta.COMPACT_2026_09_04)
              .messages(history)
              .build();
          var response = client.beta().messages().create(params);
          history.add(response.toParam());

          // A próxima requisição também envia esta resposta, então conte-a.
          long conversationTokens = response.usage().inputTokens() + response.usage().outputTokens();
          if (conversationTokens > COMPACT_AT_TOKENS && turn < questions.size()) {
              var summaryParams = MessageCreateParams.builder()
                  .model(Model.CLAUDE_OPUS_5_5)
                  .maxTokens(4096)
                  .system(SYSTEM)
                  .addBeta(AnthropicBeta.COMPACT_2026_09_04)
                  .messages(history)
                  .compaction(BetaCompactionConfig.builder().build()) // type defaults to "summarize"
                  .build();
              var summary = client.beta().messages().create(summaryParams);
              if (summary.stopReason().map(BetaStopReason.COMPACTION::equals).orElse(false)) {
                  history.clear();
                  history.add(summary.toParam());
                  IO.println("Compacted before turn " + (turn + 1));
              }
          }
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaCompactionConfig;
  use Anthropic\Beta\Messages\BetaMessageParam;
  use Anthropic\Beta\Messages\BetaMessageParam\Role;
  use Anthropic\Beta\Messages\BetaStopReason;

  $client = new Client();

  // Defina isto próximo ao seu orçamento real de entrada. Aqui está baixo para que uma conversa curta seja compactada.
  const COMPACT_AT_TOKENS = 2500;
  const SYSTEM = "You help design a recipe app's data model. Keep answers short.";

  $questions = [
      'What are the main entities in the data model?',
      'Which fields should Recipe have?',
      'Which fields should Ingredient have?',
      'Which fields should RecipeIngredient have?',
      'Which fields should Step have?',
      'Which indexes should these tables have?',
      'Which fields should be required?',
      'Which fields should have default values?',
  ];

  $history = [];
  foreach ($questions as $index => $question) {
      $turn = $index + 1;
      $history[] = BetaMessageParam::with(role: Role::USER, content: $question);
      $response = $client->beta->messages->create(
          model: Model::CLAUDE_OPUS_5_5,
          maxTokens: 8192,
          system: SYSTEM,
          betas: [AnthropicBeta::COMPACT_2026_09_04],
          messages: $history,
      );
      $history[] = BetaMessageParam::with(role: Role::ASSISTANT, content: $response->content);

      // A próxima requisição também envia esta resposta, então conte-a.
      $conversationTokens = $response->usage->inputTokens + $response->usage->outputTokens;
      if ($conversationTokens > COMPACT_AT_TOKENS && $turn < count($questions)) {
          $summary = $client->beta->messages->create(
              model: Model::CLAUDE_OPUS_5_5,
              maxTokens: 4096,
              system: SYSTEM,
              betas: [AnthropicBeta::COMPACT_2026_09_04],
              messages: $history,
              compaction: new BetaCompactionConfig(), // type defaults to 'summarize'
          );
          if ($summary->stopReason === BetaStopReason::COMPACTION->value) {
              $history = [BetaMessageParam::with(role: Role::ASSISTANT, content: $summary->content)];
              printf("Compacted before turn %d\n", $turn + 1);
          }
      }
  }
  ```

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

  # Defina isto próximo ao seu orçamento real de entrada. Aqui está baixo para que uma conversa curta seja compactada.
  COMPACT_AT_TOKENS = 2500
  SYSTEM = "You help design a recipe app's data model. Keep answers short."

  questions = [
    "What are the main entities in the data model?",
    "Which fields should Recipe have?",
    "Which fields should Ingredient have?",
    "Which fields should RecipeIngredient have?",
    "Which fields should Step have?",
    "Which indexes should these tables have?",
    "Which fields should be required?",
    "Which fields should have default values?"
  ]

  history = []
  questions.each.with_index(1) do |question, turn|
    history << { role: "user", content: question }
    response = client.beta.messages.create(
      model: Anthropic::Model::CLAUDE_OPUS_5_5,
      max_tokens: 8192,
      system_: SYSTEM,
      betas: [Anthropic::AnthropicBeta::COMPACT_2026_09_04],
      messages: history
    )
    history << { role: "assistant", content: response.content }

    # A próxima requisição também envia esta resposta, então conte-a.
    conversation_tokens = response.usage.input_tokens + response.usage.output_tokens
    if conversation_tokens > COMPACT_AT_TOKENS && turn < questions.length
      summary = client.beta.messages.create(
        model: Anthropic::Model::CLAUDE_OPUS_5_5,
        max_tokens: 4096,
        system_: SYSTEM,
        betas: [Anthropic::AnthropicBeta::COMPACT_2026_09_04],
        messages: history,
        compaction: { type: "summarize" }
      )
      if summary.stop_reason == :compaction
        history = [{ role: "assistant", content: summary.content }]
        puts "Compacted before turn #{turn + 1}"
      end
    end
  end
  ```
</CodeGroup>

A verificação de `stop_reason` vem antes de o código procurar o bloco; [Lidar com um resumo ausente ou um erro](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-on-demand#when-no-summary-comes-back) explica por quê. O histórico é substituído, e não acrescido: a mensagem retornada substitui todas as mensagens que a solicitação carregava, conforme as regras em [Continuar a partir do resumo](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-on-demand#continue-from-the-summary). Quando nenhum resumo é retornado, o loop mantém seu histórico e pede novamente após o próximo turno.

O "[tool runner](https://platform.claude.com/docs/pt-BR/agents-and-tools/tool-use/tool-runner)" (executor de ferramentas) do SDK em Python, TypeScript, C#, Go, Java, PHP e Ruby pode enviar a solicitação de compactação por você. Quando você decidir compactar, chame `compact_before_next_turn()` (typescript, java, php: `compactBeforeNextTurn()`; csharp, go: `CompactBeforeNextTurn()`) no runner. Assim que o turno atual e suas chamadas de ferramentas terminarem, o runner envia a solicitação de compactação e substitui seu histórico pela mensagem retornada. Crie o runner com o beta `compact-2026-09-04`, porque o runner não o adiciona.

O runner monta a solicitação de compactação a partir de seus próprios parâmetros e deixa `context_management` de fora. Ele também deixa de fora `stop_sequences`, um `tool_choice` do tipo `any` ou `tool` e um `output_config.format` de saída estruturada, que a API rejeita em uma solicitação de compactação. [Solicitar um resumo](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-on-demand#request-a-summary) explica por quê. O runner os envia novamente em suas solicitações posteriores. Versões do SDK anteriores a Python 1.8.0, TypeScript 0.128.0, C# 12.50.0, Go 1.75.0 e Java 2.65.0 também os enviam na solicitação de compactação. Nessas versões, um runner que define qualquer um desses parâmetros recebe um erro 400. O runner envia um [orçamento de tarefa](https://platform.claude.com/docs/pt-BR/build-with-claude/task-budgets) sem alterações. Se `output_config.task_budget` definir `remaining`, a solicitação de compactação retorna um erro 400, então deixe `remaining` sem definir, como diz [Limites e interações com outros recursos](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-on-demand#how-it-fits-with-the-rest-of-the-api). O runner se recusa a compactar enquanto seu `context_management` tiver uma edição de compactação, então use um único tipo de compactação em um runner.

### Quando compactar

Você pode enviar uma solicitação de compactação após qualquer turno concluído, então é o seu código que decide quando.

Para estimar o tamanho da próxima solicitação, some `input_tokens` e `output_tokens` do `usage` da última resposta, como o loop faz. Com ["prompt caching" (cache de prompt)](https://platform.claude.com/docs/pt-BR/build-with-claude/prompt-caching#tracking-cache-performance), `input_tokens` conta apenas os tokens após o último ponto de interrupção de cache, então some também `cache_read_input_tokens` e `cache_creation_input_tokens`. Você também pode enviar as mesmas mensagens para o endpoint de ["token counting" (contagem de tokens)](https://platform.claude.com/docs/pt-BR/build-with-claude/token-counting).

Compare esse número com um limite que você escolher, abaixo da [janela de contexto](https://platform.claude.com/docs/pt-BR/build-with-claude/context-windows) do modelo.

## Escrever seu próprio prompt de sumarização

Sem `instructions`, a API usa seu próprio prompt de sumarização. Uma string `instructions` não vazia (de até 16.384 caracteres) substitui esse prompt por completo. Por exemplo:

```json
{
  "compaction": {
    "type": "summarize",
    "instructions": "Summarize this recipe app design conversation. Preserve every entity and field name agreed so far, and the user's latest open request. Do not call tools; respond with the summary text only."
  }
}
```

O sumarizador lê a conversa inteira, incluindo o pensamento anterior, com ou sem `instructions`. Em suas `instructions`, diga o que o resumo deve reter e instrua o modelo a não chamar ferramentas. A chamada de sumarização é executada sob as mesmas salvaguardas que qualquer outra solicitação.

## Lidar com um resumo ausente ou um erro

Um resumo é produzido somente quando a chamada de sumarização termina normalmente com texto e sem chamada de ferramenta. Caso contrário, a resposta ainda é um 200 com `content` vazio, então verifique `stop_reason` antes de procurar o bloco. A chamada ainda é cobrada e informada em `usage.iterations`, com uso zero quando nenhuma chamada pôde ser feita. O `stop_reason` é aquele com o qual a chamada de sumarização terminou. Em todos os casos, você pode continuar sem um resumo e compactar mais tarde.

| `stop_reason`                     | Causa                                                       | O que fazer                                                                 |
| --------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------- |
| `"max_tokens"`                    | O resumo foi cortado.                                       | Reenvie com um `max_tokens` maior.                                          |
| `"model_context_window_exceeded"` | Não havia espaço para o prompt de sumarização.              | Reenvie com `instructions` mais curtas ou menos mensagens.                  |
| `"tool_use"`                      | O modelo chamou uma ferramenta em vez de escrever o resumo. | Reenvie com `instructions` que digam ao modelo para não chamar ferramentas. |
| `"refusal"`                       | A solicitação foi recusada.                                 | Continue sem um resumo.                                                     |
| `"end_turn"`                      | A chamada não retornou nenhum texto.                        | Continue sem um resumo.                                                     |

A chamada de sumarização está sujeita às mesmas salvaguardas que suas outras solicitações. Após um `"refusal"`, [`stop_details`](https://platform.claude.com/docs/pt-BR/build-with-claude/handling-stop-reasons#refusal) identifica a categoria de política por trás dele.

### Erros

Uma solicitação de compactação, ou uma solicitação que carrega um bloco, também pode falhar completamente. A maioria dos erros 400 tem uma mensagem que diz o que remover ou reenviar. Alguns também trazem um `error.details.error_code` que começa com `compaction_`. Erros de parâmetro, como um campo que não pode ser combinado com `compaction`, trazem apenas a mensagem.

| Erro                                                                                                                                                                                       | Causa                                                                                            | O que fazer                                                                                                                                                                                              |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 529 `overloaded_error`, `error.details.error_code` `compaction_unavailable`                                                                                                                | Um problema transitório no servidor ao produzir um bloco, ou ao ler um que você enviou de volta. | Tente a solicitação novamente.                                                                                                                                                                           |
| 400 `compaction_block_misplaced`                                                                                                                                                           | Mensagens resumidas permanecem antes do bloco.                                                   | Remova-as, para que o bloco venha primeiro em `messages`.                                                                                                                                                |
| 400 `compaction_signature_invalid` ou `compaction_content_mismatch`                                                                                                                        | A `signature` ou o `content` do bloco foi alterado depois que a API o retornou.                  | Envie o bloco exatamente como retornado, incluindo sua `signature`.                                                                                                                                      |
| 400                                                                                                                                                                                        | A solicitação carrega mais de um bloco `compaction`.                                             | Envie exatamente um, o mais recente.                                                                                                                                                                     |
| 400                                                                                                                                                                                        | O último turno `assistant` termina em uma chamada de ferramenta ainda sem resultado.             | Envie os resultados de ferramentas desse turno e, em seguida, compacte.                                                                                                                                  |
| 400 `compaction_nothing_to_summarize`                                                                                                                                                      | `messages` não tem conteúdo `user` ou `assistant`, por exemplo, uma lista vazia.                 | Envie pelo menos uma mensagem `user` ou `assistant`.                                                                                                                                                     |
| 400 na solicitação de compactação, com uma mensagem que diz que o parâmetro `compaction` `requires anthropic-beta: compact-2026-09-04`                                                     | A solicitação de compactação deixou de fora o cabeçalho beta.                                    | Adicione o cabeçalho beta; consulte [Solicitar um resumo](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-on-demand#request-a-summary).                                              |
| 400 em uma solicitação posterior que carrega o bloco: um erro de validação que diz que `compaction` não é um dos tipos de bloco de conteúdo esperados. A mensagem não menciona o cabeçalho | Essa solicitação deixou de fora o cabeçalho beta.                                                | Adicione o cabeçalho beta a todas as solicitações que carregam o bloco; consulte [Solicitar um resumo](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-on-demand#request-a-summary). |
| Erro de validação 400, como `messages.0.content.0.compaction.citations: Extra inputs are not permitted`                                                                                    | Um bloco foi enviado de volta com campos que a API não retornou, como `citations: null`.         | Envie o bloco exatamente como retornado; consulte [Continuar a partir do resumo](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-on-demand#continue-from-the-summary).               |

## Contabilizar o uso da compactação

A chamada de sumarização é cobrada e sujeita a "rate limits" (limites de taxa) como qualquer outra solicitação, e `usage.iterations` a informa como a entrada `compaction`. Os `input_tokens` e `output_tokens` de nível superior são zero porque nenhuma resposta foi gerada. Para contabilizar o que uma conversa consumiu, some os valores ao longo de `usage.iterations`, e não os campos de nível superior. Enviar um bloco de volta em solicitações posteriores não adiciona custo de compactação.

Você tem um loop funcional que compacta uma conversa e lida com um resumo ausente. Duas páginas mudam a forma como ele é executado, e você pode combiná-las: [Compactação que mantém turnos recentes](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-keep-recent-turns) mantém os últimos turnos palavra por palavra, e [Compactação em segundo plano](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-background) permite que a conversa continue enquanto o resumo é escrito. [Compactação e pensamento preservado](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-thinking-blocks) se aplica se você enviar blocos de pensamento de volta e fizer qualquer uma das duas coisas.

## Limites e interações com outros recursos

* **Compactação por limite e edição de contexto.** Você não pode enviar `compaction` e `context_management` na mesma solicitação. A compactação por limite (`compact_20260112`) não pode ser executada em uma solicitação que carrega um bloco assinado.
* **Cache de prompt.** `cache_control` no bloco coloca um ponto de interrupção após o resumo.
* **Mensagens de sistema e alterações de ferramentas no meio da conversa.** Mensagens `role: "system"` dentro do intervalo resumido também são resumidas, então suas instruções em texto deixam de se aplicar assim que o bloco as substitui. Um nível de [esforço por mensagem](https://platform.claude.com/docs/pt-BR/build-with-claude/effort#change-effort-mid-conversation-beta) que elas definam também não é mantido: até que uma mensagem posterior defina um nível, os turnos são executados com o `output_config.effort` de nível superior da solicitação, ou com o padrão do modelo se você não definir um. Se uma instrução ou nível de esforço ainda importar, declare-o novamente em uma mensagem `role: "system"`. Envie essa mensagem logo após seu próximo novo turno `user` e mantenha-a em seu histórico a partir de então. Para [alterações de ferramentas](https://platform.claude.com/docs/pt-BR/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes), e para saber onde essa mensagem fica quando você mantém turnos após o bloco, consulte [Alterar o prompt do sistema ou as ferramentas](https://platform.claude.com/docs/pt-BR/build-with-claude/compaction-thinking-blocks#change-the-system-prompt-or-tools).
* **Orçamentos de tarefa.** Não envie o valor `remaining` de um [orçamento de tarefa](https://platform.claude.com/docs/pt-BR/build-with-claude/task-budgets) (`output_config.task_budget.remaining`) com `compaction` ou em solicitações que carregam o bloco. Fazer isso retorna um erro 400.
* **Contagem de tokens.** O endpoint de [contagem de tokens](https://platform.claude.com/docs/pt-BR/build-with-claude/token-counting) ignora o parâmetro `compaction`.
* **Conteúdo que o resumo não consegue carregar.** Imagens, documentos, blocos `container_upload` e URLs buscadas dentro das mensagens resumidas desaparecem quando o bloco as substitui. Reafirme ou reenvie qualquer coisa de que um turno posterior ainda precise.
