---
title: Вызов API на самостоятельно размещаемом сервере
url: https://platform.claude.com/docs/ru/managed-agents/self-hosted/call-the-api
description: Направьте официальный SDK, cURL или ant CLI на ваш самостоятельно размещаемый сервер Claude Managed Agents, запустите сеанс и прочитайте ответ агента. Затем при необходимости подключите собственные воркеры.
---

<Note>
  Чтобы запросить доступ к самостоятельно размещаемому Claude Managed Agents, обратитесь к команде, работающей с вашей учётной записью в Anthropic.
</Note>

Самостоятельно размещаемый сервер Claude Managed Agents предоставляет тот же API, что и размещённый сервис [Managed Agents](https://platform.claude.com/docs/ru/managed-agents/overview) от Anthropic. Ваш код вызывает его с помощью официального SDK, cURL или `ant` CLI. Меняются две вещи: «base URL» (базовый URL) — это адрес вашего сервера, а ключ API — это ваш [ключ API сервера](https://platform.claude.com/docs/ru/managed-agents/self-hosted#the-three-credentials) вместо ключа Claude API.

Чтобы создавать агентов и запускать сеансы в браузере, см. [Использование консоли на вашем сервере](https://platform.claude.com/docs/ru/managed-agents/self-hosted/console).

## Предварительные требования

* **Работающий сервер:** запустите его, как описано в разделе [Начало работы с самостоятельно размещаемым Claude Managed Agents](https://platform.claude.com/docs/ru/managed-agents/self-hosted/quickstart) или [Развёртывание в Kubernetes](https://platform.claude.com/docs/ru/managed-agents/self-hosted/kubernetes).
* **Доступ к серверу:** если сервер запускает кто-то другой, узнайте у него адрес сервера и способ аутентификации. Если используется единый вход, см. [Вход разработчиков из терминала](https://platform.claude.com/docs/ru/managed-agents/self-hosted/configure#let-developers-log-in-from-a-terminal).
* **CLI `ant`:** установите последнюю версию, как показано в [кратком руководстве по CLI](https://platform.claude.com/docs/ru/cli-sdks-libraries/cli/quickstart#installation).

## Направление клиента на ваш сервер

SDK и CLI `ant` читают адрес сервера из `ANTHROPIC_BASE_URL`, а ключ API — из `ANTHROPIC_API_KEY`. Задайте обе переменные в терминале, который вы выделяете для этого сервера.

Для [стека из краткого руководства](https://platform.claude.com/docs/ru/managed-agents/self-hosted/quickstart) выполните эти команды из каталога, в котором находится ваш файл `.env`:

```bash
export ANTHROPIC_BASE_URL=http://127.0.0.1:8400
export ANTHROPIC_API_KEY=$(grep '^CMA_SERVER__API_KEY=' .env | cut -d= -f2)
```

В Kubernetes задайте эти две переменные, как показано в разделе [Запуск сеанса](https://platform.claude.com/docs/ru/managed-agents/self-hosted/kubernetes#run-a-session), и оставьте запущенным перенаправление порта.

В этом терминале каждая команда `ant`, например `ant beta:agents list`, обращается к вашему серверу. Не запускайте в этом терминале Claude Code или `docker compose`, поскольку они читают те же переменные.

## Запуск сеанса

Для сеанса нужны идентификатор агента и идентификатор окружения:

* **Агент:** создайте его, как показано в разделе [Создание агента](https://platform.claude.com/docs/ru/managed-agents/agent-setup#create-an-agent), направив клиент на ваш сервер. Если вы отправляете необработанные HTTP-запросы, замените `https://api.anthropic.com` в URL на `$ANTHROPIC_BASE_URL`.
* **Окружение:** стек из краткого руководства создаёт окружение с именем `compose-sandbox`, а Helm-чарты создают окружение с именем `default`. `ant beta:environments list` выводит имя и идентификатор каждого окружения. Для ваших собственных воркеров это идентификатор, который административный CLI вывел в разделе [Запуск собственных воркеров](https://platform.claude.com/docs/ru/managed-agents/self-hosted/call-the-api#point-a-worker-at-your-server).

Поместите оба идентификатора в вашу оболочку вместо этих примеров идентификаторов:

```bash
export AGENT_ID=agent_011CYm1BLqPXpQRk5khsSXrs
export ENVIRONMENT_ID=env_01595EKxaaTTGwwY3kyXdtbs
```

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

<CodeGroup>
  ```bash cURL
  curl -sS --fail-with-body "$ANTHROPIC_BASE_URL/v1/sessions" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2026-10-21" \
    -H "anthropic-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    -d '{
      "agent": "'"$AGENT_ID"'",
      "environment_id": "'"$ENVIRONMENT_ID"'",
      "initial_events": [
        {
          "type": "user.message",
          "content": [{"type": "text", "text": "List the files in the working directory."}]
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:sessions create --agent "$AGENT_ID" --environment-id "$ENVIRONMENT_ID" \
    --initial-event '{type: user.message, content: [{type: text, text: "List the files in the working directory."}]}'
  ```

  ```python Python
  import os

  from anthropic import Anthropic

  client = Anthropic()

  session = client.beta.sessions.create(
      agent=os.environ["AGENT_ID"],
      environment_id=os.environ["ENVIRONMENT_ID"],
      initial_events=[
          {
              "type": "user.message",
              "content": [
                  {"type": "text", "text": "List the files in the working directory."}
              ],
          },
      ],
  )
  print(session.id)
  ```

  ```typescript TypeScript
  import Anthropic from "@anthropic-ai/sdk";

  const client = new Anthropic();

  const session = await client.beta.sessions.create({
    agent: process.env["AGENT_ID"]!,
    environment_id: process.env["ENVIRONMENT_ID"]!,
    initial_events: [
      {
        type: "user.message",
        content: [{ type: "text", text: "List the files in the working directory." }]
      }
    ]
  });
  console.log(session.id);
  ```

  ```csharp C#
  using System;
  using Anthropic;
  using Anthropic.Models.Beta.Agents;
  using Anthropic.Models.Beta.Sessions;
  using Anthropic.Models.Beta.Sessions.Events;

  AnthropicClient client = new();

  var session = await client.Beta.Sessions.Create(new()
  {
      Agent = Environment.GetEnvironmentVariable("AGENT_ID")!,
      EnvironmentID = Environment.GetEnvironmentVariable("ENVIRONMENT_ID")!,
      InitialEvents =
      [
          new BetaManagedAgentsUserMessageEventParams
          {
              Content =
              [
                  new BetaManagedAgentsTextBlock
                  {
                      Text = "List the files in the working directory.",
                  },
              ],
          },
      ],
  });
  Console.WriteLine(session.ID);
  ```

  ```go Go
  package main

  import (
  	"context"
  	"fmt"
  	"os"

  	"github.com/anthropics/anthropic-sdk-go/v2"
  )

  func main() {
  	client := anthropic.NewClient()

  	session, err := client.Beta.Sessions.New(context.Background(), anthropic.BetaSessionNewParams{
  		Agent: anthropic.BetaSessionNewParamsAgentUnion{
  			OfString: anthropic.String(os.Getenv("AGENT_ID")),
  		},
  		EnvironmentID: os.Getenv("ENVIRONMENT_ID"),
  		InitialEvents: []anthropic.BetaSessionNewParamsInitialEventUnion{{
  			OfUserMessage: &anthropic.BetaManagedAgentsUserMessageEventParams{
  				Content: []anthropic.BetaManagedAgentsUserMessageEventParamsContentUnion{{
  					OfText: &anthropic.BetaManagedAgentsTextBlockParam{
  						Text: "List the files in the working directory.",
  					},
  				}},
  			},
  		}},
  	})
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(session.ID)
  }
  ```

  ```java Java
  import com.anthropic.client.AnthropicClient;
  import com.anthropic.client.okhttp.AnthropicOkHttpClient;
  import com.anthropic.models.beta.sessions.SessionCreateParams;
  import com.anthropic.models.beta.sessions.events.BetaManagedAgentsUserMessageEventParams;

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

      var session = client.beta().sessions().create(SessionCreateParams.builder()
          .agent(System.getenv("AGENT_ID"))
          .environmentId(System.getenv("ENVIRONMENT_ID"))
          .addInitialEvent(BetaManagedAgentsUserMessageEventParams.builder()
              .addTextContent("List the files in the working directory.")
              .build())
          .build());
      IO.println(session.id());
  }
  ```

  ```php PHP
  <?php

  use Anthropic\Client;

  $client = new Client();

  $session = $client->beta->sessions->create(
      agent: (string) getenv('AGENT_ID'),
      environmentID: (string) getenv('ENVIRONMENT_ID'),
      initialEvents: [
          [
              'type' => 'user.message',
              'content' => [['type' => 'text', 'text' => 'List the files in the working directory.']],
          ],
      ],
  );
  echo $session->id, "\n";
  ```

  ```ruby Ruby
  require "anthropic"

  client = Anthropic::Client.new

  session = client.beta.sessions.create(
    agent: ENV.fetch("AGENT_ID"),
    environment_id: ENV.fetch("ENVIRONMENT_ID"),
    initial_events: [
      {
        type: :"user.message",
        content: [{type: :text, text: "List the files in the working directory."}]
      }
    ]
  )
  puts session.id
  ```
</CodeGroup>

Ответ содержит идентификатор сеанса, который начинается с `sesn_`. Агент сразу приступает к работе. Его встроенные инструменты, такие как `bash`, выполняются на «worker» (воркере), который обслуживает окружение.

Чтобы наблюдать за сеансом, откройте [консоль на вашем сервере](https://platform.claude.com/docs/ru/managed-agents/self-hosted/console) в браузере, выберите **Sessions**, а затем выберите сеанс. Сеанс, запущенный с ключом API сервера, как на этой странице, виден только администраторам.

Чтобы вместо этого отслеживать сеанс в терминале, передайте его идентификатор в команду [`ant beta:sessions connect`](https://platform.claude.com/docs/ru/cli-sdks-libraries/cli/sessions-connect):

```bash
ant beta:sessions connect sesn_011CZkZAtmR3yMPDzynEDxu7
```

О других возможностях сеанса, например о закреплении версии агента, см. [Запуск сеанса](https://platform.claude.com/docs/ru/managed-agents/sessions).

## Отправка сообщения и чтение ответа

Поместите идентификатор вашего сеанса в оболочку вместо этого примера идентификатора:

```bash
export SESSION_ID=sesn_011CZkZAtmR3yMPDzynEDxu7
```

Дождитесь, пока сеанс перейдёт в режим ожидания, прежде чем запускать следующий пример. Пример прекращает чтение, когда ход завершается. Если предыдущий ход ещё выполняется, его завершение может остановить пример до того, как придёт ответ на ваше сообщение. Консоль и `ant beta:sessions connect` показывают статус сеанса.

Следующий пример отправляет сообщение и выводит ответ агента. Сначала он открывает поток событий сеанса, потому что поток доставляет только те события, которые происходят после его открытия:

<CodeGroup exclude="shell">
  <CodeGroupItem language="cURL">
    Этот рабочий процесс требует больше логики, чем одна команда оболочки. Используйте [Anthropic SDK](https://platform.claude.com/docs/ru/cli-sdks-libraries/overview) для его запуска.
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    Этот рабочий процесс требует больше логики, чем одна команда оболочки. Чтобы отправлять сообщения и читать ответы в терминале, используйте [`ant beta:sessions connect`](https://platform.claude.com/docs/ru/cli-sdks-libraries/cli/sessions-connect).
  </CodeGroupItem>

  ```python Python
  import os

  from anthropic import Anthropic

  client = Anthropic()
  session_id = os.environ["SESSION_ID"]

  with client.beta.sessions.events.stream(session_id) as stream:
      client.beta.sessions.events.send(
          session_id,
          events=[
              {
                  "type": "user.message",
                  "content": [
                      {"type": "text", "text": "Summarize what you did in one sentence."}
                  ],
              },
          ],
      )

      for event in stream:
          match event.type:
              case "agent.message":
                  for block in event.content:
                      if block.type == "text":
                          print(block.text, end="")
              case "session.error":
                  error_message = event.error.message if event.error else "unknown"
                  print(f"\n[Error: {error_message}]")
              case "session.status_idle":
                  if event.stop_reason.type != "requires_action":
                      break
              case "session.status_terminated":
                  break
  ```

  ```typescript TypeScript
  import Anthropic from "@anthropic-ai/sdk";

  const client = new Anthropic();
  const sessionId = process.env["SESSION_ID"]!;

  const stream = await client.beta.sessions.events.stream(sessionId);
  await client.beta.sessions.events.send(sessionId, {
    events: [
      {
        type: "user.message",
        content: [{ type: "text", text: "Summarize what you did in one sentence." }]
      }
    ]
  });

  events: for await (const event of stream) {
    switch (event.type) {
      case "agent.message":
        for (const block of event.content) {
          if (block.type === "text") {
            process.stdout.write(block.text);
          }
        }
        break;
      case "session.error":
        console.log(`\n[Error: ${event.error?.message ?? "unknown"}]`);
        break;
      case "session.status_idle":
        if (event.stop_reason.type !== "requires_action") {
          break events;
        }
        break;
      case "session.status_terminated":
        break events;
    }
  }
  ```

  ```csharp C#
  using System;
  using Anthropic;
  using Anthropic.Models.Beta.Sessions.Events;

  AnthropicClient client = new();
  var sessionId = Environment.GetEnvironmentVariable("SESSION_ID")!;

  using var stream = await client.Beta.Sessions.Events.WithRawResponse.StreamStreaming(sessionId);
  await client.Beta.Sessions.Events.Send(sessionId, new()
  {
      Events =
      [
          new BetaManagedAgentsUserMessageEventParams
          {
              Content = [new BetaManagedAgentsTextBlock { Text = "Summarize what you did in one sentence." }],
          },
      ],
  });

  await foreach (var streamEvent in stream.Enumerate())
  {
      if (streamEvent.Value is BetaManagedAgentsAgentMessageEvent message)
      {
          foreach (var block in message.Content)
          {
              if (block.Value is BetaManagedAgentsTextBlock textBlock)
              {
                  Console.Write(textBlock.Text);
              }
          }
      }
      else if (streamEvent.Value is BetaManagedAgentsSessionErrorEvent error)
      {
          Console.WriteLine($"\n[Error: {error.Error?.Message ?? "unknown"}]");
      }
      else if (streamEvent.Value is BetaManagedAgentsSessionStatusIdleEvent idle
          && idle.StopReason?.Value is not BetaManagedAgentsSessionRequiresAction)
      {
          break;
      }
      else if (streamEvent.Value is BetaManagedAgentsSessionStatusTerminatedEvent)
      {
          break;
      }
  }
  ```

  ```go Go
  package main

  import (
  	"cmp"
  	"context"
  	"fmt"
  	"os"

  	"github.com/anthropics/anthropic-sdk-go/v2"
  )

  func main() {
  	client := anthropic.NewClient()
  	ctx := context.Background()
  	sessionID := os.Getenv("SESSION_ID")

  	stream := client.Beta.Sessions.Events.StreamEvents(ctx, sessionID, anthropic.BetaSessionEventStreamParams{})
  	defer stream.Close()

  	if _, err := client.Beta.Sessions.Events.Send(ctx, sessionID, anthropic.BetaSessionEventSendParams{
  		Events: []anthropic.BetaManagedAgentsEventParamsUnion{{
  			OfUserMessage: &anthropic.BetaManagedAgentsUserMessageEventParams{
  				Content: []anthropic.BetaManagedAgentsUserMessageEventParamsContentUnion{{
  					OfText: &anthropic.BetaManagedAgentsTextBlockParam{
  						Text: "Summarize what you did in one sentence.",
  					},
  				}},
  			},
  		}},
  	}); err != nil {
  		panic(err)
  	}

  events:
  	for stream.Next() {
  		switch event := stream.Current().AsAny().(type) {
  		case anthropic.BetaManagedAgentsAgentMessageEvent:
  			for _, block := range event.Content {
  				if block.Type == "text" {
  					fmt.Print(block.Text)
  				}
  			}
  		case anthropic.BetaManagedAgentsSessionErrorEvent:
  			fmt.Printf("\n[Error: %s]\n", cmp.Or(event.Error.Message, "unknown"))
  		case anthropic.BetaManagedAgentsSessionStatusIdleEvent:
  			if _, paused := event.StopReason.AsAny().(anthropic.BetaManagedAgentsSessionRequiresAction); !paused {
  				break events
  			}
  		case anthropic.BetaManagedAgentsSessionStatusTerminatedEvent:
  			break events
  		}
  	}
  	if err := stream.Err(); err != nil {
  		panic(err)
  	}
  }
  ```

  ```java Java
  import com.anthropic.client.AnthropicClient;
  import com.anthropic.client.okhttp.AnthropicOkHttpClient;
  import com.anthropic.core.JsonObject;
  import com.anthropic.models.beta.sessions.events.BetaManagedAgentsUserMessageEventParams;
  import com.anthropic.models.beta.sessions.events.EventSendParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();
      var sessionId = System.getenv("SESSION_ID");

      try (var stream = client.beta().sessions().events().streamStreaming(sessionId)) {
          client.beta().sessions().events().send(
              sessionId,
              EventSendParams.builder()
                  .addEvent(BetaManagedAgentsUserMessageEventParams.builder()
                      .addTextContent("Summarize what you did in one sentence.")
                      .build())
                  .build()
          );

          events:
          for (var event : stream) {
              switch (event.type().value()) {
                  case AGENT_MESSAGE -> {
                      for (var block : event.asAgentMessage().content()) {
                          block.text().ifPresent(textBlock -> IO.print(textBlock.text()));
                      }
                  }
                  case SESSION_ERROR -> {
                      var errorMessage =
                          event.asSessionError().error()._json().orElse(null) instanceof JsonObject json
                              ? json.values().get("message").asStringOrThrow()
                              : "unknown";
                      IO.println("\n[Error: " + errorMessage + "]");
                  }
                  case SESSION_STATUS_IDLE -> {
                      if (!event.asSessionStatusIdle().stopReason().isRequiresAction()) {
                          break events;
                      }
                  }
                  case SESSION_STATUS_TERMINATED -> {
                      break events;
                  }
                  default -> {}
              }
          }
      }
  }
  ```

  ```php PHP
  <?php

  use Anthropic\Beta\Sessions\Events\ManagedAgentsAgentMessageEvent;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsSessionErrorEvent;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsSessionRequiresAction;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsSessionStatusIdleEvent;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsSessionStatusTerminatedEvent;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsTextBlock;
  use Anthropic\Client;

  $client = new Client();
  $sessionId = (string) getenv('SESSION_ID');

  $stream = $client->beta->sessions->events->streamStream($sessionId);
  $client->beta->sessions->events->send(
      $sessionId,
      events: [
          [
              'type' => 'user.message',
              'content' => [['type' => 'text', 'text' => 'Summarize what you did in one sentence.']],
          ],
      ],
  );

  foreach ($stream as $event) {
      switch (true) {
          case $event instanceof ManagedAgentsAgentMessageEvent:
              foreach ($event->content as $block) {
                  if ($block instanceof ManagedAgentsTextBlock) {
                      echo $block->text;
                  }
              }
              break;
          case $event instanceof ManagedAgentsSessionErrorEvent:
              printf("\n[Error: %s]\n", $event->error->message);
              break;
          case $event instanceof ManagedAgentsSessionStatusIdleEvent:
              if (!($event->stopReason instanceof ManagedAgentsSessionRequiresAction)) {
                  break 2; // Break foreach loop
              }
              break;
          case $event instanceof ManagedAgentsSessionStatusTerminatedEvent:
              break 2; // Break foreach loop
      }
  }
  $stream->close();
  ```

  ```ruby Ruby
  require "anthropic"

  client = Anthropic::Client.new
  session_id = ENV.fetch("SESSION_ID")

  stream = client.beta.sessions.events.stream_events(session_id)

  client.beta.sessions.events.send_(
    session_id,
    events: [{
      type: "user.message",
      content: [{type: "text", text: "Summarize what you did in one sentence."}]
    }]
  )

  stream.each do |event|
    case event
    when Anthropic::Beta::Sessions::BetaManagedAgentsAgentMessageEvent
      event.content.each do |block|
        print block.text if block.is_a?(Anthropic::Beta::Sessions::BetaManagedAgentsTextBlock)
      end
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionErrorEvent
      puts "\n[Error: #{event.error&.message || "unknown"}]"
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionStatusIdleEvent
      break unless event.stop_reason.is_a?(Anthropic::Beta::Sessions::BetaManagedAgentsSessionRequiresAction)
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionStatusTerminatedEvent
      break
    else
      # игнорируем прочие типы событий
    end
  end
  ```
</CodeGroup>

Помимо вывода текста `agent.message`, цикл обрабатывает три события:

* **`session.status_idle`:** цикл завершается, если только `stop_reason.type` события не равен `requires_action`.
* **`session.status_terminated`:** цикл завершается.
* **`session.error`:** цикл выводит сообщение об ошибке и продолжает чтение, потому что сервер может повторить неудавшийся вызов модели и завершить ход.

`requires_action` означает, что сеанс приостановлен для вызова инструмента. То, что завершает паузу, зависит от вызова:

* **Вызов пользовательского инструмента или запрос на подтверждение вызова инструмента:** ответить на него может только ваш код. Если ваш агент использует что-либо из этого, см. [Ответ на вызовы инструментов, приостанавливающие сеанс](https://platform.claude.com/docs/ru/managed-agents/events-and-streaming#answer-tool-calls-that-pause-the-session).
* **Вызов инструмента, который выполняет воркер, например `bash`:** Такой вызов обычно не приостанавливает сеанс. Если ни один воркер не берёт вызов примерно в течение 3 минут, сеанс приостанавливается, пока воркер не вернёт результат. В этом случае вашему коду не нужно ничего отвечать. Держите поток открытым, и ход возобновится, когда воркер выполнит вызов.

О других событиях, которые отправляет сеанс, и о том, как переподключиться, не пропустив ни одного из них, см. [Поток событий сеанса](https://platform.claude.com/docs/ru/managed-agents/events-and-streaming).

## Передача данных в сеанс и из него

Данные попадают в сеанс и покидают его через рабочий каталог воркера.

В стеке из краткого руководства контейнер каждого сеанса запускается с пустым каталогом `/workspace`, если не считать клонов репозиториев сеанса. По умолчанию примерно через минуту после окончания хода контейнер завершается, и Docker удаляет его вместе с этим каталогом. Всё, что сеанс должен сохранить, должно быть выведено до этого через вызов инструмента, например загрузку или `git push`.

Кроме того, контейнер завершается примерно через час после запуска, даже посреди хода. Никакая настройка этого не меняет. Ход продолжается в новом контейнере, обычно через минуту-две, и ваш клиент не получает никакого события о переключении. У переключения есть два последствия:

* **Команды:** всё, что выполняется в старом контейнере, останавливается. Новый контейнер снова выполняет прерванный вызов инструмента с самого начала, но ничто не перезапускает команду, которую агент оставил выполняться в фоновом режиме.
* **Файлы:** каталог `/workspace` нового контейнера снова пуст, если не считать новых клонов репозиториев сеанса.

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

В Kubernetes сеанс сохраняет один под не более чем примерно на час, и ход продолжается таким же образом. Отличаются две вещи: новый под находит файлы сеанса в `/workspace`, и он запускается примерно через 6 минут после остановки старого пода.

Для воркеров, которые вы запускаете сами, поместите входные файлы в рабочий каталог перед отправкой сообщения, которому они нужны. После этого читайте из него выходные файлы.

Если вы сами запускаете контейнер для каждого сеанса, подключите каталог с входными файлами сеанса в качестве рабочего каталога контейнера. Соберите из него выходные файлы после завершения контейнера. См. [Подготовка файлов для сеанса](https://platform.claude.com/docs/ru/managed-agents/self-hosted-sandboxes-workers#stage-files-for-a-session).

## Другие примеры в руководствах по размещённому сервису

В руководствах по размещённому сервису объясняются [основные понятия](https://platform.claude.com/docs/ru/managed-agents/overview#core-concepts) API и приводятся примеры для каждой функции. Их примеры SDK и CLI вызывают ваш сервер, если запускать их в терминале, где заданы `ANTHROPIC_BASE_URL` и `ANTHROPIC_API_KEY`. В их примерах cURL указан адрес `https://api.anthropic.com`, поэтому перед запуском такого примера замените этот адрес на `$ANTHROPIC_BASE_URL`.

Для некоторых функций сначала нужно задать настройку на вашем сервере или изменить пример:

| Задача                                                                     | Руководство по размещённому сервису                                                                                                                                                | На вашем сервере                                                                                                                                                                                                                                                                                                                                          |
| -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Задание модели, системной подсказки и версий агента                        | [Определение агента](https://platform.claude.com/docs/ru/managed-agents/agent-setup)                                                                                               | Некоторые поля [зависят от вашего поставщика инференса](https://platform.claude.com/docs/ru/managed-agents/self-hosted/differences#differences-that-depend-on-your-inference-provider).                                                                                                                                                                   |
| Выбор встроенных инструментов или добавление пользовательских инструментов | [Инструменты](https://platform.claude.com/docs/ru/managed-agents/tools)                                                                                                            | Чтобы использовать веб-инструменты, сначала включите их, как описано в разделе [Веб-инструментам нужна настройка сервера](https://platform.claude.com/docs/ru/managed-agents/self-hosted/differences#web-tools-need-a-server-setting). Какие из них доступны, зависит от вашего поставщика инференса.                                                     |
| Подключение сервера MCP и хранение его токена                              | [Коннектор MCP](https://platform.claude.com/docs/ru/managed-agents/mcp-connector) и [Аутентификация с помощью хранилищ](https://platform.claude.com/docs/ru/managed-agents/vaults) | Добавьте хост сервера MCP в [список разрешённых серверов MCP](https://platform.claude.com/docs/ru/managed-agents/self-hosted/differences#mcp-servers-need-an-allowlist-entry). Храните токен как учётные данные `static_bearer`.                                                                                                                          |
| Добавление навыков агенту                                                  | [Навыки](https://platform.claude.com/docs/ru/managed-agents/skills)                                                                                                                | Загружайте каждый навык в виде отдельных файлов, поскольку ваш сервер не принимает zip-архивы. [Готовые навыки](https://platform.claude.com/docs/ru/managed-agents/self-hosted/differences#features-that-arent-available) из примеров этого руководства недоступны.                                                                                       |
| Сохранение памяти между сеансами                                           | [Использование памяти агента](https://platform.claude.com/docs/ru/managed-agents/memory)                                                                                           | Если вы запускаете собственные воркеры, предоставьте им доступный для записи каталог `/mnt/memory`, как в разделе [Хранилища памяти в самостоятельно размещаемых песочницах](https://platform.claude.com/docs/ru/managed-agents/self-hosted-sandboxes-memory).                                                                                            |
| Передача работы другим агентам                                             | [Оркестрация нескольких агентов](https://platform.claude.com/docs/ru/managed-agents/multiagent-orchestration)                                                                      | Замените блок `multiagent_20261001` в примерах этого руководства на [блок `coordinator`](https://platform.claude.com/docs/ru/managed-agents/self-hosted/differences#features-that-behave-differently).                                                                                                                                                    |
| Работа в репозитории Git                                                   | [Доступ к GitHub](https://platform.claude.com/docs/ru/managed-agents/github)                                                                                                       | Укажите Git-хост в настройках вашего сервера, как описано в разделе [Репозиториям Git нужна запись в списке разрешённых](https://platform.claude.com/docs/ru/managed-agents/self-hosted/differences#git-repositories-need-an-allowlist-entry). Примеру агента из этого руководства также нужен `api.githubcopilot.com` в списке разрешённых серверов MCP. |
| Проверка работы оценщиком по критериям                                     | [Определение результатов](https://platform.claude.com/docs/ru/managed-agents/define-outcomes)                                                                                      | Отправляйте критерии в виде текста. Files API недоступен, поэтому [собирайте выходные файлы](https://platform.claude.com/docs/ru/managed-agents/self-hosted/call-the-api#move-data-in-and-out-of-a-session) из рабочего каталога.                                                                                                                         |
| Отслеживание сеанса и ответ на его вызовы инструментов                     | [Поток событий сеанса](https://platform.claude.com/docs/ru/managed-agents/events-and-streaming)                                                                                    | Первый пример из этого руководства закрывает поток при любой паузе, поэтому вместо него начните с цикла из раздела [Отправка сообщения и чтение ответа](https://platform.claude.com/docs/ru/managed-agents/self-hosted/call-the-api#send-a-message-and-read-the-reply).                                                                                   |

Полный список приведён на странице [Отличия от размещённого сервиса](https://platform.claude.com/docs/ru/managed-agents/self-hosted/differences). Ознакомьтесь с ним, прежде чем переносить существующее приложение.

## Запуск собственных воркеров

[Стек из краткого руководства](https://platform.claude.com/docs/ru/managed-agents/self-hosted/quickstart) создаёт окружение и запускает его воркеры. То же делают Helm-чарты из раздела [Развёртывание в Kubernetes](https://platform.claude.com/docs/ru/managed-agents/self-hosted/kubernetes). Если вам нужны только эти воркеры, пропустите этот раздел.

Вы запускаете воркеры так же, как и в случае [самостоятельно размещаемых песочниц](https://platform.claude.com/docs/ru/managed-agents/self-hosted-sandboxes): с помощью тех же команд `ant beta:worker` и воркеров SDK, теми способами, которые показаны в разделе [Развёртывание самостоятельно размещаемых воркеров](https://platform.claude.com/docs/ru/managed-agents/self-hosted-sandboxes-workers). Исключение составляют воркеры, запускаемые по вебхукам, поскольку ваш сервер их не отправляет.

### Создание окружения и его ключа

Создайте окружение и «environment key» (ключ окружения) с помощью административного CLI, а не в Claude Console. CLI `cma-server-admin` находится в корне архива выпуска, поэтому выполняйте команду оттуда. В `-base-url` передайте адрес, по которому ваши воркеры обращаются к серверу:

* **Воркеры на машине, где запущен стек из краткого руководства:** `http://127.0.0.1:8400`
* **Воркеры на другой машине:** `https`-адрес [TLS-прокси, размещённого перед сервером](https://platform.claude.com/docs/ru/managed-agents/self-hosted/kubernetes#put-tls-in-front-of-the-server)

Административный CLI обращается к серверу по тому же адресу, поэтому запускайте его на машине, с которой этот адрес доступен.

```bash
echo "$ANTHROPIC_API_KEY" | ./cma-server-admin bootstrap \
  -base-url http://127.0.0.1:8400 -name my-env -key-file -
```

Команда выводит настройки воркера, команду для запуска воркера, а также идентификатор ключа и срок его действия:

```text wrap
export ANTHROPIC_BASE_URL='http://127.0.0.1:8400'
export ANTHROPIC_ENVIRONMENT_ID='env_...'
export ANTHROPIC_ENVIRONMENT_KEY='sk-ant-oat01-...'
# then: histchars= HISTFILE=/dev/null ant beta:worker poll --workdir /workspace
# key id: 'etok_...'  expires: '...'
```

Команда показывает ключ только один раз, поэтому сохраните ключ, его идентификатор и срок действия в вашем менеджере секретов. Ключ перестаёт работать через 365 дней. До этого выполните действия из раздела [Замена ключа окружения для собственных воркеров](https://platform.claude.com/docs/ru/managed-agents/self-hosted/kubernetes#replace-an-environment-key-for-your-own-workers).

Не размещайте ключ API сервера на машинах, где работают воркеры. Запускайте воркеры в контейнере или виртуальной машине, где нет ничего, что нужно защищать. О других ваших обязанностях в области безопасности см. [Ваши обязанности по безопасности](https://platform.claude.com/docs/ru/managed-agents/self-hosted#your-security-responsibilities).

### Запуск локального эксперимента

Выполните три строки `export` в оболочке, в которой вы запускаете воркер. Затем запустите воркер следующими командами, а не выведенной командой. Первая команда создаёт рабочий каталог воркера, поскольку воркер его не создаёт:

```bash
mkdir -p "$HOME/cma-workspace" "$HOME/.config/cma"
cat > "$HOME/.config/cma/worker.inputrc" <<'EOF'
$include /etc/inputrc
set disable-completion on
EOF
histchars= HISTFILE=/dev/null INPUTRC="$HOME/.config/cma/worker.inputrc" \
  ant beta:worker poll --workdir "$HOME/cma-workspace"
```

`histchars`, `INPUTRC` и `HISTFILE` настраивают оболочку, на которой работает инструмент `bash` воркера, чтобы она выполняла каждую команду в том виде, в каком её написал агент:

* **`histchars=`:** оболочка не воспринимает `!` как ссылку на историю команд.
* **`INPUTRC`:** файл отключает автодополнение, которое иначе поглощало бы каждый символ табуляции в команде. Храните файл вне рабочего каталога, где файловые инструменты агента могли бы его перезаписать.
* **`HISTFILE=/dev/null`:** оболочка не читает и не записывает файл истории.

Не используйте этот воркер ни для чего другого. Он хранит ключ окружения и выполняет инструменты всех сеансов в одном процессе. Кроме того, он не клонирует репозитории сеанса. Сеанс выполняется без них, и ваш клиент не получает ошибки.

### Запуск воркеров в рабочей среде

Во всех случаях, кроме локального эксперимента, запускайте отдельный контейнер для каждого сеанса и выполняйте в нём `ant beta:worker run`, как показано в разделе [Запуск одной песочницы на сеанс](https://platform.claude.com/docs/ru/managed-agents/self-hosted-sandboxes-workers#run-one-sandbox-per-session). Предоставьте его образу всё, что перечислено в разделе [Сборка собственного образа песочницы](https://platform.claude.com/docs/ru/managed-agents/self-hosted/call-the-api#build-your-own-sandbox-image), и измените в этой настройке три вещи:

* **Ключ окружения:** не передавайте `ANTHROPIC_ENVIRONMENT_KEY` в контейнер сеанса. Сервер принимает этот ключ для всех сеансов в окружении, а контейнеру нужен доступ только к одному сеансу.
* **Секрет элемента работы:** передайте этот секрет вместо ключа, поскольку сервер принимает его только для этого одного сеанса. В разделе [Передача секрета элемента работы](https://platform.claude.com/docs/ru/managed-agents/self-hosted-sandboxes-workers#forward-the-work-items-secret) показано, где ваш код его получает. Там, где в этом разделе задаётся `ANTHROPIC_WORK_SECRET`, поместите секрет в файл, который может читать только пользователь контейнера. Например, передайте секрет через конвейер на стандартный ввод контейнера, и пусть контейнер запишет файл перед запуском воркера. Затем задайте в `ANTHROPIC_WORK_SECRET_FILE` путь к файлу.
* **Адрес сервера:** задайте в `ANTHROPIC_BASE_URL` адрес, доступный из контейнера. `http://127.0.0.1:8400` таким адресом не является.

Для воркера SDK действуют ещё два пункта:

* **Версия:** собирайте воркер на последней версии SDK, как описано в разделе [SDK, CLI и библиотеки](https://platform.claude.com/docs/ru/cli-sdks-libraries/overview). Воркер этой версии ожидает подтверждения, прежде чем выполнить вызов инструмента, которому оно нужно, и никогда не выполняет вызов, запрещённый политикой. Воркер, собранный на более ранней версии, выполняет каждый вызов инструмента сразу после его поступления.
* **Примеры:** примеры в разделе [Запуск воркера SDK внутри песочницы](https://platform.claude.com/docs/ru/managed-agents/self-hosted-sandboxes-workers#run-the-sdk-worker-inside-the-sandbox) считывают ключ окружения, поэтому здесь они в исходном виде не работают.

### Сборка собственного образа песочницы

Собственному образу нужны следующие пакеты и настройки:

* **Пакеты:** Git 2.38 или новее, `curl`, `jq` и ripgrep, с помощью которого выполняет поиск инструмент `grep` воркера.

* **Настройки оболочки:** `histchars`, `HISTFILE` и `INPUTRC`, как в локальном эксперименте, а также `TERMINFO`. Добавьте эти строки в Dockerfile перед любой строкой `USER`:

  ```dockerfile
  ENV histchars=
  RUN printf '\nset disable-completion on\n' >> /etc/inputrc
  ENV INPUTRC=/etc/inputrc TERMINFO=/etc/terminfo HISTFILE=/dev/null
  RUN test -r /etc/terminfo/d/dumb
  ```

  `TERMINFO` должен указывать на каталог, содержащий `d/dumb` — описание терминала, которое читает `bash` воркера. В Alpine с установленным `bash` это `/etc/terminfo`, как показано. В другом базовом образе, например Debian или Ubuntu, это `/lib/terminfo` или `/usr/share/terminfo` — тот, в котором находится `d/dumb`. Укажите этот каталог в настройке `TERMINFO` и в строке `RUN test`, которая останавливает сборку, если файл отсутствует.

Образу также нужны два сценария из архива, которые выполняются перед запуском воркера:

1. Скопируйте `image-build/with-repositories.sh` в `/usr/local/bin/cma-with-repositories`. Он клонирует репозитории одного сеанса.
2. Скопируйте `image-build/with-egress.sh` в `/usr/local/bin/cma-with-egress`. Он направляет инструменты сеанса на [«egress gateway» (шлюз исходящего трафика)](https://platform.claude.com/docs/ru/managed-agents/self-hosted/agent-identity#environment-variable-credentials), если ваш сервер его запускает.
3. Сделайте оба файла исполняемыми.
4. Поставьте оба перед командой воркера, как в `cma-with-egress cma-with-repositories ant beta:worker run ...`. Пропустите этот шаг, если ваш образ запускает `kubernetes/sandbox/worker.sh` из архива, поскольку этот сценарий запускает воркер именно так.

Воркер, запущенный без `cma-with-repositories`, выполняет сеанс без репозитория. Ваш клиент не получает ошибки.

### Перенос воркеров с размещённого сервиса

Если вы уже запускаете воркеры для размещённого сервиса Anthropic, те же воркеры могут вместо этого обслуживать ваш сервер. Сделайте три вещи:

* Передайте процессу, который опрашивает наличие работы, три значения `export`, выведенные административным CLI.
* Запускайте этот процесс с заданными `histchars`, `HISTFILE` и `INPUTRC`, как в локальном эксперименте.
* Внесите изменения, описанные в разделе [Запуск воркеров в рабочей среде](https://platform.claude.com/docs/ru/managed-agents/self-hosted/call-the-api#run-workers-in-production), и проверьте образ каждого сеанса по разделу [Сборка собственного образа песочницы](https://platform.claude.com/docs/ru/managed-agents/self-hosted/call-the-api#build-your-own-sandbox-image).

## Следующие шаги

* [Вход разработчиков из терминала](https://platform.claude.com/docs/ru/managed-agents/self-hosted/configure#let-developers-log-in-from-a-terminal): настройте единый вход, чтобы разработчики использовали `ant` CLI под своей собственной учётной записью в терминале без `ANTHROPIC_API_KEY`.
* [Идентификация агентов и учётные данные](https://platform.claude.com/docs/ru/managed-agents/self-hosted/agent-identity): настройка доверия внешних систем к вашим агентам и хранение учётных данных хранилища в вашем менеджере секретов.
* [Поставщик инференса](https://platform.claude.com/docs/ru/managed-agents/self-hosted/inference-provider): отправка вызовов модели облачному провайдеру или вашему собственному шлюзу моделей.
