---
title: Системные сообщения и изменения инструментов в середине разговора
url: https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages
description: Изменяйте системные инструкции или доступность инструментов в ходе разговора, не делая недействительным кэшированный префикс, который им предшествовал.
---

<Note>
  Чтобы узнать, как «zero data retention» (нулевое хранение данных), или ZDR, применяется к этой функции, см. раздел [API и хранение данных](https://platform.claude.com/docs/ru/manage-claude/api-and-data-retention).
</Note>

Системные инструкции обычно находятся в поле верхнего уровня `system`, перед всеми сообщениями разговора. Это положение отлично подходит для «prompt caching» ([кэширования подсказок](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching)): системная подсказка является частью стабильного префикса, поэтому последующие ходы попадают в кэш. Это плохое положение для инструкций, необходимость в которых вы обнаруживаете только в середине сессии, потому что редактирование поля верхнего уровня `system` изменяет самое начало подсказки и делает кэш недействительным для всего, что следует за ним.

Системные сообщения в середине разговора закрывают этот пробел. Вы добавляете сообщение `{"role": "system"}` в той точке разговора, где новая инструкция становится актуальной, вместо того чтобы редактировать поле верхнего уровня `system`. Кэшированный префикс остаётся прежним, поэтому следующий запрос по-прежнему читает его из кэша, а новая инструкция по-прежнему применяется как системная инструкция, а не как обычный пользовательский текст.

<Note>
  Системные сообщения в середине разговора доступны в Claude API, [Claude в Amazon Bedrock](https://platform.claude.com/docs/ru/build-with-claude/claude-in-amazon-bedrock) и [Google Cloud](https://platform.claude.com/docs/ru/build-with-claude/claude-on-vertex-ai).

  Эта функция доступна в Claude Fable 5.1, [Claude Mythos 5.1](https://platform.claude.com/docs/ru/models/mythos-5-1/overview), Claude Fable 5, [Claude Mythos 5](https://platform.claude.com/docs/ru/models/mythos-5/overview), Claude Opus 5.5, Claude Opus 4.8, Claude Opus 5, Claude Sonnet 5.5 и Claude Haiku 5.5. Для системных сообщений в середине разговора «beta header» (бета-заголовок) не требуется. Эта функция недоступна в Claude Sonnet 5. Вместо неё используйте там поле верхнего уровня `system`.

  [Изменения инструментов в середине диалога](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes) находятся в бета-версии на тех же моделях. В Claude API отправляйте бета-заголовок `inline-tools-2026-09-15`, который также охватывает [определение инструмента внутри блока `tool_addition`](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta). Для [добавления таким способом сервера «Model Context Protocol», или MCP,](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages#add-an-mcp-server-mid-conversation-beta) нужен второй бета-заголовок, `mcp-client-2026-09-15`, который доступен в Claude API. Заголовок `mid-conversation-tool-changes-2026-07-01` работает для изменений, указывающих инструмент по ссылке, в Claude API, Amazon Bedrock и Google Cloud.

  [Системные сообщения, ограниченные ходом](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) (`clear_at`), находятся в бета-версии и требуют бета-заголовка `mid-conversation-system-clear-at-2026-08-21`, на тех же моделях и платформах, что и системные сообщения в середине разговора.
</Note>

## Изменения инструментов в середине разговора

Массив `tools` находится в хэшируемом префиксе запроса даже раньше, чем поле верхнего уровня `system`, поэтому его редактирование делает недействительным [кэш подсказок](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching) для всего диалога. Изменения инструментов в середине диалога — это аналог системных сообщений в середине диалога для инструментов. Вместо того чтобы фиксировать список инструментов на всё время существования диалога, вы меняете набор инструментов, предлагаемых модели, между ходами: заранее объявите полный набор инструментов в `tools`, а затем используйте блоки `tool_addition` и `tool_removal`, чтобы предложить инструмент модели или отозвать его начиная с определённой точки диалога. Сам массив `tools` никогда не меняется, поэтому кэшированный префикс остаётся нетронутым. Изменения инструментов в середине диалога находятся в бета-версии и используют бета-заголовок `inline-tools-2026-09-15` в Claude API.

`tool_addition` и `tool_removal` — это блоки содержимого в массиве `content` сообщения `role: "system"`, и их можно сочетать с блоками `text` в одном сообщении. Сообщение подчиняется правилам размещения для любого системного сообщения в середине диалога, с одним дополнительным ограничением после приостановленного хода (см. [Ограничения](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages#limitations)), а изменение применяется начиная с этой точки диалога. Поле `tool` каждого блока ссылается на инструмент, а не определяет его: `{"type": "tool_reference", "name": "..."}` указывает инструмент, объявленный в массиве `tools` запроса, а на инструменты [MCP connector](https://platform.claude.com/docs/ru/agents-and-tools/mcp-connector) можно ссылаться по отдельности с помощью `mcp_tool_reference` (`server_name` и `name`) или как на целый набор инструментов с помощью `mcp_toolset_reference` (`server_name`). Ссылка на имя, не объявленное в `tools`, возвращает ошибку 400 (в Claude API — с `error.details.error_code`, равным `tool_reference_unresolved`). Вместо этого блок `tool_addition` может [содержать полное определение инструмента](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta), что не поддерживается заголовком `mid-conversation-tool-changes-2026-07-01`.

Каждый инструмент, объявленный в `tools`, предлагается модели с начала разговора. Исключение — инструменты, объявленные с `defer_loading: true`: они скрыты, пока блок `tool_addition` не сделает их доступными. `tool_addition` также снова предлагает инструмент, отозванный ранее блоком `tool_removal`.

Следующий запрос объявляет `get_weather` в `tools`, а затем отзывает его после первого хода пользователя с помощью блока `tool_removal`. Запрос отправляет бета-заголовок `inline-tools-2026-09-15`.

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

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

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

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      betas=["inline-tools-2026-09-15"],
      # Полный набор инструментов объявляется заранее и не меняется, поэтому
      # кэшированный префикс остаётся нетронутым.
      tools=[
          {
              "name": "get_weather",
              "description": "Get the current weather for a location.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string", "description": "City name"},
                  },
                  "required": ["location"],
              },
          },
      ],
      messages=[
          {
              "role": "user",
              "content": "Say OK.",
          },
          # Отзываем get_weather начиная с этого места. Блок ссылается
          # на инструмент по имени, а не изменяет `tools`, поэтому прежние ходы остаются
          # побайтово идентичными и кэш по-прежнему срабатывает.
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_removal",
                      "tool": {"type": "tool_reference", "name": "get_weather"},
                  },
              ],
          },
      ],
  )

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

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

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    betas: ["inline-tools-2026-09-15"],
    // Полный набор инструментов объявляется заранее и никогда не меняется, поэтому
    // кэшированный префикс остаётся нетронутым.
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: {
              type: "string",
              description: "City name"
            }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "Say OK." },
      // С этого момента отзываем get_weather. Блок ссылается на
      // инструмент по имени, а не изменяет `tools`, поэтому предыдущие ходы остаются
      // побайтово идентичными, и попадание в кэш сохраняется.
      {
        role: "system",
        content: [
          {
            type: "tool_removal",
            tool: { type: "tool_reference", name: "get_weather" }
          }
        ]
      }
    ]
  });

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

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

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Betas = [AnthropicBeta.InlineTools2026_09_15],
      // Полный набор инструментов объявляется заранее и не меняется, поэтому
      // кэшированный префикс остаётся нетронутым.
      Tools =
      [
          new BetaTool
          {
              Name = "get_weather",
              Description = "Get the current weather for a location.",
              InputSchema = new InputSchema
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["location"] = JsonSerializer.SerializeToElement(new { type = "string", description = "City name" }),
                  },
                  Required = ["location"],
              },
          },
      ],
      Messages =
      [
          new() { Role = Role.User, Content = "Say OK." },
          // С этого момента отзываем get_weather. Блок ссылается
          // на инструмент по имени, а не изменяет `Tools`, поэтому предыдущие ходы остаются
          // побайтово идентичными, и попадание в кэш сохраняется.
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolRemovalBlock
                  {
                      Tool = new BetaToolChangeToolReference { Name = "get_weather" },
                  },
              ]),
          },
      ],
  });

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

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

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaInlineTools2026_09_15},
  	// Полный набор инструментов объявляется заранее и не меняется, поэтому
  	// кэшированный префикс остаётся неизменным.
  	Tools: []anthropic.BetaToolUnionParam{
  		{OfTool: &anthropic.BetaToolParam{
  			Name:        "get_weather",
  			Description: anthropic.String("Get the current weather for a location."),
  			InputSchema: anthropic.BetaToolInputSchemaParam{
  				Properties: map[string]any{
  					"location": map[string]any{
  						"type":        "string",
  						"description": "City name",
  					},
  				},
  				Required: []string{"location"},
  			},
  		}},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Say OK.")),
  		// С этого момента отзываем get_weather. Блок ссылается
  		// на инструмент по имени, а не изменяет Tools, поэтому предыдущие ходы остаются
  		// побайтово идентичными и попадание в кэш сохраняется.
  		{
  			Role: anthropic.BetaMessageParamRoleSystem,
  			Content: []anthropic.BetaContentBlockParamUnion{
  				anthropic.NewBetaToolRemovalBlock(anthropic.BetaToolChangeToolReferenceParam{
  					Name: "get_weather",
  				}),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

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

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

      // Полный набор инструментов объявляется заранее и не меняется, поэтому
      // кэшированный префикс остаётся нетронутым.
      BetaTool weatherTool = BetaTool.builder()
          .name("get_weather")
          .description("Get the current weather for a location.")
          .inputSchema(BetaTool.InputSchema.builder()
              .properties(BetaTool.InputSchema.Properties.builder()
                  .putAdditionalProperty("location", JsonValue.from(Map.of(
                      "type", "string",
                      "description", "City name")))
                  .build())
              .addRequired("location")
              .build())
          .build();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addBeta(AnthropicBeta.INLINE_TOOLS_2026_09_15)
          .addTool(weatherTool)
          .addUserMessage("Say OK.")
          // С этого момента отзываем get_weather. Блок ссылается
          // на инструмент по имени, а не изменяет `tools`, поэтому предыдущие ходы остаются
          // побайтово идентичными, и попадание в кэш сохраняется.
          .addMessage(BetaMessageParam.builder()
              .role(BetaMessageParam.Role.SYSTEM)
              .contentOfBetaContentBlockParams(List.of(
                  BetaContentBlockParam.ofToolRemoval(BetaRequestToolRemovalBlock.builder()
                      .referenceTool("get_weather")
                      .build())))
              .build())
          .build();

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

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

  $client = new Client();

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      betas: [AnthropicBeta::INLINE_TOOLS_2026_09_15],
      // Полный набор инструментов объявляется заранее и не меняется, поэтому
      // кэшированный префикс остаётся нетронутым.
      tools: [
          [
              'name' => 'get_weather',
              'description' => 'Get the current weather for a location.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'location' => [
                          'type' => 'string',
                          'description' => 'City name',
                      ],
                  ],
                  'required' => ['location'],
              ],
          ],
      ],
      messages: [
          ['role' => 'user', 'content' => 'Say OK.'],
          // С этого момента отзываем get_weather. Блок ссылается
          // на инструмент по имени, а не изменяет `tools`, поэтому предыдущие ходы остаются
          // побайтово идентичными, и попадание в кэш сохраняется.
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_removal',
                      'tool' => ['type' => 'tool_reference', 'name' => 'get_weather'],
                  ],
              ],
          ],
      ],
  );

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

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

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    max_tokens: 1024,
    betas: [Anthropic::AnthropicBeta::INLINE_TOOLS_2026_09_15],
    # Полный набор инструментов объявляется заранее и не меняется, поэтому
    # кэшированный префикс остаётся нетронутым.
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "Say OK." },
      # Отзываем get_weather начиная с этого места. Блок ссылается
      # на инструмент по имени, а не изменяет `tools`, поэтому прежние ходы
      # остаются побайтово идентичными и кэш по-прежнему срабатывает.
      {
        role: "system",
        content: [
          {
            type: "tool_removal",
            tool: { type: "tool_reference", name: "get_weather" }
          }
        ]
      }
    ]
  )

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

### Определение инструментов в сообщении (бета)

С бета-заголовком `inline-tools-2026-09-15` блок `tool_addition` может определять инструмент по значению, то есть содержать его полное определение вместо ссылки. Так можно ввести инструмент, неизвестный в начале разговора или со схемой, которая меняется позже: достаточно добавить сообщение `role: "system"`. Массив `tools` и все предыдущие сообщения остаются точно такими, какими были отправлены. Поэтому кэш подсказок по-прежнему срабатывает, и как новые входные данные обрабатывается только добавленное сообщение. Единственное исключение — массив `tools` без неотложенных инструментов — описано в правилах ниже. Этот заголовок также охватывает добавление и удаление инструментов по ссылке, поэтому отправлять ещё и `mid-conversation-tool-changes-2026-07-01` не нужно.

Оберните определение в объект `tool` типа `tool_definition`. `definition` — это элемент `tools` с его обычной конфигурацией, включая `cache_control` и `defer_loading`. Это может быть, например, пользовательский инструмент или определённый Anthropic клиентский или серверный инструмент. Во время бета-периода некоторые типы инструментов (в том числе инструмент computer use) пока нельзя определить в сообщении: для них возвращается ошибка 400 с соответствующим пояснением. Объявляйте такие инструменты в `tools` и добавляйте по ссылке. Например, чтобы определить пользовательский инструмент в середине разговора:

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

Начиная с этой позиции модель может вызывать инструмент так же, как инструмент, объявленный в `tools`. Повторная отправка идентичного определения ничего не меняет, поэтому клиент может безопасно отправить его снова, например при повторной попытке.

Следующий запрос сохраняет `get_weather` в `tools` и определяет `db_query` после первого хода пользователя:

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

  ```bash CLI
  ant beta:messages create --beta inline-tools-2026-09-15 <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  # Оставьте в `tools` хотя бы один неотложенный инструмент, чтобы инструмент, определённый
  # позже, не менял начало сформированной подсказки.
  tools:
    - name: get_weather
      description: Get the current weather for a location.
      input_schema:
        type: object
        properties:
          location:
            type: string
            description: City name
        required:
          - location
  messages:
    - role: user
      content: How many orders shipped yesterday?
    # С этого момента определяйте db_query по значению. `tools` и
    # предыдущие сообщения остаются точно такими, как были отправлены, поэтому попадание в кэш сохраняется.
    - role: system
      content:
        - type: tool_addition
          tool:
            type: tool_definition
            definition:
              name: db_query
              description: Run a read-only SQL query against the analytics database.
              input_schema:
                type: object
                properties:
                  sql:
                    type: string
                required:
                  - sql
  YAML
  ```

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

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      betas=["inline-tools-2026-09-15"],
      # Оставляйте в `tools` хотя бы один неотложенный инструмент, чтобы инструмент, определённый
      # позже, не менял начало сформированной подсказки.
      tools=[
          {
              "name": "get_weather",
              "description": "Get the current weather for a location.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string", "description": "City name"},
                  },
                  "required": ["location"],
              },
          },
      ],
      messages=[
          {"role": "user", "content": "How many orders shipped yesterday?"},
          # С этого момента определяйте db_query по значению. `tools` и
          # предыдущие сообщения остаются точно такими, как были отправлены, поэтому кэш по-прежнему срабатывает.
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_addition",
                      "tool": {
                          "type": "tool_definition",
                          "definition": {
                              "name": "db_query",
                              "description": "Run a read-only SQL query against the analytics database.",
                              "input_schema": {
                                  "type": "object",
                                  "properties": {"sql": {"type": "string"}},
                                  "required": ["sql"],
                              },
                          },
                      },
                  },
              ],
          },
      ],
  )

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

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

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    betas: ["inline-tools-2026-09-15"],
    // Оставляйте в `tools` хотя бы один неотложенный инструмент, чтобы инструмент, определённый
    // позже, не менял начало сформированной подсказки.
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "How many orders shipped yesterday?" },
      // С этого момента определяйте db_query по значению. `tools` и
      // предыдущие сообщения остаются точно такими, как были отправлены, поэтому кэш по-прежнему срабатывает.
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: {
                name: "db_query",
                description: "Run a read-only SQL query against the analytics database.",
                input_schema: {
                  type: "object",
                  properties: { sql: { type: "string" } },
                  required: ["sql"]
                }
              }
            }
          }
        ]
      }
    ]
  });

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

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

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Betas = [AnthropicBeta.InlineTools2026_09_15],
      // Оставляйте в `Tools` хотя бы один неотложенный инструмент, чтобы инструмент, определённый
      // позже, не менял начало сформированной подсказки.
      Tools =
      [
          new BetaTool
          {
              Name = "get_weather",
              Description = "Get the current weather for a location.",
              InputSchema = new InputSchema
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["location"] = JsonSerializer.SerializeToElement(new { type = "string", description = "City name" }),
                  },
                  Required = ["location"],
              },
          },
      ],
      Messages =
      [
          new() { Role = Role.User, Content = "How many orders shipped yesterday?" },
          // С этого момента определяйте db_query по значению. `Tools` и
          // предыдущие сообщения остаются точно такими, как были отправлены, поэтому попадание в кэш сохраняется.
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolAdditionBlock
                  {
                      Tool = new BetaToolChangeToolDefinitionParam
                      {
                          Definition = new BetaTool
                          {
                              Name = "db_query",
                              Description = "Run a read-only SQL query against the analytics database.",
                              InputSchema = new InputSchema
                              {
                                  Properties = new Dictionary<string, JsonElement>
                                  {
                                      ["sql"] = JsonSerializer.SerializeToElement(new { type = "string" }),
                                  },
                                  Required = ["sql"],
                              },
                          },
                      },
                  },
              ]),
          },
      ],
  });

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

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

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaInlineTools2026_09_15},
  	// Оставляйте в Tools хотя бы один неотложенный инструмент, чтобы инструмент, определённый
  	// позже, не менял начало сформированной подсказки.
  	Tools: []anthropic.BetaToolUnionParam{
  		{OfTool: &anthropic.BetaToolParam{
  			Name:        "get_weather",
  			Description: anthropic.String("Get the current weather for a location."),
  			InputSchema: anthropic.BetaToolInputSchemaParam{
  				Properties: map[string]any{
  					"location": map[string]any{
  						"type":        "string",
  						"description": "City name",
  					},
  				},
  				Required: []string{"location"},
  			},
  		}},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("How many orders shipped yesterday?")),
  		// С этого момента определяйте db_query по значению. Tools и
  		// предыдущие сообщения остаются в точности такими, как были отправлены, поэтому попадание в кэш сохраняется.
  		{
  			Role: anthropic.BetaMessageParamRoleSystem,
  			Content: []anthropic.BetaContentBlockParamUnion{
  				anthropic.NewBetaToolAdditionBlock(anthropic.BetaToolChangeToolDefinitionParam{
  					Definition: anthropic.BetaToolUnionParam{OfTool: &anthropic.BetaToolParam{
  						Name:        "db_query",
  						Description: anthropic.String("Run a read-only SQL query against the analytics database."),
  						InputSchema: anthropic.BetaToolInputSchemaParam{
  							Properties: map[string]any{
  								"sql": map[string]any{"type": "string"},
  							},
  							Required: []string{"sql"},
  						},
  					}},
  				}),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

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

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

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

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

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

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addBeta(AnthropicBeta.INLINE_TOOLS_2026_09_15)
          // Оставляйте в `tools` хотя бы один неотложенный инструмент, чтобы инструмент, определённый
          // позже, не менял начало сформированной подсказки.
          .addTool(weatherTool)
          .addUserMessage("How many orders shipped yesterday?")
          // С этого момента определяйте db_query по значению. `tools` и
          // предыдущие сообщения остаются в точности такими, как были отправлены, поэтому попадание в кэш сохраняется.
          .addSystemMessageOfBetaContentBlockParams(List.of(
              BetaContentBlockParam.ofToolAddition(BetaRequestToolAdditionBlock.builder()
                  .definitionTool(dbQueryTool)
                  .build())))
          .build();

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

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

  $client = new Client();

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      betas: [AnthropicBeta::INLINE_TOOLS_2026_09_15],
      // Оставляйте в `tools` хотя бы один неотложенный инструмент, чтобы инструмент, определённый
      // позже, не менял начало отрисованной подсказки.
      tools: [
          [
              'name' => 'get_weather',
              'description' => 'Get the current weather for a location.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'location' => [
                          'type' => 'string',
                          'description' => 'City name',
                      ],
                  ],
                  'required' => ['location'],
              ],
          ],
      ],
      messages: [
          ['role' => 'user', 'content' => 'How many orders shipped yesterday?'],
          // С этого момента определяйте db_query по значению. `tools` и
          // предыдущие сообщения остаются точно такими, как отправлены, поэтому кэш срабатывает.
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_addition',
                      'tool' => [
                          'type' => 'tool_definition',
                          'definition' => [
                              'name' => 'db_query',
                              'description' => 'Run a read-only SQL query against the analytics database.',
                              'input_schema' => [
                                  'type' => 'object',
                                  'properties' => ['sql' => ['type' => 'string']],
                                  'required' => ['sql'],
                              ],
                          ],
                      ],
                  ],
              ],
          ],
      ],
  );

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

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

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    max_tokens: 1024,
    betas: [Anthropic::AnthropicBeta::INLINE_TOOLS_2026_09_15],
    # Оставляйте в `tools` хотя бы один неотложенный инструмент, чтобы инструмент, определённый
    # позже, не менял начало сформированной подсказки.
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "How many orders shipped yesterday?" },
      # С этого момента определяйте db_query по значению. `tools` и
      # предыдущие сообщения остаются в точности такими, как были отправлены, поэтому кэш по-прежнему срабатывает.
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: {
                name: "db_query",
                description: "Run a read-only SQL query against the analytics database.",
                input_schema: {
                  type: "object",
                  properties: { sql: { type: "string" } },
                  required: ["sql"]
                }
              }
            }
          }
        ]
      }
    ]
  )

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

`content` ответа включает блок `tool_use` для нового инструмента, например:

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

Чтобы изменить схему инструмента или перевести серверный инструмент на более новую версию, отправьте другое определение под тем же именем. Новое определение заменяет предыдущее начиная с этой позиции. Если определение повторно использует имя инструмента другого типа, возвращается ошибка 400 с `error.details.error_code`, равным `tool_name_conflict`. Более новая версия того же инструмента не считается другим типом. `tool_removal` по-прежнему принимает ссылку, а удалённый инструмент позже можно снова определить или предложить.

Из того, где отображается определение, вытекает несколько правил:

* **Объявляйте заранее то, что знаете.** Инструмент, известный на момент первого запроса, должен находиться в `tools`. Если модель пока не должна его видеть, объявите его с `defer_loading: true` и добавьте позже ссылкой в блоке `tool_addition`. Определяйте по значению только то, что неизвестно на момент первого запроса или меняется позже.
* **Оставляйте в `tools` хотя бы один неотложенный инструмент.** Разговор, в массиве `tools` которого нет неотложенных инструментов, принимается. Однако первый инструмент, определённый в нём по значению, изменяет начало отображаемой подсказки. Из-за этого запрос, в котором он определён, полностью промахивается мимо кэша. [Инструмент поиска инструментов](https://platform.claude.com/docs/ru/agents-and-tools/tool-use/tool-search-tool) считается неотложенным.
* **Датированные типы инструментов сохраняют собственные бета-заголовки.** Если серверный инструмент, который вы определяете по значению, требует собственного бета-заголовка, отправляйте этот заголовок в каждом последующем запросе разговора.
* **`cache_control` указывается либо в блоке, либо в определении, но не в обоих местах.** Он учитывается в лимите «breakpoint» (точек останова) запроса. Отложенное определение не может содержать `cache_control`.

Запрос возвращает ошибку 400 с `error.details.error_code`, равным `available_tools_limit_exceeded`, если превышен любой из этих лимитов:

* После любого сообщения доступно более 10 000 отложенных инструментов.
* После любого сообщения доступно более 10 000 инструментов, определённых после первого сообщения пользователя.
* Определения инструментов, отправленные после первого сообщения пользователя и всё ещё доступные после любого сообщения, в сумме превышают 4 МБ (4 194 304 байта).
* Отображаемый текст инструментов превышает 4 МБ (4 194 304 байта).

### Добавление сервера MCP в середине разговора (бета)

Чтобы добавить сервер [коннектора MCP](https://platform.claude.com/docs/ru/agents-and-tools/mcp-connector) по ходу разговора, отправьте бета-заголовок `mcp-client-2026-09-15` вместе с `inline-tools-2026-09-15`. Тогда `definition` в блоке `tool_addition` может быть объектом `mcp_toolset`, и инструменты сервера становятся доступными без редактирования `tools`. Как обычно, укажите параметры подключения к серверу в `mcp_servers`. Затем добавьте набор инструментов в том месте, где сервер стал доступен:

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

Объект `mcp_toolset` — тот же, который вы поместили бы в `tools`, включая `default_config` и `configs`. Блок `tool_addition` никогда не содержит URL-адрес или токен сервера: они остаются в `mcp_servers`.

Следующий запрос сохраняет `get_weather` в `tools`, указывает сервер календаря в `mcp_servers` и добавляет набор инструментов сервера после первого хода пользователя:

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

  ```bash CLI
  ant beta:messages create \
    --beta inline-tools-2026-09-15,mcp-client-2026-09-15 <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  mcp_servers:
    - type: url
      url: https://mcp.example.com/calendar
      name: calendar
      authorization_token: YOUR_TOKEN
  tools:
    - name: get_weather
      description: Get the current weather for a location.
      input_schema:
        type: object
        properties:
          location:
            type: string
            description: City name
        required:
          - location
  messages:
    - role: user
      content: What's on my calendar tomorrow?
    # Сделать инструменты сервера календаря доступными начиная с этого момента.
    # Блок указывает имя сервера; он никогда не содержит URL или токен.
    - role: system
      content:
        - type: tool_addition
          tool:
            type: tool_definition
            definition:
              type: mcp_toolset
              mcp_server_name: calendar
  YAML
  ```

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

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      betas=["inline-tools-2026-09-15", "mcp-client-2026-09-15"],
      mcp_servers=[
          {
              "type": "url",
              "url": "https://mcp.example.com/calendar",
              "name": "calendar",
              "authorization_token": "YOUR_TOKEN",
          },
      ],
      tools=[
          {
              "name": "get_weather",
              "description": "Get the current weather for a location.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string", "description": "City name"},
                  },
                  "required": ["location"],
              },
          },
      ],
      messages=[
          {"role": "user", "content": "What's on my calendar tomorrow?"},
          # Сделать инструменты сервера календаря доступными начиная с этого момента.
          # Блок указывает имя сервера; он никогда не содержит URL или токен.
          {
              "role": "system",
              "content": [
                  {
                      "type": "tool_addition",
                      "tool": {
                          "type": "tool_definition",
                          "definition": {
                              "type": "mcp_toolset",
                              "mcp_server_name": "calendar",
                          },
                      },
                  },
              ],
          },
      ],
  )

  # Ответ начинается с блока mcp_tool_listing для сервера календаря,
  # поэтому проверяйте тип каждого блока, а не читайте content[0].
  for block in response.content:
      match block.type:
          case "mcp_tool_listing":
              print(block.mcp_server_name, [tool.name for tool in block.tools])
          case "text":
              print(block.text)
  ```

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

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    betas: ["inline-tools-2026-09-15", "mcp-client-2026-09-15"],
    mcp_servers: [
      {
        type: "url",
        url: "https://mcp.example.com/calendar",
        name: "calendar",
        authorization_token: "YOUR_TOKEN"
      }
    ],
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "What's on my calendar tomorrow?" },
      // Сделать инструменты сервера календаря доступными начиная с этого момента.
      // Блок указывает имя сервера; он никогда не содержит URL или токен.
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: { type: "mcp_toolset", mcp_server_name: "calendar" }
            }
          }
        ]
      }
    ]
  });

  // Ответ начинается с блока mcp_tool_listing для сервера календаря,
  // поэтому проверяйте тип каждого блока, а не читайте content[0].
  for (const block of response.content) {
    switch (block.type) {
      case "mcp_tool_listing":
        console.log(
          block.mcp_server_name,
          block.tools.map((tool) => tool.name)
        );
        break;
      case "text":
        console.log(block.text);
        break;
    }
  }
  ```

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

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Betas = [AnthropicBeta.InlineTools2026_09_15, AnthropicBeta.McpClient2026_09_15],
      McpServers =
      [
          new BetaRequestMcpServerUrlDefinition
          {
              Url = "https://mcp.example.com/calendar",
              Name = "calendar",
              AuthorizationToken = "YOUR_TOKEN",
          },
      ],
      Tools =
      [
          new BetaTool
          {
              Name = "get_weather",
              Description = "Get the current weather for a location.",
              InputSchema = new InputSchema
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["location"] = JsonSerializer.SerializeToElement(new { type = "string", description = "City name" }),
                  },
                  Required = ["location"],
              },
          },
      ],
      Messages =
      [
          new() { Role = Role.User, Content = "What's on my calendar tomorrow?" },
          // Сделать инструменты сервера календаря доступными начиная с этого момента.
          // Блок указывает имя сервера; он никогда не содержит URL или токен.
          new()
          {
              Role = Role.System,
              Content = new(
              [
                  new BetaRequestToolAdditionBlock
                  {
                      Tool = new BetaToolChangeToolDefinitionParam
                      {
                          Definition = new BetaMcpToolset("calendar"),
                      },
                  },
              ]),
          },
      ],
  });

  // Ответ начинается с блока mcp_tool_listing для сервера календаря,
  // поэтому проверяйте тип каждого блока, а не читайте Content[0].
  foreach (var block in response.Content)
  {
      if (block.TryPickMcpToolListing(out var listing))
      {
          Console.WriteLine($"{listing.McpServerName} {JsonSerializer.Serialize(listing.Tools.Select(tool => tool.Name))}");
      }
      else if (block.TryPickText(out var text))
      {
          Console.WriteLine(text.Text);
      }
  }
  ```

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

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Betas: []anthropic.AnthropicBeta{
  		anthropic.AnthropicBetaInlineTools2026_09_15,
  		anthropic.AnthropicBetaMCPClient2026_09_15,
  	},
  	MCPServers: []anthropic.BetaRequestMCPServerURLDefinitionParam{
  		{
  			URL:                "https://mcp.example.com/calendar",
  			Name:               "calendar",
  			AuthorizationToken: anthropic.String("YOUR_TOKEN"),
  		},
  	},
  	Tools: []anthropic.BetaToolUnionParam{
  		{OfTool: &anthropic.BetaToolParam{
  			Name:        "get_weather",
  			Description: anthropic.String("Get the current weather for a location."),
  			InputSchema: anthropic.BetaToolInputSchemaParam{
  				Properties: map[string]any{
  					"location": map[string]any{
  						"type":        "string",
  						"description": "City name",
  					},
  				},
  				Required: []string{"location"},
  			},
  		}},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What's on my calendar tomorrow?")),
  		// Сделать инструменты сервера календаря доступными начиная с этого момента.
  		// Блок указывает имя сервера; он никогда не содержит URL или токен.
  		{
  			Role: anthropic.BetaMessageParamRoleSystem,
  			Content: []anthropic.BetaContentBlockParamUnion{
  				anthropic.NewBetaToolAdditionBlock(anthropic.BetaToolChangeToolDefinitionParam{
  					Definition: anthropic.BetaToolUnionParam{OfMCPToolset: &anthropic.BetaMCPToolsetParam{
  						MCPServerName: "calendar",
  					}},
  				}),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  // Ответ начинается с блока mcp_tool_listing для сервера календаря,
  // поэтому проверяйте тип каждого блока, а не читайте Content[0].
  for _, block := range response.Content {
  	switch variant := block.AsAny().(type) {
  	case anthropic.BetaMCPToolListingBlock:
  		var toolNames []string
  		for _, tool := range variant.Tools {
  			toolNames = append(toolNames, tool.Name)
  		}
  		fmt.Println(variant.MCPServerName, toolNames)
  	case anthropic.BetaTextBlock:
  		fmt.Println(variant.Text)
  	}
  }
  ```

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

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

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

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addBeta(AnthropicBeta.INLINE_TOOLS_2026_09_15)
          .addBeta(AnthropicBeta.MCP_CLIENT_2026_09_15)
          .addMcpServer(BetaRequestMcpServerUrlDefinition.builder()
              .url("https://mcp.example.com/calendar")
              .name("calendar")
              .authorizationToken("YOUR_TOKEN")
              .build())
          .addTool(weatherTool)
          .addUserMessage("What's on my calendar tomorrow?")
          // Сделать инструменты сервера календаря доступными начиная с этого момента.
          // Блок указывает имя сервера; он никогда не содержит URL или токен.
          .addSystemMessageOfBetaContentBlockParams(List.of(
              BetaContentBlockParam.ofToolAddition(BetaRequestToolAdditionBlock.builder()
                  .definitionTool(BetaMcpToolset.builder()
                      .mcpServerName("calendar")
                      .build())
                  .build())))
          .build();

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

      // Ответ начинается с блока mcp_tool_listing для сервера календаря,
      // поэтому проверяйте тип каждого блока, а не читайте первый блок.
      for (var block : response.content()) {
          switch (block.type().value()) {
              case MCP_TOOL_LISTING -> {
                  var listing = block.asMcpToolListing();
                  var toolNames = listing.tools().stream().map(BetaMcpTool::name).toList();
                  IO.println(listing.mcpServerName() + " " + toolNames);
              }
              case TEXT -> IO.println(block.asText().text());
          }
      }
  }
  ```

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

  $client = new Client();

  $response = $client->beta->messages->create(
      model: Model::CLAUDE_OPUS_5_5,
      maxTokens: 1024,
      betas: [
          AnthropicBeta::INLINE_TOOLS_2026_09_15,
          AnthropicBeta::MCP_CLIENT_2026_09_15,
      ],
      mcpServers: [
          [
              'type' => 'url',
              'url' => 'https://mcp.example.com/calendar',
              'name' => 'calendar',
              'authorization_token' => 'YOUR_TOKEN',
          ],
      ],
      tools: [
          [
              'name' => 'get_weather',
              'description' => 'Get the current weather for a location.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'location' => [
                          'type' => 'string',
                          'description' => 'City name',
                      ],
                  ],
                  'required' => ['location'],
              ],
          ],
      ],
      messages: [
          ['role' => 'user', 'content' => "What's on my calendar tomorrow?"],
          // Сделать инструменты сервера календаря доступными начиная с этого момента.
          // Блок указывает имя сервера; он никогда не содержит URL или токен.
          [
              'role' => 'system',
              'content' => [
                  [
                      'type' => 'tool_addition',
                      'tool' => [
                          'type' => 'tool_definition',
                          'definition' => [
                              'type' => 'mcp_toolset',
                              'mcp_server_name' => 'calendar',
                          ],
                      ],
                  ],
              ],
          ],
      ],
  );

  // Ответ начинается с блока mcp_tool_listing для сервера календаря,
  // поэтому проверяйте тип каждого блока, а не читайте content[0].
  foreach ($response->content as $block) {
      switch (true) {
          case $block instanceof BetaMCPToolListingBlock:
              $toolNames = array_map(fn (BetaMCPTool $tool) => $tool->name, $block->tools);
              echo $block->mcpServerName, ' ', json_encode($toolNames), PHP_EOL;
              break;
          case $block instanceof BetaTextBlock:
              echo $block->text, PHP_EOL;
              break;
      }
  }
  ```

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

  response = client.beta.messages.create(
    model: Anthropic::Model::CLAUDE_OPUS_5_5,
    max_tokens: 1024,
    betas: [
      Anthropic::AnthropicBeta::INLINE_TOOLS_2026_09_15,
      Anthropic::AnthropicBeta::MCP_CLIENT_2026_09_15
    ],
    mcp_servers: [
      {
        type: "url",
        url: "https://mcp.example.com/calendar",
        name: "calendar",
        authorization_token: "YOUR_TOKEN"
      }
    ],
    tools: [
      {
        name: "get_weather",
        description: "Get the current weather for a location.",
        input_schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City name" }
          },
          required: ["location"]
        }
      }
    ],
    messages: [
      { role: "user", content: "What's on my calendar tomorrow?" },
      # Сделать инструменты сервера календаря доступными начиная с этого момента.
      # Блок указывает имя сервера; он никогда не содержит URL или токен.
      {
        role: "system",
        content: [
          {
            type: "tool_addition",
            tool: {
              type: "tool_definition",
              definition: { type: "mcp_toolset", mcp_server_name: "calendar" }
            }
          }
        ]
      }
    ]
  )

  # Ответ начинается с блока mcp_tool_listing для сервера календаря,
  # поэтому проверяйте тип каждого блока, а не читайте content[0].
  response.content.each do |block|
    case block
    when Anthropic::Beta::BetaMCPToolListingBlock
      puts "#{block.mcp_server_name} #{block.tools.map(&:name)}"
    when Anthropic::Beta::BetaTextBlock
      puts block.text
    end
  end
  ```
</CodeGroup>

С `mcp-client-2026-09-15` ответ, для которого API получил список инструментов сервера, начинается с блоков `mcp_tool_listing` — по одному на каждый такой сервер. Если ваш код читает `content[0]`, пропускайте эти блоки. Отправляйте сообщение ассистента обратно без изменений, включая этот блок. Продолжайте отправлять `mcp-client-2026-09-15` в каждом запросе, который содержит такой блок. Тогда последующие запросы используют записанный список и не обращаются к серверу повторно. Чтобы закрепить набор инструментов самостоятельно, скопируйте этот список в поле `tools` объекта `mcp_toolset`, как описано в разделе [Закрепление списка инструментов сервера MCP](https://platform.claude.com/docs/ru/agents-and-tools/mcp-connector#pin-mcp-tool-list).

`mcp-client-2026-09-15` включает всё, что включает `mcp-client-2025-11-20`, поэтому отправлять оба заголовка не нужно. Эти функции доступны в Claude API. На запросы, использующие коннектор MCP, распространяются его условия [хранения данных](https://platform.claude.com/docs/ru/agents-and-tools/mcp-connector#data-retention).

## Когда использовать системное сообщение в середине разговора

[Кэширование подсказок](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching) хэширует префикс запроса по порядку: `tools`, затем `system`, затем `messages`. Для попадания в кэш требуется, чтобы префикс точно, байт в байт, совпадал с недавним запросом вплоть до точки разрыва кэша.

Такой порядок означает, что поле верхнего уровня `system` находится почти в самом начале хэшируемого префикса. Любое его изменение, даже добавление одного предложения, даёт другой хэш, и запрос промахивается мимо кэша для системной подсказки и каждого кэшированного сообщения после неё.

Системные сообщения в середине разговора позволяют вместо этого добавить инструкцию в **конец** истории сообщений. Всё, что предшествует новой инструкции, остаётся неизменным, поэтому существующая запись кэша по-прежнему совпадает, и только новое сообщение обрабатывается как свежий ввод.

Несколько ситуаций, в которых это важно:

* **Изменения политики или персоны в середине сессии.** Длинной агентной сессии требуется новое ограничение («с этого момента пиши весь SQL в виде параметризованных запросов») после десятков кэшированных ходов. Добавление его в поле верхнего уровня `system` привело бы к повторной обработке всей истории.
* **Контекст для каждого хода, который должен быть авторитетным.** Вы хотите внедрить заметку об актуальности, крайний срок сессии или изменение доступности инструментов с весом системного уровня, и это меняется слишком часто, чтобы находиться в кэшированном префиксе.
* **Напоминания для каждого хода, которые не должны накапливаться.** Обвязка подталкивает модель после каждой порции результатов инструментов («запрашивай независимые чтения вместе», «пользователь давно не получал от тебя ответа») и хочет, чтобы модель видела только самую новую копию. [Системное сообщение, ограниченное ходом](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages), отображается в течение одного хода, а затем ничего не стоит, без удаления чего-либо из истории.
* **Изменения состояния, которые наблюдает ваше приложение.** Ваше приложение замечает что-то, что Claude должен воспринимать как факт уровня оператора: файлы изменились на диске, пользователь переключил настройку автоматического одобрения, изменились доступные инструменты или оставшийся бюджет токенов упал ниже порога.
* **Ввод пользователя, который не должен прерывать агентный цикл.** Пользователь вводит уточнение, пока Claude ещё выполняет инструменты для предыдущего запроса. Передача его в виде системного сообщения после следующего результата инструмента позволяет Claude включить новый ввод в уже выполняемую работу, а не воспринимать его как новый запрос, на который нужно переключиться. В Claude Sonnet 5.5 и Claude Haiku 5.5 вместо этого добавляйте слова пользователя в виде блока `text` после последнего `tool_result` в том же сообщении `user`. См. [Размещение после результатов инструментов](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages#placement-after-tool-results).
* **Переключения режимов, предоставляющие постоянные разрешения.** Режим уровня сессии может использовать системное сообщение в середине разговора, чтобы предоставить постоянное согласие на дорогостоящую возможность, такую как автоматический запуск мультиагентных рабочих процессов, с коротким напоминанием каждые несколько ходов и уведомлением о выходе, когда режим выключается. Разобранный пример см. в разделе [Создание режима оркестрации](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-effort-example).

Во всех этих случаях вы могли бы поместить инструкцию в обычное сообщение `user`, и Claude действительно следует инструкциям, поступающим в пользовательских ходах. Разница в приоритете: сообщение `user` рассматривается как исходящее от конечного пользователя, тогда как сообщение `system` рассматривается как исходящее от вас, оператора приложения. Когда они конфликтуют, системные инструкции имеют приоритет, поэтому используйте роль `system` для фактов и ограничений уровня оператора, которые должны соблюдаться, даже если конечный пользователь просит о чём-то другом. Системное сообщение в середине разговора сохраняет этот приоритет уровня оператора, не платя цену промаха кэша за редактирование поля верхнего уровня `system`.

## Как это работает

Добавьте сообщение с `"role": "system"` в массив `messages`. Для `content` используйте простую строку или блоки содержимого — так же, как для хода `user` или `assistant`. Инструкция применяется начиная с этой точки разговора. При конфликте инструкций более поздние системные сообщения имеют приоритет над более ранними. Системные сообщения в середине разговора также имеют приоритет над полем верхнего уровня `system` для следующих за ними ходов.

Поле верхнего уровня `system` по-прежнему подходит для инструкций, которые должны действовать на протяжении всего разговора. Системные сообщения в середине разговора используйте для инструкций, которые становятся актуальными только позже или которые нужно добавить, не делая недействительным кэшированный префикс.

Сообщение `role: "system"` также может содержать `output_config.effort`, чтобы изменить уровень [effort](https://platform.claude.com/docs/ru/build-with-claude/effort) посреди разговора. Эта возможность находится в бета-версии в Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5.5 и Claude Haiku 5.5 в Claude API и Google Cloud и требует бета-заголовка `mid-conversation-output-config-2026-07-01`. В Amazon Bedrock она находится в бета-версии в Claude Fable 5.1, Claude Mythos 5.1 и Claude Opus 5.5 с тем же бета-значением. Claude Opus 5 не поддерживает её в Amazon Bedrock. См. [Уровень усилий для отдельных сообщений](https://platform.claude.com/docs/ru/build-with-claude/effort#change-effort-mid-conversation-beta).

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

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

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

  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      # Автоматическое "prompt caching" (кэширование подсказок): каждый запрос кэширует текущий диалог,
      # а следующий запрос читает неизменённый префикс из кэша.
      cache_control={"type": "ephemeral"},
      system="You are a code review assistant. Be concise.",
      messages=[
          {
              "role": "user",
              "content": "Review process() in utils.py for performance issues.",
          },
          {
              "role": "assistant",
              "content": "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.",
          },
          {
              "role": "user",
              "content": "Now review the calling code that invokes process().",
          },
          # Посреди сеанса рецензент понимает, что все предложения должны
          # также соответствовать строгой политике типизации команды. Добавление
          # инструкции здесь сохраняет прежние ходы побайтово идентичными, поэтому
          # префикс, закэшированный предыдущим запросом, по-прежнему читается из кэша.
          {
              "role": "system",
              "content": "From now on, every suggestion must include explicit type annotations.",
          },
      ],
  )

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

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

  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    // Автоматическое кэширование подсказок: каждый запрос кэширует текущий диалог,
    // а следующий запрос читает неизменённый префикс из кэша.
    cache_control: { type: "ephemeral" },
    system: "You are a code review assistant. Be concise.",
    messages: [
      {
        role: "user",
        content: "Review process() in utils.py for performance issues."
      },
      {
        role: "assistant",
        content:
          "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list."
      },
      {
        role: "user",
        content: "Now review the calling code that invokes process()."
      },
      // Посреди сессии рецензент понимает, что все предложения также должны соответствовать
      // строгой политике типизации команды. Добавление инструкции здесь сохраняет
      // предыдущие ходы побайтово идентичными, поэтому префикс, закэшированный предыдущим
      // запросом, по-прежнему читается из кэша.
      {
        role: "system",
        content: "From now on, every suggestion must include explicit type annotations."
      }
    ]
  });

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

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

  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      // Автоматический prompt caching (кэширование подсказок): каждый запрос кэширует диалог на текущий момент,
      // а следующий запрос читает неизменённый префикс из кэша.
      CacheControl = new CacheControlEphemeral(),
      System = "You are a code review assistant. Be concise.",
      Messages =
      [
          new()
          {
              Role = Role.User,
              Content = "Review process() in utils.py for performance issues."
          },
          new()
          {
              Role = Role.Assistant,
              Content = "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list."
          },
          new()
          {
              Role = Role.User,
              Content = "Now review the calling code that invokes process()."
          },
          // Посреди сессии рецензент понимает, что все предложения также должны соответствовать
          // строгой политике типизации команды. Добавление инструкции здесь сохраняет
          // предыдущие ходы побайтово идентичными, поэтому префикс, закэшированный предыдущим
          // запросом, по-прежнему читается из кэша.
          new()
          {
              Role = Role.System,
              Content = "From now on, every suggestion must include explicit type annotations."
          }
      ]
  };

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

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

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	// Автоматический prompt caching (кэширование подсказок): каждый запрос кэширует диалог на текущий момент,
  	// а следующий запрос читает неизменённый префикс из кэша.
  	CacheControl: anthropic.NewCacheControlEphemeralParam(),
  	System: []anthropic.TextBlockParam{
  		{Text: "You are a code review assistant. Be concise."},
  	},
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Review process() in utils.py for performance issues.")),
  		anthropic.NewAssistantMessage(anthropic.NewTextBlock("The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.")),
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Now review the calling code that invokes process().")),
  		// Посреди сессии рецензент понимает, что все предложения также должны
  		// соответствовать строгой политике типизации команды. Добавление инструкции
  		// здесь сохраняет предыдущие ходы побайтово идентичными, поэтому префикс, закэшированный
  		// предыдущим запросом, по-прежнему читается из кэша.
  		{
  			Role: anthropic.MessageParamRoleSystem,
  			Content: []anthropic.ContentBlockParamUnion{
  				anthropic.NewTextBlock("From now on, every suggestion must include explicit type annotations."),
  			},
  		},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  for _, block := range response.Content {
  	if textBlock, ok := block.AsAny().(anthropic.TextBlock); ok {
  		fmt.Println(textBlock.Text)
  	}
  }
  ```

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

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          // Автоматическое кэширование подсказок (prompt caching): каждый запрос кэширует диалог на текущий момент,
          // а следующий запрос читает неизменённый префикс из кэша.
          .cacheControl(CacheControlEphemeral.builder().build())
          .system("You are a code review assistant. Be concise.")
          .addUserMessage("Review process() in utils.py for performance issues.")
          .addAssistantMessage("The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.")
          .addUserMessage("Now review the calling code that invokes process().")
          // Посреди сессии рецензент понимает, что все предложения также должны соответствовать
          // строгой политике типизации команды. Добавление инструкции здесь сохраняет
          // предыдущие ходы побайтово идентичными, поэтому префикс, закэшированный предыдущим
          // запросом, по-прежнему читается из кэша.
          .addMessage(MessageParam.builder()
              .role(MessageParam.Role.SYSTEM)
              .content("From now on, every suggestion must include explicit type annotations.")
              .build())
          .build();

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

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

  $response = $client->messages->create(
      maxTokens: 1024,
      messages: [
          ['role' => 'user', 'content' => 'Review process() in utils.py for performance issues.'],
          ['role' => 'assistant', 'content' => 'The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.'],
          ['role' => 'user', 'content' => 'Now review the calling code that invokes process().'],
          // Посреди сессии рецензент понимает, что все предложения также должны соответствовать
          // строгой политике типизации команды. Добавление инструкции здесь сохраняет
          // предыдущие ходы побайтово идентичными, поэтому префикс, закэшированный предыдущим
          // запросом, по-прежнему читается из кэша.
          ['role' => 'system', 'content' => 'From now on, every suggestion must include explicit type annotations.']
      ],
      model: 'claude-opus-5-5',
      // Автоматическое кэширование подсказок: каждый запрос кэширует текущий диалог,
      // а следующий запрос читает неизменённый префикс из кэша.
      cacheControl: CacheControlEphemeral::with(),
      system: 'You are a code review assistant. Be concise.',
  );

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

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

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    # Автоматическое кэширование подсказок: каждый запрос кэширует текущий диалог,
    # а следующий запрос читает неизменённый префикс из кэша.
    cache_control: { type: "ephemeral" },
    system: "You are a code review assistant. Be concise.",
    messages: [
      { role: "user", content: "Review process() in utils.py for performance issues." },
      { role: "assistant", content: "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list." },
      { role: "user", content: "Now review the calling code that invokes process()." },
      # Посреди сеанса рецензент понимает, что все предложения должны также соответствовать
      # строгой политике типизации команды. Добавление инструкции здесь сохраняет
      # предыдущие ходы побайтово идентичными, поэтому префикс, закэшированный предыдущим
      # запросом, по-прежнему читается из кэша.
      { role: "system", content: "From now on, every suggestion must include explicit type annotations." }
    ]
  )

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

Этот пример включает [автоматическое кэширование](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching#automatic-caching) с помощью поля верхнего уровня `cache_control`. Кэширование подсказок нужно включать явно. Если в запросе нет поля `cache_control` (ни автоматического, ни [явной точки останова](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching#explicit-cache-breakpoints)), ничего не кэшируется. Тогда каждый запрос оплачивается по обычной цене входных токенов за весь разговор. При включённом кэшировании добавление системного сообщения не меняет уже кэшированные ходы. Поэтому запрос с новой инструкцией по-прежнему считывает их из кэша, а не обрабатывает заново. Кроме того, разговор должен достигать [минимальной длины кэшируемой подсказки](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching#cache-limitations). Такой короткий пример, как этот, её не достигает, поэтому `cache_creation_input_tokens` и `cache_read_input_tokens` остаются равными 0, пока разговор не станет длиннее.

Системное сообщение в середине разговора, имеющее содержимое (блоки `text`, `tool_addition` или `tool_removal`), должно непосредственно следовать за ходом `user` (или ходом `assistant`, заканчивающимся результатом серверного инструмента) и должно либо быть последней записью в `messages`, либо непосредственно предшествовать ходу `assistant`. Сообщение `user`, содержащее блоки `tool_result`, тоже подходит: в агентном цикле вы можете разместить системное сообщение сразу после результатов инструментов, перед следующим ходом Claude. Любая другая позиция для сообщения с содержимым, в том числе между блоком `tool_use` в ходе `assistant` и отвечающим на него `tool_result`, возвращает ошибку 400. Сообщение с пустым `content`, которое только задаёт [`output_config.effort`](https://platform.claude.com/docs/ru/build-with-claude/effort#change-effort-mid-conversation-beta), принимается в любом месте `messages`. Последовательные сообщения `system` оцениваются вместе, поэтому сообщение, задающее только effort, рядом с сообщением с содержимым подчиняется правилу для сообщений с содержимым.

### Размещение после результатов инструментов

В [агентном цикле](https://platform.claude.com/docs/ru/agents-and-tools/tool-use/overview) системное сообщение размещается после сообщения `user`, доставляющего результаты инструментов. На большинстве моделей именно здесь ваше приложение также может передать ввод, который пользователь набрал, пока Claude работал, чтобы новый контекст был учтён без перезапуска хода (для Claude Sonnet 5.5 и Claude Haiku 5.5 см. конец этого раздела):

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

Формулируйте системное содержимое как контекст, а не как команду, отменяющую указания пользователя. Изложите факт («от пользователя поступил новый ввод: X», «оставшийся бюджет токенов теперь Y») и позвольте Claude действовать на его основе. Claude обучен сопротивляться инструкциям, которые выглядят направленными против пользователя, и эта защита по-прежнему распространяется на системную роль, поэтому формулировки вроде «игнорируй то, что сказал пользователь» менее эффективны, чем изложение того, что изменилось.

Этот шаблон предназначен для передачи ввода от собственного конечного пользователя разговора. Не используйте его для передачи вывода инструментов, извлечённых документов или другого стороннего содержимого; храните это содержимое в блоках `tool_result` (см. [Ограничения](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages#limitations)).

В Claude Sonnet 5.5 и Claude Haiku 5.5 вместо этого передавайте слова пользователя в пользовательском ходе. Эти модели обучены сопротивляться внедрению подсказок через результаты инструментов, поэтому они могут воспринять системное сообщение, размещённое сразу после результата инструмента, как недоверенный текст и проигнорировать его. Добавляйте слова пользователя в виде блока `text` после последнего `tool_result` в том же сообщении `user`. Уведомления обвязки, например напоминания, размещайте в отдельном системном сообщении в середине разговора после этого сообщения `user` и никогда не помещайте уведомление и слова пользователя в один блок:

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

Подробнее об этом поведении см. в разделах [Подсказки для Claude Sonnet 5.5](https://platform.claude.com/docs/ru/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#mid-turn-user-messages-and-task-budgets) и [Составление подсказок для Claude Haiku 5.5](https://platform.claude.com/docs/ru/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#mid-turn-user-messages).

### Системные сообщения, ограниченные ходом

Чтобы ограничить сообщение `role: "system"` текущим ходом, задайте его поле `clear_at`. Оно принимает одно из двух значений:

* `"never"` (по умолчанию): сообщение отображается на своей позиции в каждом запросе, который его включает. Отсутствие поля равнозначно этому значению.
* `"next_user_message"`: сообщение **ограничено ходом**. Его текст отображается, только пока после него в `messages` нет сообщения `role: "user"`. Сообщение пользователя, содержащее только блоки `tool_result`, здесь тоже считается сообщением пользователя. Как только появляется более позднее сообщение пользователя, сообщение **очищается**. Оно остаётся в массиве, но ничего не отображает и не расходует входные токены — ни в этом запросе, ни во всех последующих.

Системные сообщения, ограниченные ходом, находятся в бета-версии. Включите [бета-заголовок](https://platform.claude.com/docs/ru/api/beta-headers) `mid-conversation-system-clear-at-2026-08-21`. Без него `clear_at` отклоняется как неизвестное поле.

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

Основное применение — напоминание для каждого хода в цикле инструментов. Добавляйте напоминание после сообщения `tool_result` каждый раз, когда хотите, чтобы модель его увидела, и оставляйте все более ранние копии на своих местах. Модель видит только копии, идущие после последнего сообщения пользователя, поэтому напоминание никогда не накапливается. Ничто ранее в `messages` не меняется, поэтому [кэш подсказок](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching) продолжает совпадать. В Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 и Claude Haiku 5.5 это также сохраняет действительность последующих [блоков размышлений](https://platform.claude.com/docs/ru/build-with-claude/thinking#preserved-in-conversation): удаление более раннего напоминания изменило бы разговор перед этими блоками и привело бы к провалу проверки разговора, тогда как очищенное сообщение остаётся в массиве и оставляет этот разговор неизменным.

Следующий запрос — более поздний шаг агентного цикла. `messages[3]` отображалось в предыдущем запросе, когда было последним сообщением в массиве. Как только появляется `messages[5]` (более позднее сообщение пользователя), `messages[3]` очищается. Очищенное сообщение остаётся в массиве, поэтому разговор перед блоком размышлений в `messages[4]` не меняется, но модель больше не видит его текст. `messages[6]` и `messages[7]` отображаются оба, по порядку.

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

Правила для сообщений, ограниченных ходом:

* **Отправляйте очищенные сообщения повторно дословно.** Очищенное сообщение по-прежнему является частью истории разговора. Его пересоздание из текущего состояния (свежий подсчёт токенов, временная метка), удаление как избыточного или изменение его значения `clear_at` является редактированием более раннего сообщения. Кэш подсказок промахивается с этой точки, а в Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 и Claude Haiku 5.5 каждый блок размышлений, созданный после него, не проходит [проверку разговора](https://platform.claude.com/docs/ru/build-with-claude/thinking#preserved-in-conversation).
* **Только текст.** `content` — это один или несколько блоков `text` (или строка). Блоки `tool_addition` и `tool_removal` в сообщении в пределах хода возвращают ошибку 400, как и `output_config`. Для них используйте отдельное сообщение `role: "system"` без `clear_at`.
* **Никакого `cache_control` в его блоках.** Очищенное сообщение никогда не входит в ключ кэша, поэтому точка останова на нём никогда не совпала бы. Вместо этого поместите точку останова на последний блок предшествующего хода пользователя, как в примере. Поле верхнего уровня [автоматического кэширования](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching#automatic-caching) пропускает сообщения в пределах хода при выборе точки останова. В запросе, который очищает сообщение, повторно используемый кэшированный префикс заканчивается на ходе пользователя перед ним, поэтому повторно обрабатывается только один ход ассистента между этим сообщением и новым сообщением пользователя.
* **Правила размещения по-прежнему действуют**, независимо от того, очищено сообщение или нет. Сообщение в пределах хода должно следовать за ходом `user` (или ходом `assistant`, заканчивающимся результатом серверного инструмента) и предшествовать ходу `assistant` или завершать массив, как любое системное сообщение в середине диалога. Сообщение, завершающее массив, отображается всегда. Сообщение, за которым непосредственно следует другое сообщение `user`, вызывает ошибку 400, а не очищается: помещайте все результаты одного раунда инструментов в одно сообщение пользователя, а напоминания — после него.
* **Ходы ассистента не очищают его.** Предзаполненный или [приостановленный](https://platform.claude.com/docs/ru/build-with-claude/handling-stop-reasons#pause-turn) ход ассистента после сообщения, а также серверный цикл инструментов не добавляют сообщения пользователя, поэтому сообщение по-прежнему отображается при таком продолжении. Чтобы напоминание оставалось в поле зрения на протяжении клиентского цикла инструментов, добавляйте его снова после каждого сообщения `tool_result`.
* **Подсчёт токенов соответствует тому, что отображается.** Очищенное сообщение ничего не добавляет к `usage.input_tokens` или к [подсчёту токенов](https://platform.claude.com/docs/ru/build-with-claude/token-counting).
* **Импортированная история.** В транскрипте, который вы создаёте за один шаг (примеры few-shot, перенесённый диалог), сообщение в пределах хода, после которого уже есть ход ассистента и сообщение пользователя, очищено с первого запроса и никогда не отображается. Это правильное состояние для переносимого напоминания для каждого хода. Оставляйте `clear_at` незаданным только для сообщения, которое модель должна видеть в каждом запросе.

Ошибки валидации:

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

Первая — это ошибка, возвращаемая без бета-заголовка. В Google Cloud и [Claude в Amazon Bedrock](https://platform.claude.com/docs/ru/build-with-claude/claude-in-amazon-bedrock) отправляйте бета-значение в заголовке `anthropic-beta`, как и в Claude API (см. [Бета-заголовки](https://platform.claude.com/docs/ru/api/beta-headers)). При использовании [InvokeModel API](https://platform.claude.com/docs/ru/build-with-claude/claude-on-amazon-bedrock-legacy) Amazon Bedrock вместо этого поместите его в массив `anthropic_beta` тела запроса.

Через SDK задайте `clear_at` (csharp, go: `ClearAt`; java: `.clearAt()`; php: `clearAt`) в элементе `role: "system"` в `messages` и отправьте бета-заголовок. Следующий пример добавляет напоминание в пределах хода после хода пользователя; в следующем запросе, как только появляется более позднее сообщение пользователя, напоминание остаётся в массиве, но больше не отображается:

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

  ```bash CLI
  ant beta:messages create --beta mid-conversation-system-clear-at-2026-08-21 \
    --transform 'content.#(type=="text").text' --raw-output <<'YAML'
  model: claude-fable-5-1
  max_tokens: 4096
  messages:
    - role: user
      content: Draft a short status update on the database migration for the team channel.
    # Напоминание в рамках хода: отображается в этом ходе и очищается, когда появляется следующее сообщение пользователя.
    - role: system
      clear_at: next_user_message
      content: "The reader is on call: keep this reply under 50 words."
  YAML
  ```

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

  response = client.beta.messages.create(
      model="claude-fable-5-1",
      max_tokens=4096,
      messages=[
          {
              "role": "user",
              "content": "Draft a short status update on the database migration for the team channel.",
          },
          # Напоминание в рамках хода: отображается в текущем ходе и удаляется, когда появляется следующее сообщение пользователя.
          {
              "role": "system",
              "clear_at": "next_user_message",
              "content": "The reader is on call: keep this reply under 50 words.",
          },
      ],
      betas=["mid-conversation-system-clear-at-2026-08-21"],
  )

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

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

  const response = await client.beta.messages.create({
    model: "claude-fable-5-1",
    max_tokens: 4096,
    messages: [
      {
        role: "user",
        content: "Draft a short status update on the database migration for the team channel."
      },
      // Напоминание в рамках хода: отображается в текущем ходе и сбрасывается, когда появляется следующее сообщение пользователя.
      {
        role: "system",
        clear_at: "next_user_message",
        content: "The reader is on call: keep this reply under 50 words."
      }
    ],
    betas: ["mid-conversation-system-clear-at-2026-08-21"]
  });

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

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

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(new MessageCreateParams
  {
      Model = Messages::Model.ClaudeFable5_1,
      MaxTokens = 4096,
      Messages =
      [
          new() { Role = Role.User, Content = "Draft a short status update on the database migration for the team channel." },
          // Напоминание в рамках хода: отображается в текущем ходе и очищается, когда появляется следующее сообщение пользователя.
          new()
          {
              Role = Role.System,
              ClearAt = ClearAt.NextUserMessage,
              Content = "The reader is on call: keep this reply under 50 words.",
          },
      ],
      Betas = [AnthropicBeta.MidConversationSystemClearAt2026_08_21],
  });

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

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

  response, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeFable5_1,
  	MaxTokens: 4096,
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Draft a short status update on the database migration for the team channel.")),
  		// Напоминание в рамках хода: отображается в текущем ходе и сбрасывается, когда появляется следующее сообщение пользователя.
  		{
  			Role:    anthropic.BetaMessageParamRoleSystem,
  			ClearAt: anthropic.BetaMessageParamClearAtNextUserMessage,
  			Content: []anthropic.BetaContentBlockParamUnion{anthropic.NewBetaTextBlock("The reader is on call: keep this reply under 50 words.")},
  		},
  	},
  	Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaMidConversationSystemClearAt2026_08_21},
  })
  if err != nil {
  	log.Fatal(err)
  }

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

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

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

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_FABLE_5_1)
          .maxTokens(4096L)
          .addBeta(AnthropicBeta.MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21)
          .addUserMessage("Draft a short status update on the database migration for the team channel.")
          // Напоминание в рамках хода: отображается в текущем ходе и сбрасывается, когда появляется следующее сообщение пользователя.
          .addMessage(BetaMessageParam.builder()
              .role(BetaMessageParam.Role.SYSTEM)
              .clearAt(BetaMessageParam.ClearAt.NEXT_USER_MESSAGE)
              .content("The reader is on call: keep this reply under 50 words.")
              .build())
          .build();

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

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

  $client = new Client();

  $response = $client->beta->messages->create(
      model: 'claude-fable-5-1',
      maxTokens: 4096,
      messages: [
          BetaMessageParam::with(role: 'user', content: 'Draft a short status update on the database migration for the team channel.'),
          // Напоминание в рамках хода: отображается в этом ходе и очищается, когда появляется следующее сообщение пользователя.
          BetaMessageParam::with(
              role: 'system',
              clearAt: 'next_user_message',
              content: 'The reader is on call: keep this reply under 50 words.',
          ),
      ],
      betas: [AnthropicBeta::MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21],
  );

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

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

  response = client.beta.messages.create(
    model: "claude-fable-5-1",
    max_tokens: 4096,
    messages: [
      {role: "user", content: "Draft a short status update on the database migration for the team channel."},
      # Напоминание в рамках хода: отображается в этом ходе и очищается, когда появляется следующее сообщение пользователя.
      {role: "system", clear_at: :next_user_message, content: "The reader is on call: keep this reply under 50 words."}
    ],
    betas: [Anthropic::AnthropicBeta::MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21]
  )

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

## Сочетание с кэшированием подсказок

Системные сообщения в середине разговора и [кэширование подсказок](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching) спроектированы для совместного использования:

* **Включайте кэширование явно.** Кэширование происходит только тогда, когда запрос включает `cache_control` — либо поле верхнего уровня [автоматического кэширования](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching#automatic-caching), либо [явную точку разрыва](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching#explicit-cache-breakpoints) на блоке содержимого. Системное сообщение в середине разговора само по себе не создаёт запись кэша, а без включённого кэширования нет экономии, которую можно было бы сохранить.
* **Кэшируйте стабильный префикс как обычно.** Поместите `cache_control` на последний блок, который остаётся неизменным между запросами, будь то конец поля верхнего уровня `system`, конец ваших определений инструментов или стабильная точка в истории сообщений.
* **Добавляйте системное сообщение после точки разрыва.** Поскольку оно идёт после кэшированного префикса, оно не меняет хэш префикса, и кэш по-прежнему срабатывает.
* **Системное сообщение в середине разговора само по себе кэшируемо.** Как только оно оказывается в разговоре, оно становится частью стабильной истории. На следующем ходе вы можете переместить точку разрыва кэша за него (или положиться на [автоматическое кэширование](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching#automatic-caching), чтобы оно сделало это), и системное сообщение читается из кэша, как любой другой ход.

Избегайте редактирования или удаления уже отправленного системного сообщения в середине разговора. Как и любое другое изменение более ранних сообщений, это делает кэш недействительным с этой точки и далее. В Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 и Claude Haiku 5.5 это также делает недействительными [блоки размышлений](https://platform.claude.com/docs/ru/build-with-claude/thinking#preserved-in-conversation) во всех последующих ходах ассистента. Для указаний, которые должны применяться только к одному ходу, используйте [системное сообщение в пределах хода](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) и оставьте его на месте. Если инструкция должна меняться, добавьте новое системное сообщение, а не переписывайте старое. Последовательные системные сообщения принимаются и рассматриваются как единый системный раздел, который в целом подчиняется тому же правилу размещения.

## Ограничения

* **Не для первого сообщения.** Сообщение `system` с содержимым не может быть первой записью в `messages`. Для инструкций, действующих с самого начала, используйте поле верхнего уровня `system`.

* **Размещение ограничено.** Сообщение `system` с содержимым (блоками `text`, `tool_addition` или `tool_removal`) должно следовать непосредственно за ходом `user` (в том числе за ходом `user` с блоками `tool_result`) или за ходом `assistant`, заканчивающимся результатом серверного инструмента. Кроме того, оно должно предшествовать ходу `assistant` или завершать массив. Оно не может находиться между блоком `tool_use` и его `tool_result`. Размещение в другом месте возвращает ошибку 400.

  * Исключение: блоки `tool_addition` и `tool_removal` не принимаются сразу после [приостановленного](https://platform.claude.com/docs/ru/build-with-claude/handling-stop-reasons#pause-turn) хода `assistant` (заканчивающегося результатом серверного инструмента), хотя блоки `text` там допустимы. Сначала возобновите приостановленный ход, а затем отправьте изменение инструментов в следующем сообщении `system`.
  * Сообщение с пустым `content`, которое только задаёт [`output_config.effort`](https://platform.claude.com/docs/ru/build-with-claude/effort#change-effort-mid-conversation-beta), ничего не отображает на своей позиции и допускается в любом месте `messages`, в том числе первым или между ходом `assistant` и ходом `user`.
  * Несколько сообщений `system` подряд оцениваются вместе. Если рядом с сообщением, задающим только effort, добавить сообщение с текстом, на всю группу распространяется правило для сообщений с содержимым.

* **Сообщения, ограниченные ходом, содержат только текст и отправляются повторно без изменений.** Сообщение `clear_at: "next_user_message"` не может содержать `tool_addition`, `tool_removal`, `output_config` или `cache_control`. После очистки оно должно оставаться в `messages` байт в байт во всех последующих запросах. См. [Системные сообщения, ограниченные ходом](https://platform.claude.com/docs/ru/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages).

* **Не место для недоверенного содержимого.** Claude рассматривает системное содержимое как инструкции оператора и следует им. Не помещайте в системное сообщение текст извне разговора, например необработанный вывод инструментов, извлечённые документы или веб-содержимое: это наделит такой текст полномочиями уровня оператора. Храните такие данные в блоках `tool_result` и продолжайте следовать рекомендациям из раздела [Защита от джейлбрейков и внедрения подсказок](https://platform.claude.com/docs/ru/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks).

## Связанные материалы

<CardGroup cols={2}>
  <Card title="Кэширование подсказок" icon="bolt" href="https://platform.claude.com/docs/ru/build-with-claude/prompt-caching">
    Как работает кэширование, где размещать точки разрыва и как читать поля использования кэша.
  </Card>

  <Card title="Диагностика кэша" icon="magnifying-glass" href="https://platform.claude.com/docs/ru/build-with-claude/cache-diagnostics">
    Выясните, где именно разошлись два запроса, когда ожидаемое попадание в кэш не происходит.
  </Card>

  <Card title="Использование Messages API" icon="message" href="https://platform.claude.com/docs/ru/build-with-claude/working-with-messages">
    Структура сообщений, многоходовые разговоры и поле `system`.
  </Card>

  <Card title="Лучшие практики составления подсказок" icon="text" href="https://platform.claude.com/docs/ru/build-with-claude/prompt-engineering/claude-prompting-best-practices">
    Написание эффективных подсказок и системных инструкций.
  </Card>

  <Card title="Использование инструментов с Claude" icon="wrench" href="https://platform.claude.com/docs/ru/agents-and-tools/tool-use/overview">
    Как блоки `tool_use` и `tool_result` структурированы в массиве `messages`.
  </Card>
</CardGroup>
