---
title: Сжатие по запросу
url: https://platform.claude.com/docs/ru/build-with-claude/compaction-on-demand
description: Попросите Claude составить сводку разговора в момент, выбранный вашим приложением, а затем продолжите работу с этой сводки.
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
---

При использовании «on-demand compaction» (сжатие по запросу) ваше приложение само решает, когда разговор будет кратко изложен: вы отправляете один запрос с параметром `compaction`, и Claude возвращает «summary» (сводку) вместо ответа.

## Как работает сжатие по запросу

Запрос на сжатие отделён от ходов вашего разговора. Вы отправляете разговор в его текущем виде с параметром `compaction`, и ответ содержит единственный блок `compaction`. Блок содержит сводку в виде текста, который вы можете прочитать, и подпись. Отправляйте его в последующих запросах точно в том виде, в котором он пришёл.

С этого момента блок занимает место сообщений, которые он обобщает. Он идёт первым в `messages`, обобщённые сообщения удаляются, а ваш следующий ход следует за ним. Claude видит сводку там, где были эти сообщения.

<Frame>
  ![On-demand compaction (сжатие по запросу): запрос, содержащий четыре сообщения и параметр compaction, возвращает один блок compaction и никакого ответа; в следующем запросе блок идёт первым в messages вместо этих четырёх сообщений, а за ним следует следующий ход пользователя](https://platform.claude.com/docs/ru/images/compaction-on-demand-swap.svg)
</Frame>

## Запрос сводки

Отправляйте бета-заголовок `compact-2026-09-04` в запросе, который запрашивает сводку, и в каждом последующем запросе, содержащем подписанный блок. Чтобы проверить, поддерживает ли модель сжатие по запросу, вызовите [Models API](https://platform.claude.com/docs/ru/api/beta/models/list) с бета-заголовком и прочитайте `capabilities.compaction` каждой модели. Нельзя сочетать `compaction` с `context_management` в одном запросе.

Отправьте разговор в его текущем виде с `"compaction": {"type": "summarize"}`. API один раз обобщает все сообщения в запросе, не генерирует после этого ответа и возвращает только блок со `stop_reason` `"compaction"`. Отправляйте ту же «system prompt» (системную подсказку) `system` и те же `tools`, которые вы используете в остальной части разговора. Модуль обобщения читает их, и если вы сохраняете ходы после блока на модели с [сохранёнными размышлениями](https://platform.claude.com/docs/ru/build-with-claude/preserved-thinking), размышления в этих ходах остаются действительными, только если `system` и `tools` совпадают. В разговоре из этого примера нет системной подсказки `system` и инструментов, поэтому запрос не отправляет ни того, ни другого:

<CodeGroup>
  ```bash cURL
  # max_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 ограничивает весь вызов, включая размышления, поэтому выделите несколько тысяч токенов.
  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 ограничивает весь вызов, включая размышления, поэтому выделите несколько тысяч токенов.
      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 ограничивает весь вызов, включая размышления, поэтому выделите несколько тысяч токенов.
    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 ограничивает весь вызов, включая размышления, поэтому выделите несколько тысяч токенов.
      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 ограничивает весь вызов, включая размышления, поэтому выделите несколько тысяч токенов.
  	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 ограничивает весь вызов, включая размышления, поэтому выделите несколько тысяч токенов.
          .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 ограничивает весь вызов, включая размышления, поэтому выделите несколько тысяч токенов.
      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 ограничивает весь вызов, включая размышления, поэтому выделите несколько тысяч токенов.
    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 }]
  }
}
```

Вызов обобщения использует модель запроса, `system`, `tools`, настройки размышлений и `max_tokens`. Модуль обобщения читает определения инструментов, но никогда не запускает инструменты, а ответ не содержит размышлений. `max_tokens` ограничивает весь вызов, включая любые размышления модели перед написанием сводки, поэтому выделите несколько тысяч токенов. В разделе [Подсчёт использования при сжатии](https://platform.claude.com/docs/ru/build-with-claude/compaction-on-demand#understanding-usage) показано, как тарифицируется этот вызов.

Если последний ход `assistant` заканчивается вызовом инструмента, для которого ещё нет результата, API отклоняет запрос. Сначала отправьте результаты инструментов для этого хода. Также не указывайте `stop_sequences`, `output_config.format` для структурированного вывода и `tool_choice` типа `any` или `tool`. В вызове обобщения они ничего бы не делали, и API их отклоняет. Разговор по-прежнему должен помещаться в «context window» (контекстное окно) модели, поэтому выполняйте сжатие до того, как превысите его, а не после.

При «streaming» (потоковой передаче) ответа блок приходит целиком. Вы получаете одно событие `content_block_start`, содержащее полный блок, затем `content_block_stop`, без событий `content_block_delta`. События `ping` могут приходить до них или между ними.

## Продолжение со сводки

В вашей истории замените отправленные сообщения возвращённым сообщением ассистента. Сохраняйте блок `compaction` точно в том виде, в котором его вернул API, включая его `signature`. Любые ходы, сделанные после отправки запроса на сжатие, следуют за блоком без изменений — на этом основано [Сжатие в фоновом режиме](https://platform.claude.com/docs/ru/build-with-claude/compaction-background). Отправляйте блок первым в каждом последующем запросе вместе с бета-заголовком:

```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." }
  ]
}
```

Этот пример продолжает пример запроса, который заканчивался ходом `user`; на диаграмме показан более простой случай, когда во время написания сводки ходы не делаются. Здесь второе сообщение `assistant` — это ответ на последний обобщённый ход `user`. Он пришёл, пока писалась сводка, поэтому не вошёл в число обобщённых сообщений. Два сообщения `assistant` подряд здесь допустимы, потому что блок по-прежнему идёт первым.

API помещает сводку туда, где стоит блок, и передаёт Claude все последующие сообщения без изменений. Соблюдайте следующие правила:

* Помещайте блок первым в `messages` — либо как отдельное сообщение `assistant`, либо как первый блок содержимого первого сообщения, будь то сообщение `user` или `assistant`.
* Удаляйте обобщённые сообщения. Если какие-либо из них остаются перед блоком, запрос возвращает ошибку 400 (`compaction_block_misplaced`).
* Отправляйте ровно один блок `compaction` на запрос, в каждом последующем запросе.

<Warning>
  Две ошибки при замене не вызывают сообщения об ошибке. Если обобщённые сообщения остаются после блока, API снова отправляет их Claude. Если последующий запрос не содержит блока, Claude не получает сводку.
</Warning>

Сжатие по порогу работает наоборот: его блок следует за сообщениями, которые он обобщает, и API удаляет их за вас. См. [Обратная передача блоков сжатия](https://platform.claude.com/docs/ru/build-with-claude/compaction-threshold#passing-compaction-blocks-back).

В Python используйте `client.beta.messages`, как это делают примеры на этой странице. Если вы вызываете `client.messages` и сериализуете блоки самостоятельно, используйте `to_dict()` или `model_dump(exclude_none=True)`: обычный `model_dump()` добавляет к блоку `citations: null` и `text: null`, и API его отклоняет.

Если вы сохраняете ходы после блока и отправляете их блоки размышлений обратно, условия, при которых эти размышления остаются действительными, описаны на странице [Сжатие и сохранённые размышления](https://platform.claude.com/docs/ru/build-with-claude/compaction-thinking-blocks).

### Повторное сжатие

Чтобы сжать разговор, который уже начинается с блока, снова отправьте `compaction`. Новый блок обобщает старую сводку и всё, что идёт после неё. С этого момента отправляйте только самый новый блок.

## Сжатие в цикле

После каждого хода цикл складывает входные и выходные токены последнего ответа, потому что следующий запрос отправляет и этот ответ. Когда эта сумма превышает лимит и впереди ещё есть ход, цикл отправляет запрос на сжатие с той же моделью и системной подсказкой `system`, проверяет `stop_reason`, заменяет свою историю возвращённым сообщением и выводит ход, перед которым было выполнено сжатие. Лимит в 2 500 токенов в примере намеренно занижен, чтобы сжатие происходило даже в коротком разговоре. Установите свой лимит близко к вашему реальному бюджету входных данных.

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

  client = anthropic.Anthropic()

  # Задайте значение, близкое к реальному бюджету входных токенов. Здесь оно занижено, чтобы сжатие сработало даже в коротком диалоге.
  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})

      # Следующий запрос тоже отправит этот ответ, поэтому учитывайте его.
      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();

  // Задайте значение, близкое к вашему реальному бюджету входных токенов. Здесь оно занижено, чтобы сжатие сработало даже в коротком диалоге.
  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 });

    // Следующий запрос тоже отправит этот ответ, поэтому учитывайте его.
    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();

  // Задайте значение, близкое к реальному бюджету входных токенов. Здесь оно занижено, чтобы сжимался даже короткий диалог.
  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(),
      });

      // Следующий запрос тоже отправит этот ответ, поэтому учитывайте его.
      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()

  // Задайте значение, близкое к вашему реальному бюджету входных токенов. Здесь оно занижено, чтобы сжатие сработало даже в коротком диалоге.
  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())

  	// Следующий запрос тоже отправит этот ответ, поэтому учитывайте его.
  	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;

  // Задайте значение, близкое к вашему реальному бюджету входных токенов. Здесь оно занижено, чтобы сжатие сработало даже в коротком диалоге.
  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());

          // Следующий запрос тоже отправит этот ответ, поэтому учитывайте его.
          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();

  // Задайте значение, близкое к реальному бюджету входных токенов. Здесь оно занижено, чтобы сжимался даже короткий диалог.
  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);

      // Следующий запрос тоже отправит этот ответ, поэтому учитывайте его.
      $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

  # Задайте значение, близкое к вашему реальному бюджету входных токенов. Здесь оно занижено, чтобы сжатие сработало даже в коротком диалоге.
  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 }

    # Следующий запрос тоже отправит этот ответ, поэтому учитывайте его.
    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>

Проверка `stop_reason` выполняется до того, как код ищет блок; причина объясняется в разделе [Обработка отсутствующей сводки или ошибки](https://platform.claude.com/docs/ru/build-with-claude/compaction-on-demand#when-no-summary-comes-back). История заменяется, а не дополняется: возвращённое сообщение заменяет все сообщения, которые содержал запрос, по правилам из раздела [Продолжение со сводки](https://platform.claude.com/docs/ru/build-with-claude/compaction-on-demand#continue-from-the-summary). Если сводка не возвращается, цикл сохраняет свою историю и повторяет запрос после следующего хода.

[«Tool runner» (исполнитель инструментов)](https://platform.claude.com/docs/ru/agents-and-tools/tool-use/tool-runner) в SDK для Python, TypeScript, C#, Go, Java, PHP и Ruby может отправить запрос на сжатие за вас. Когда вы решите выполнить сжатие, вызовите у исполнителя `compact_before_next_turn()` (typescript, java, php: `compactBeforeNextTurn()`; csharp, go: `CompactBeforeNextTurn()`). Как только текущий ход и его вызовы инструментов завершатся, исполнитель отправит запрос на сжатие и заменит свою историю возвращённым сообщением. Создавайте исполнитель с бета-версией `compact-2026-09-04`, потому что сам исполнитель её не добавляет.

Исполнитель формирует запрос на сжатие из собственных параметров и не включает в него `context_management`. Он также не включает `stop_sequences`, `tool_choice` типа `any` или `tool` и `output_config.format` для структурированного вывода, которые API отклоняет в запросе на сжатие. Причина объясняется в разделе [Запрос сводки](https://platform.claude.com/docs/ru/build-with-claude/compaction-on-demand#request-a-summary). В последующих запросах исполнитель снова отправляет их. Версии SDK до Python 1.8.0, TypeScript 0.128.0, C# 12.50.0, Go 1.75.0 и Java 2.65.0 отправляют их и в запросе на сжатие. В этих версиях исполнитель, задающий любой из этих параметров, получает ошибку 400. Исполнитель отправляет [бюджет задачи](https://platform.claude.com/docs/ru/build-with-claude/task-budgets) без изменений. Если `output_config.task_budget` задаёт `remaining`, запрос на сжатие возвращает ошибку 400, поэтому не задавайте `remaining`, как указано в разделе [Ограничения и взаимодействие с другими функциями](https://platform.claude.com/docs/ru/build-with-claude/compaction-on-demand#how-it-fits-with-the-rest-of-the-api). Исполнитель отказывается выполнять сжатие, пока его `context_management` содержит правку сжатия, поэтому используйте в одном исполнителе только один вид сжатия.

### Когда выполнять сжатие

Вы можете отправить запрос на сжатие после любого завершённого хода, поэтому момент определяет ваш код.

Чтобы оценить размер следующего запроса, сложите `input_tokens` и `output_tokens` из `usage` последнего ответа, как это делает цикл. При использовании [«prompt caching» (кэширования подсказок)](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching#tracking-cache-performance) `input_tokens` учитывает только токены после последней точки останова кэша, поэтому также прибавьте `cache_read_input_tokens` и `cache_creation_input_tokens`. Вы также можете отправить те же сообщения в конечную точку [подсчёта токенов](https://platform.claude.com/docs/ru/build-with-claude/token-counting).

Сравните это число с выбранным вами лимитом, который меньше [контекстного окна](https://platform.claude.com/docs/ru/build-with-claude/context-windows) модели.

## Написание собственной подсказки для обобщения

Без `instructions` API использует собственную подсказку для обобщения. Непустая строка `instructions` (до 16 384 символов) полностью заменяет эту подсказку. Например:

```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."
  }
}
```

Модуль обобщения читает весь разговор, включая предыдущие размышления, независимо от наличия `instructions`. В своих `instructions` укажите, что должна сохранить сводка, и скажите модели не вызывать инструменты. Вызов обобщения выполняется с теми же мерами защиты, что и любой другой запрос.

## Обработка отсутствующей сводки или ошибки

Сводка создаётся только тогда, когда вызов обобщения завершается нормально с текстом и без вызова инструмента. В противном случае ответ всё равно имеет код 200 с пустым `content`, поэтому проверяйте `stop_reason`, прежде чем искать блок. Вызов всё равно тарифицируется и отражается в `usage.iterations`, с нулевым использованием, если вызов выполнить не удалось. `stop_reason` — это причина, с которой завершился вызов обобщения. В любом случае вы можете продолжить без сводки и выполнить сжатие позже.

| `stop_reason`                     | Причина                                            | Что делать                                                                             |
| --------------------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `"max_tokens"`                    | Сводка была обрезана.                              | Отправьте повторно с большим значением `max_tokens`.                                   |
| `"model_context_window_exceeded"` | Не хватило места для подсказки для обобщения.      | Отправьте повторно с более короткими `instructions` или меньшим количеством сообщений. |
| `"tool_use"`                      | Модель вызвала инструмент вместо написания сводки. | Отправьте повторно с `instructions`, которые запрещают модели вызывать инструменты.    |
| `"refusal"`                       | Запрос был отклонён.                               | Продолжайте без сводки.                                                                |
| `"end_turn"`                      | Вызов не вернул текста.                            | Продолжайте без сводки.                                                                |

На вызов обобщения распространяются те же меры защиты, что и на другие ваши запросы. После `"refusal"` поле [`stop_details`](https://platform.claude.com/docs/ru/build-with-claude/handling-stop-reasons#refusal) указывает категорию политики, ставшую причиной отказа.

### Ошибки

Запрос на сжатие или запрос, содержащий блок, также может завершиться ошибкой. У большинства ошибок 400 есть сообщение, в котором сказано, что нужно удалить или отправить повторно. Некоторые также содержат `error.details.error_code`, начинающийся с `compaction_`. Ошибки параметров, например поле, которое нельзя сочетать с `compaction`, содержат только сообщение.

| Ошибка                                                                                                                                                                               | Причина                                                                                       | Что делать                                                                                                                                                                                        |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 529 `overloaded_error`, `error.details.error_code` `compaction_unavailable`                                                                                                          | Временная проблема на сервере при создании блока или при чтении отправленного вами блока.     | Повторите запрос.                                                                                                                                                                                 |
| 400 `compaction_block_misplaced`                                                                                                                                                     | Перед блоком остаются обобщённые сообщения.                                                   | Удалите их, чтобы блок шёл первым в `messages`.                                                                                                                                                   |
| 400 `compaction_signature_invalid` или `compaction_content_mismatch`                                                                                                                 | `signature` или `content` блока были изменены после того, как API его вернул.                 | Отправляйте блок точно в том виде, в котором он был возвращён, включая его `signature`.                                                                                                           |
| 400                                                                                                                                                                                  | Запрос содержит более одного блока `compaction`.                                              | Отправляйте ровно один — самый новый.                                                                                                                                                             |
| 400                                                                                                                                                                                  | Последний ход `assistant` заканчивается вызовом инструмента, для которого ещё нет результата. | Отправьте результаты инструментов для этого хода, затем выполните сжатие.                                                                                                                         |
| 400 `compaction_nothing_to_summarize`                                                                                                                                                | `messages` не содержит содержимого `user` или `assistant`, например это пустой список.        | Отправьте хотя бы одно сообщение `user` или `assistant`.                                                                                                                                          |
| 400 на запрос сжатия с сообщением о том, что параметр `compaction` `requires anthropic-beta: compact-2026-09-04`                                                                     | В запросе на сжатие отсутствует бета-заголовок.                                               | Добавьте бета-заголовок; см. [Запрос сводки](https://platform.claude.com/docs/ru/build-with-claude/compaction-on-demand#request-a-summary).                                                       |
| 400 на последующий запрос, содержащий блок: ошибка валидации, сообщающая, что `compaction` не является одним из ожидаемых типов блоков содержимого. Сообщение не упоминает заголовок | В этом запросе отсутствует бета-заголовок.                                                    | Добавьте бета-заголовок в каждый запрос, содержащий блок; см. [Запрос сводки](https://platform.claude.com/docs/ru/build-with-claude/compaction-on-demand#request-a-summary).                      |
| 400, ошибка валидации, например `messages.0.content.0.compaction.citations: Extra inputs are not permitted`                                                                          | Блок был отправлен обратно с полями, которые API не возвращал, например `citations: null`.    | Отправляйте блок точно в том виде, в котором он был возвращён; см. [Продолжение со сводки](https://platform.claude.com/docs/ru/build-with-claude/compaction-on-demand#continue-from-the-summary). |

## Подсчёт использования при сжатии

Вызов обобщения тарифицируется и подпадает под «rate limit» (ограничение скорости) так же, как любой другой запрос, а `usage.iterations` отражает его как запись `compaction`. Поля верхнего уровня `input_tokens` и `output_tokens` равны нулю, потому что ответ не генерировался. Чтобы подсчитать, сколько потребил разговор, суммируйте значения по `usage.iterations`, а не поля верхнего уровня. Отправка блока обратно в последующих запросах не добавляет затрат на сжатие.

Теперь у вас есть работающий цикл, который сжимает разговор и обрабатывает отсутствие сводки. Две страницы описывают изменения в его работе, и их можно сочетать: [Сжатие с сохранением последних ходов](https://platform.claude.com/docs/ru/build-with-claude/compaction-keep-recent-turns) сохраняет последние ходы дословно, а [Сжатие в фоновом режиме](https://platform.claude.com/docs/ru/build-with-claude/compaction-background) позволяет разговору продолжаться, пока пишется сводка. Страница [Сжатие и сохранённые размышления](https://platform.claude.com/docs/ru/build-with-claude/compaction-thinking-blocks) актуальна, если вы отправляете блоки размышлений обратно и используете любой из этих вариантов.

## Ограничения и взаимодействие с другими функциями

* **Сжатие по порогу и редактирование контекста.** Нельзя отправлять `compaction` и `context_management` в одном запросе. Сжатие по порогу (`compact_20260112`) не может выполняться в запросе, содержащем подписанный блок.
* **Кэширование подсказок.** `cache_control` на блоке устанавливает точку останова после сводки.
* **Системные сообщения и изменения инструментов в середине разговора.** Сообщения `role: "system"` внутри обобщаемого диапазона тоже включаются в сводку, поэтому их текстовые инструкции перестают действовать, как только блок их заменяет. Заданный ими [уровень усилий для отдельного сообщения](https://platform.claude.com/docs/ru/build-with-claude/effort#change-effort-mid-conversation-beta) также не переносится: пока более позднее сообщение не задаст уровень, ходы выполняются с `output_config.effort` верхнего уровня запроса или со значением модели по умолчанию, если вы его не задали. Если инструкция или уровень усилий по-прежнему важны, укажите их снова в сообщении `role: "system"`. Отправьте это сообщение сразу после вашего следующего нового хода `user` и оставляйте его в истории с этого момента. Об [изменениях инструментов](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes), а также о том, куда помещать это сообщение, если вы сохраняете ходы после блока, см. [Изменение системной подсказки или инструментов](https://platform.claude.com/docs/ru/build-with-claude/compaction-thinking-blocks#change-the-system-prompt-or-tools).
* **Бюджеты задач.** Не отправляйте значение `remaining` [бюджета задачи](https://platform.claude.com/docs/ru/build-with-claude/task-budgets) (`output_config.task_budget.remaining`) вместе с `compaction` или в запросах, содержащих блок. Это приводит к ошибке 400.
* **Подсчёт токенов.** Конечная точка [подсчёта токенов](https://platform.claude.com/docs/ru/build-with-claude/token-counting) игнорирует параметр `compaction`.
* **Содержимое, которое сводка не может передать.** Изображения, документы, блоки `container_upload` и загруженные URL внутри обобщённых сообщений исчезают, как только блок их заменяет. Повторите или загрузите заново всё, что ещё понадобится в последующих ходах.
