Самостоятельно размещаемые песочницы
Запускайте сессии Claude Managed Agents в самостоятельно размещаемых песочницах, сохраняя выполнение инструментов, файлы и исходящий сетевой трафик в вашей собственной инфраструктуре.
По умолчанию Managed Agents выполняет инструменты и код внутри облачных песочниц, управляемых Anthropic. Самостоятельно размещаемые песочницы, или «self-hosted sandboxes», оставляют оркестрацию на стороне Anthropic, но переносят выполнение инструментов в инфраструктуру, которую контролируете вы, поэтому код агента, файловая система и исходящий сетевой трафик никогда не покидают вашу среду.
Выполнение инструментов остаётся на вашем хосте: файловая система, которую агент читает и в которую пишет, процессы, которые он порождает, и сеть, к которой он может обращаться, — всё это находится под вашим контролем. Входные и выходные данные инструментов по-прежнему передаются в плоскость управления Anthropic (где работает Claude), чтобы модель могла видеть результаты и определять, что делать дальше. Навыки агента и содержимое любых хранилищ памяти, подключённых к сессии, хранятся у Anthropic и копируются в вашу песочницу на время сессии; изменения, которые агент вносит в файлы памяти, синхронизируются обратно в хранилище. Полное описание границ потоков данных см. в разделе модель безопасности.
Чем это отличается от облачных окружений
| Облачное окружение | Самостоятельно размещаемая песочница | |
|---|---|---|
| Где выполняются инструменты | Песочницы, управляемые Anthropic | Ваша инфраструктура |
| Сетевая доступность | Средства контроля исходящего трафика Anthropic | Ваша сетевая политика |
| Монтирование файлов и репозиториев GitHub | Управляется Anthropic | Управляется вами |
| Хранилища памяти | Монтируются Anthropic в /mnt/memory/ | Загружаются в /mnt/memory/ и синхронизируются воркером SDK |
| Жизненный цикл | Управляется Anthropic | Управляется вами |
Самостоятельное размещение хорошо подходит, когда агенту нужно работать с данными, которые не могут покидать границы вашей сети, обращаться к внутренним сервисам, не имеющим публичной маршрутизации, или работать в рамках собственных средств контроля соответствия и аудита вашей организации.
Сведения о соответствии требованиям Zero Data Retention и HIPAA BAA см. в разделе API и хранение данных.
Когда сочетать с туннелями MCP
Самостоятельное размещение определяет, где выполняется код агента. Туннели MCP определяют, как Anthropic обращается к серверам MCP в вашей сети. Они независимы: сессия, работающая в облачных песочницах Anthropic, по-прежнему может обращаться к приватным серверам MCP через туннель, а самостоятельно размещаемая сессия может использовать как туннелированные, так и публичные серверы MCP. Используйте оба подхода, когда хотите, чтобы и выполнение, и доступ к инструментам оставались внутри ваших границ. Чтобы предоставить агенту инструменты с сервера MCP внутри вашей сети без запуска туннеля, вы также можете обернуть сервер в пользовательские инструменты, обслуживаемые вашим воркером.
Воркер окружения
«Environment worker» (воркер окружения) — это процесс, который вы запускаете в собственной инфраструктуре. Он получает запросы на выполнение инструментов от Anthropic и выполняет их локально. Окружение self_hosted действует как очередь работ: когда ему назначается сессия, Anthropic помещает сессию в очередь как рабочий элемент. Ваш воркер забирает рабочие элементы из этой очереди, порождает контекст выполнения для каждого из них, загружает навыки агента (многократно используемые ресурсы на основе файловой системы, дающие агенту экспертизу в предметной области), выполняет вызовы инструментов и отправляет результаты обратно.
Рабочие элементы забираются путём опроса очереди окружения: либо постоянно работающим воркером, который опрашивает очередь непрерывно, либо обработчиком, запускаемым по вебхуку, который пробуждается по событию session.status_run_started и начинает опрос.
И CLI, и SDK поставляются с готовыми воркерами. CLI ant поддерживает только постоянно работающий режим; SDK поддерживает как постоянно работающий режим, так и запуск по вебхуку. Оба варианта настраиваются: флаги CLI см. в разделе Самостоятельно размещаемый воркер справочника, а параметры SDK — в разделе Вспомогательные средства SDK на этой странице. Для большего контроля вызывайте конечные точки Environments Work напрямую и реализуйте собственный воркер.
Файловая система песочницы
/workspace: системный рабочий каталог по умолчанию для выполнения инструментов и загрузки навыков. Флаг CLI--workdirпо умолчанию указывает на текущий каталог; передайте--workdir /workspace, чтобы соответствовать системному значению по умолчанию. Навыки загружаются в<workdir>/skills/<name>/. Если вы используете другой рабочий каталог, обновите системную подсказку вашего агента, чтобы Claude мог найти файлы навыков.- Выходные данные: в самостоятельно размещаемых окружениях системная подсказка сессии не содержит инструкции про
/mnt/session/outputs, используемой в песочницах, управляемых Anthropic, поэтому итоговые результаты оказываются там, куда агент записывает их в файловой системе вашей песочницы, обычно в рабочем каталоге. /mnt/memory/: хранилища памяти, подключённые к сессии, материализуются здесь воркером SDK, по одному каталогу на хранилище по путиmount_pathхранилища (например,/mnt/memory/user-preferences/). Воркер создаёт эти каталоги, когда забирает сессию, и удаляет их, когда сессия завершается; см. Использование хранилищ памяти.
Прежде чем начать
Вам понадобится:
- Существующий агент. Если у вас его нет, сначала пройдите Быстрый старт и запишите идентификатор агента.
- Хост Linux с
/bin/bashименно по этому пути. Инструмент bash воркера вызывает его напрямую, не обращаясь кPATH. TypeScript SDK дополнительно требует наличияunzipиtarвPATHи Node.js 22 или новее; Python и Go SDK используют свои стандартные библиотеки для распаковки архивов и не имеют дополнительных требований к бинарным файлам. - CLI
antили Anthropic SDK (Python, TypeScript или Go) на хосте воркера. - Учётные данные: ключ окружения (генерируется в Console на следующих шагах) аутентифицирует воркер в его очереди; ваш ключ API Claude создаёт сессии и читает статистику очереди извне хоста воркера. Генерация ключа возможна только в Console. Забранные рабочие элементы также содержат посессионный
secret, который воркер использует для монтирования хранилищ памяти; вы его не генерируете, но в схеме «песочница на сессию» вы сами передаёте его в песочницу (см. Запуск одной песочницы на сессию). - Для хранилищ памяти — подготовленный хост. Если сессии в этом окружении будут подключать хранилища памяти, подготовьте
/mnt/memoryна хосте воркера до запуска воркера; см. Подготовка хоста.
Создайте самостоятельно размещаемое окружение
В Console: Workspace > Environments > New > Self-hosted
Или через API:
client = anthropic.Anthropic() environment = client.beta.environments.create( name="self-hosted", config={"type": "self_hosted"} ) print(environment.id)Сгенерируйте ключ окружения
В Console откройте окружение и нажмите Generate environment key. Генерация ключа возможна только в Console, независимо от того, создали ли вы окружение через Console или через API. Затем экспортируйте идентификатор окружения и ключ на хосте воркера:
export ANTHROPIC_ENVIRONMENT_KEY="sk-ant-oat01-..." export ANTHROPIC_ENVIRONMENT_ID="env_..."
Запуск воркера
Выберите постоянно работающий режим для самой простой настройки: долгоживущий процесс непрерывно опрашивает очередь и требует только исходящего HTTPS. Выберите режим запуска по вебхуку, чтобы не держать простаивающий опрашивающий процесс; для него требуется конечная точка вебхука, доступная для Anthropic (настройку конечной точки и проверку подписи см. в разделе Вебхуки).
Установите CLI ant
Выполните это на хосте воркера.
Для окружений Linux загрузите бинарный файл релиза напрямую.
VERSION=1.27.0 OS=$(uname -s | tr '[:upper:]' '[:lower:]') case $(uname -m) in x86_64) ARCH=amd64 ;; aarch64) ARCH=arm64 ;; esac curl -fsSL "https://github.com/anthropics/anthropic-cli/releases/download/v${VERSION}/ant_${VERSION}_${OS}_${ARCH}.tar.gz" \ | sudo tar -xz -C /usr/local/bin antВсе релизы можно найти на странице релизов GitHub.
Запустите воркер
Внутри процесса
ant beta:worker pollзабирает рабочие элементы, назначенные окружению, загружает навыки, выполняет вызовы инструментов в рабочем каталоге и отправляет результаты обратно. Он читаетANTHROPIC_ENVIRONMENT_KEYиANTHROPIC_ENVIRONMENT_IDиз переменных окружения.ant beta:worker poll --workdir "/workspace"Воркер корректно завершается по SIGTERM или SIGINT: он отменяет любой выполняющийся вызов инструмента, отправляет результат с ошибкой и освобождает рабочий элемент перед остановкой.
Песочница на сессию
Если вам нужна более сильная изоляция (чистая файловая система, ограничения ресурсов или посессионный сетевой контроль), запускайте каждую сессию в собственной песочнице. Соберите образ с установленным
antиant beta:worker runв качестве точки входа. Базовый образ должен предоставлять/bin/bash;curlиспользуется только во время сборки. Когда песочница запускается, она читает сведения о сессии из переменных окружения, обрабатывает эту сессию и завершается:FROM your-base-image ARG ANT_VERSION=1.27.0 ARG TARGETARCH RUN ARCH=$([ "$TARGETARCH" = "arm64" ] && echo arm64 || echo amd64) && \ curl -fsSL "https://github.com/anthropics/anthropic-cli/releases/download/v${ANT_VERSION}/ant_${ANT_VERSION}_linux_${ARCH}.tar.gz" \ | tar -xz -C /usr/local/bin ant WORKDIR /workspace VOLUME /workspace ENTRYPOINT ["ant", "beta:worker", "run"]Затем напишите скрипт запуска, который передаёт сведения о сессии в новую песочницу. Опрашивающий процесс внедряет
ANTHROPIC_SESSION_ID,ANTHROPIC_WORK_ID,ANTHROPIC_ENVIRONMENT_IDиANTHROPIC_ENVIRONMENT_KEYв окружение скрипта и записывает забранный рабочий элемент в стандартный ввод скрипта в формате JSON, включая посессионныйsecretрабочего элемента, если Anthropic его выдал.ANTHROPIC_BASE_URLнеобязателен и передаётся только в том случае, если он был задан на хосте опрашивающего процесса; он переопределяет конечную точку API по умолчанию. В примере/host/outputs— это выбранный вами каталог хоста; он монтируется через bind-mount в рабочий каталог песочницы (/workspace), чтобы вы могли получить результаты сессии после завершения песочницы. В самостоятельно размещаемых окружениях агент записывает результаты в рабочий каталог, а не в/mnt/session/outputs(см. Файловая система песочницы), поэтому именно монтирование рабочего каталога позволяет их захватить; монтирование также захватывает загруженное деревоskills/и любые промежуточные файлы, создаваемые агентом.#!/bin/bash # spawn.sh: вызывается один раз для каждого взятого в работу элемента mkdir -p "/host/outputs/$ANTHROPIC_SESSION_ID" exec docker run --rm \ -e ANTHROPIC_SESSION_ID -e ANTHROPIC_ENVIRONMENT_KEY \ -e ANTHROPIC_WORK_ID -e ANTHROPIC_ENVIRONMENT_ID -e ANTHROPIC_BASE_URL \ -v "/host/outputs/$ANTHROPIC_SESSION_ID":/workspace \ your-imageТочка входа
ant beta:worker runне монтирует хранилища памяти. Если сессии в этом окружении подключают хранилища памяти, оставьте опрашивающий процесс, но соберите посессионный образ на основе воркера SDK и расширьте скрипт запуска так, чтобы он передавалsecretрабочего элемента в песочницу, как показано в разделе Запуск одной песочницы на сессию.Запустите опрашивающий процесс, указав на скрипт:
ant beta:worker poll --on-work ./spawn.sh
Вспомогательные средства SDK
SDK предоставляет три вспомогательных средства с разным уровнем контроля. EnvironmentWorker покрывает большинство сценариев использования; переходите к более низкоуровневым средствам, когда вам нужно запускать собственный посессионный процесс или выполнять инструменты для уже забранной сессии.
EnvironmentWorker: готовый воркер. Обрабатывает опрос, настройку и выполнение от начала до конца..run(): работает бесконечно, подхватывая сессии по мере их поступления..handle_item(): обрабатывает один забранный рабочий элемент и завершается. Передайте идентификаторы работы, сессии и окружения явно или позвольте ему прочитать переменныеANTHROPIC_*, которыеant beta:worker poll --on-workустанавливает для порождаемого им процесса. Чтобы сессия могла смонтировать свои хранилища памяти, также передайтеsecretрабочего элемента какwork_secret(workSecretв TypeScript,WorkSecretв Go) или установитеANTHROPIC_WORK_SECRET;ant beta:worker poll --on-workне устанавливает эту переменную, поэтому прочитайте секрет из JSON рабочего элемента, который он записывает в стандартный ввод вашего скрипта, как показано в разделе Запуск одной песочницы на сессию.memory_sync_interval(memorySyncIntervalMsв TypeScript,MemorySyncIntervalв Go) иmemory_sync_deletions(memorySyncDeletions,MemorySyncDeletions): как часто подключённые хранилища памяти сверяются с сервером во время работы сессии и удаляются ли из хранилища файлы, которые агент удаляет локально. Единицы измерения, значения по умолчанию и способ отключения поддержки памяти см. в разделе Настройка синхронизации.
work.poller(): опрашивает очередь работ от вашего имени и передаёт вам каждую забранную сессию. Используйте это, когда хотите сами решать, что происходит с каждой сессией, например запускать песочницу вместо выполнения инструментов внутри процесса.drain: прекращать ли опрос, когда очередь пуста, вместо ожидания новой работы.block_ms: как долго ждать поступления работы перед возвратом, в миллисекундах. Должно быть от 1 до 999 (ожидание на один опрос; вспомогательное средство автоматически повторяет опрос). Передайтеnull(Noneв Python,param.Null[int64]()в Go) для неблокирующей проверки; если параметр опущен, используется длинный опрос по умолчанию в 999 мс.reclaim_older_than_ms: повторно забирать рабочие элементы, которые были забраны, но не подтверждены в течение указанного количества миллисекунд.auto_stop(autoStopв TypeScript,AutoStopв Go): отправлять ли сигнал остановки для каждого рабочего элемента после того, как тело вашего цикла закончит с ним работу. Отключайте его всякий раз, когда то, что выполняет рабочий элемент, само отправляет остановку:handle_item()делает это, поэтому установите значение false, когда передаёте забранные элементы вhandle_item(), как это делают обработчики вебхуков на этой странице; то же относится к запускаемой вами песочнице, которая сама владеет вызовом остановки.
client.beta.sessions.events.tool_runner(): выполняет вызовы инструментов для одной сессии по идентификатору сессии и списку инструментов. Используйте, когда вы уже забрали работу и вам нужен только слой выполнения.
Используйте опрашивающее средство напрямую, когда хотите запускать собственный посессионный процесс, например поднимать песочницу для каждой забранной сессии:
import asyncio
import os
from anthropic import AsyncAnthropic
from anthropic.types.beta.environments import BetaSelfHostedWork
SANDBOX_ENV = (
"ANTHROPIC_ENVIRONMENT_ID",
"ANTHROPIC_ENVIRONMENT_KEY",
"ANTHROPIC_WORK_ID",
"ANTHROPIC_SESSION_ID",
"ANTHROPIC_WORK_SECRET",
"ANTHROPIC_BASE_URL", # forwarded only when set on this host
)
async def launch_container(work: BetaSelfHostedWork) -> None:
print(f"claimed session {work.data.id}")
# Замените `docker run` на собственный запускатель песочницы. Передайте ключ
# окружения (никогда не ваш ключ API) и посессионный секрет рабочего элемента: воркеру
# внутри нужен секрет для монтирования хранилищ памяти сессии.
env = os.environ | {
"ANTHROPIC_WORK_ID": work.id,
"ANTHROPIC_SESSION_ID": work.data.id,
"ANTHROPIC_WORK_SECRET": work.secret or "",
}
forward = [arg for name in SANDBOX_ENV for arg in ("-e", name)]
launcher = await asyncio.create_subprocess_exec(
"docker", "run", "--rm", "--detach", *forward, "your-sdk-worker-image", env=env
)
await launcher.wait()
async def main() -> None:
environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"]
async with AsyncAnthropic(auth_token=environment_key) as client:
async for work in client.beta.environments.work.poller(
environment_id=environment_id,
environment_key=environment_key,
auto_stop=False, # the launched sandbox owns the stop call
):
await launch_container(work)
asyncio.run(main())Что бы ни запускало песочницу, оно должно передавать в неё secret забранного рабочего элемента (например, как ANTHROPIC_WORK_SECRET) вместе с идентификаторами сессии, работы и окружения, чтобы воркер внутри мог смонтировать хранилища памяти сессии; см. Запуск одной песочницы на сессию.
AgentToolContext — это контекст выполнения для вызовов инструментов. Он определяет рабочий каталог и политику путей и может загружать навыки сессии. Файловые инструменты (read, write, edit, glob, grep) ограничены рабочим каталогом плюс любыми каталогами, перечисленными в allowed_roots (allowedRoots в TypeScript, AllowedRoots в Go), а write и edit дополнительно отклоняют пути внутри read_only_roots (readOnlyRoots, ReadOnlyRoots). EnvironmentWorker сам добавляет каталоги хранилищ памяти сессии в эти списки. Это ограничение — защитный механизм только для файловых инструментов, а не песочница; оно не ограничивает bash. beta_agent_toolset_20260401(env) принимает AgentToolContext и возвращает стандартные реализации инструментов (bash, read, write, edit, glob, grep).
С EnvironmentWorker: оба управляются автоматически. Передайте фабрику tools, чтобы настроить список инструментов:
EnvironmentWorker(client, ..., tools=lambda env: [beta_bash_tool(env), my_custom_tool])С work.poller() и tool_runner(): передайте список инструментов как tools в client.beta.sessions.events.tool_runner(). Чтобы построить этот список, настройте AgentToolContext самостоятельно и вызовите beta_agent_toolset_20260401(env):
from anthropic.lib.tools.agent_toolset import (
AgentToolContext,
beta_agent_toolset_20260401,
)
async with AgentToolContext(
workdir="/workspace", client=client, session_id=work.data.id
) as env:
# навыки загружены в /workspace/skills/<name>/
tools = beta_agent_toolset_20260401(env)Проверка подключения воркера
Из отдельной оболочки, установив ANTHROPIC_API_KEY в значение вашего ключа API Claude (не ключа окружения), убедитесь, что workers_polling не меньше 1:
ant beta:environments:work stats --environment-id "$ANTHROPIC_ENVIRONMENT_ID"Если workers_polling остаётся равным 0, воркер не достигает очереди: убедитесь, что ANTHROPIC_ENVIRONMENT_KEY и ANTHROPIC_ENVIRONMENT_ID установлены на хосте воркера. Полный ответ со статистикой и примеры на других языках см. в разделе Чтение глубины очереди.
Запуск сессии
Когда ваш воркер запущен, создайте сессию, нацеленную на окружение. Установите AGENT_ID в значение идентификатора агента, записанного в разделе Прежде чем начать. Сессия попадает в очередь работ окружения и ждёт там, пока воркер её не заберёт; если ни один воркер не подключён, сессия остаётся в очереди, а не завершается с ошибкой.
Anthropic не монтирует файлы или репозитории GitHub в самостоятельно размещаемые песочницы. Чтобы сделать доступными файлы, специфичные для сессии, передавайте ссылки на файлы (например, путь S3 или SHA коммита) в поле metadata сессии. Забранный рабочий элемент не содержит метаданных сессии, но содержит идентификатор сессии: ваш скрипт запуска или обработчик --on-work получает сессию (GET /v1/sessions/{session_id}), чтобы прочитать поле metadata, а затем размещает файлы в рабочем каталоге до начала выполнения инструментов.
session = client.beta.sessions.create(
agent=agent.id,
environment_id=environment.id,
metadata={"input_file": "s3://my-bucket/data.csv"},
)Полный список флагов CLI см. в разделе Самостоятельно размещаемый воркер справочника, а параметры вспомогательных средств SDK — в разделе Вспомогательные средства SDK.
Использование хранилищ памяти
Сессии в самостоятельно размещаемом окружении подключают хранилища памяти точно так же, как сессии в облачных окружениях: перечислите их в resources при создании сессии, как показано в разделе Подключение хранилища памяти к сессии. Сессия принимает до 8 хранилищ памяти. В самостоятельно размещаемом окружении каждое хранилище материализует для агента воркер SDK, а не инфраструктура Anthropic, поэтому хранилища памяти там требуют EnvironmentWorker (или его метода handle_item()) из Python, TypeScript или Go SDK.
Воркер CLI ant (ant beta:worker poll и ant beta:worker run) не монтирует хранилища памяти. Чтобы сочетать опрашивающий процесс CLI с хранилищами памяти, запускайте воркер SDK внутри посессионной песочницы, как описано в разделе Запуск одной песочницы на сессию.
Хранилища памяти нельзя подключать к сессиям в самостоятельно размещаемых окружениях на Claude Platform on AWS.
Как воркер работает с памятью
Когда воркер забирает рабочий элемент, к сессии которого подключены хранилища памяти, он:
- Загружает каждое подключённое хранилище в его
mount_pathна хосте воркера, аутентифицируясь с помощью посессионногоsecretрабочего элемента.mount_path— это тот же каталог внутри/mnt/memory/, который используют облачные сессии (например,/mnt/memory/user-preferences/для хранилища с именем «User Preferences»), и системная подсказка сессии описывает его агенту. - Добавляет эти каталоги в разрешённые корни файловых инструментов, а каталоги хранилищ, подключённых с
access: "read_only", — в их корни только для чтения, чтобы агент работал с памятью теми же инструментамиread,write,edit,globиgrep, которые он использует в рабочем каталоге. - Сверяет локальные и удалённые изменения после вызовов инструментов, не чаще одного раза за интервал синхронизации (по умолчанию 15 секунд): записи памяти, изменившиеся в хранилище, записываются на диск, а файлы, изменённые агентом, загружаются в хранилище.
- Выполняет финальную синхронизацию при завершении сессии, сбрасывает все ещё ожидающие загрузки в течение до 30 секунд, а затем удаляет созданные им каталоги. Воркер, отменённый во время работы сессии, пропускает финальную синхронизацию, но всё равно загружает изменённые файлы и удаляет каталоги перед завершением.
Хранилище памяти на стороне Anthropic остаётся источником истины. Версии памяти, редактирование (redaction), а также просмотр и изменение записей памяти в Console работают так же, как для облачных сессий, а операции чтения и записи памяти агентом отображаются в потоке событий как обычные события инструментов. Поскольку каждый воркер синхронизируется по интервалу, изменение, записанное в одной сессии, становится видимым для другой работающей сессии только после того, как обе синхронизируются, — обычно значительно меньше чем за минуту при интервале по умолчанию; сессии в облачных песочницах видят изменения друг друга почти мгновенно.
Каждый каталог хранилища содержит файл-маркер с именем .anthropic-memory-store, который связывает каталог с его хранилищем. Оставьте его на месте: воркер не синхронизирует каталог, маркер которого отсутствует или изменён.
Подготовка хоста
Хранилищам памяти в самостоятельно размещаемых песочницах нужна файловая система POSIX на хосте воркера (хост Linux из раздела Прежде чем начать); хосты Windows не поддерживаются, поскольку воркеру требуется O_NOFOLLOW при открытии файлов памяти. Рекомендуется файловая система с учётом регистра, чтобы пути памяти, различающиеся только регистром, не конфликтовали.
Перед запуском воркера создайте родительский каталог и сделайте его доступным для записи пользователю, от имени которого работает воркер:
sudo mkdir -p /mnt/memory && sudo chown "$USER" /mnt/memoryНе создавайте каталоги для отдельных хранилищ самостоятельно. Воркер создаёт каталог mount_path каждого хранилища (например, /mnt/memory/user-preferences) при запуске сессии, отказывается начинать работу сессии, если по этому пути уже что-то существует, и удаляет каталог при завершении сессии. Из этого следуют два правила эксплуатации:
- Запускайте одну сессию на файловую систему, когда сессии подключают одно и то же хранилище. Две сессии не могут смонтировать одно и то же хранилище на одном хосте одновременно, поскольку обеим нужен один и тот же путь. Выделение каждой сессии собственной песочницы, как описано в разделе Запуск одной песочницы на сессию, удовлетворяет этому правилу.
- Останавливайте воркеры корректно. Когда вы останавливаете воркер во время работы сессии,
EnvironmentWorkerзагружает изменённые файлы памяти сессии и удаляет её каталоги хранилищ только в том случае, если он отменён, а не убит: убитый процесс не выполняет завершающих действий, а сам воркер не устанавливает обработчики сигналов. Свяжите SIGTERM и SIGINT с отменой в процессе, который его запускает: прервитеsignal, который вы передаёте воркеру, в TypeScript, отмените контекст в Go, а в Python отмените задачу, выполняющуюrun()илиhandle_item(). Делайте это из обработчика сигналов, когда ваш воркер и есть процесс, как это делают автономные воркеры на этой странице, или из собственного хука завершения вашего сервера, когда воркер работает внутри обработчика вебхука, который не должен перехватывать сигналы сервера. Затем останавливайте воркеры с помощью SIGTERM и давайте им не менее 30 секунд на завершение перед любым принудительным уничтожением, поскольку финальная загрузка может занять столько времени. Если воркер убит до выполнения завершающих действий, удалите оставшийся каталог хранилища внутри/mnt/memory/до следующей сессии, подключающей это хранилище; любые правки в нём, которые не были синхронизированы, теряются.
Запуск одной песочницы на сеанс
Шаблон «песочница на сеанс» из раздела Запуск воркера предоставляет каждому сеансу свежую файловую систему, чего и требует раздел Подготовка хоста, когда сеансы подключают одно и то же хранилище. Оставьте ant beta:worker poll --on-work (или опросчик работы из SDK) в качестве опросчика на хосте.
Показанная там точка входа ant beta:worker run не монтирует хранилища памяти, поэтому вместо неё соберите образ для каждого сеанса вокруг воркера SDK: его точка входа создаёт EnvironmentWorker и вызывает handle_item() (handleItem в TypeScript, HandleItem в Go), который считывает идентификаторы сеанса, работы и окружения из переменных ANTHROPIC_*, а посеансовый secret элемента работы — из ANTHROPIC_WORK_SECRET. Вы также можете передать секрет явно как work_secret (workSecret в TypeScript, WorkSecret в Go).
import asyncio
import contextlib
import os
import signal
from anthropic import AsyncAnthropic
from anthropic.lib.environments import EnvironmentWorker
async def main() -> None:
async with AsyncAnthropic(auth_token=os.environ["ANTHROPIC_ENVIRONMENT_KEY"]) as client:
worker = EnvironmentWorker(client, workdir="/workspace")
# Без аргументов handle_item() читает переменные ANTHROPIC_*, которые передал скрипт
# запуска, включая ANTHROPIC_WORK_SECRET.
task = asyncio.create_task(worker.handle_item())
# Отмена задачи при остановке контейнера позволяет воркеру выгрузить
# изменённые файлы памяти и удалить каталоги хранилища перед выходом.
loop = asyncio.get_running_loop()
for signum in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(signum, task.cancel)
with contextlib.suppress(asyncio.CancelledError):
await task
asyncio.run(main())ant beta:worker poll --on-work не устанавливает ANTHROPIC_WORK_SECRET для запускаемого им скрипта, поэтому скрипт запуска считывает секрет из JSON элемента работы на своём стандартном вводе и передаёт его в песочницу:
#!/bin/bash
# spawn.sh: вызывается один раз для каждого взятого рабочего элемента
# Взятый рабочий элемент поступает в формате JSON через stdin. Его secret — это
# учётные данные сеанса, которые требуются конечным точкам хранилища памяти.
ANTHROPIC_WORK_SECRET="$(jq -r '.secret // empty')"
export ANTHROPIC_WORK_SECRET
mkdir -p "/host/outputs/$ANTHROPIC_SESSION_ID"
exec docker run --rm \
-e ANTHROPIC_SESSION_ID -e ANTHROPIC_ENVIRONMENT_KEY \
-e ANTHROPIC_WORK_ID -e ANTHROPIC_ENVIRONMENT_ID -e ANTHROPIC_BASE_URL \
-e ANTHROPIC_WORK_SECRET \
-v "/host/outputs/$ANTHROPIC_SESSION_ID":/workspace \
your-sdk-worker-imageЕсли вместо этого вы забираете работу с помощью опросчика работы из SDK, таким же образом передавайте secret каждого забранного элемента в запускаемую вами песочницу. Передавайте его только в ту песочницу, которая обслуживает данный сеанс, и никогда не записывайте его в журнал.
Образу песочницы также нужен доступный для записи каталог /mnt/memory (см. Подготовка хоста). Поскольку каждая песочница обслуживает один сеанс и затем удаляется, никакие оставшиеся каталоги не требуют очистки, а каталоги памяти не нужно монтировать через bind-mount на хост: воркер выгружает их содержимое в хранилище до завершения работы песочницы. Если вы останавливаете контейнер до окончания его сеанса, отправьте сигнал, который точка входа преобразует в отмену (см. Подготовка хоста), а не убивайте его, чтобы выгрузка всё же выполнилась. Также дайте контейнеру время завершить выгрузку: по умолчанию Docker отправляет SIGKILL через 10 секунд после сигнала остановки, поэтому увеличьте этот лимит как минимум до 30 секунд, которых требует раздел «Подготовка хоста», с помощью --stop-timeout в docker run или периода ожидания завершения (termination grace period) вашего оркестратора.
Настройка синхронизации
Два параметра EnvironmentWorker управляют поведением памяти:
memory_sync_interval(Python, в секундах;memorySyncIntervalMsв TypeScript, в миллисекундах;MemorySyncIntervalв Go, длительность): как часто подключённые хранилища сверяются с сервером во время работы сеанса. По умолчанию 15 секунд; минимум — 5 секунд. Более короткий интервал сужает окно, в течение которого другой сеанс видит устаревшие воспоминания, ценой большего числа запросов к хранилищу памяти.Noneв Python,nullв TypeScript или отрицательная длительность в Go полностью отключают поддержку памяти: воркер не скачивает и не синхронизирует хранилища, а сеанс с подключёнными хранилищами памяти работает без них, хотя его системная подсказка по-прежнему их описывает, поэтому отключайте поддержку памяти только на воркерах, чьи сеансы не подключают хранилища памяти. Пока поддержка памяти включена, элемент работы, поступивший без посеансовогоsecretдля сеанса с подключёнными хранилищами, завершается ошибкой, а не выполняется без памяти (см. Устранение неполадок монтирования памяти).memory_sync_deletions(memorySyncDeletionsв TypeScript,MemorySyncDeletionsв Go): удаляется ли из хранилища файл, который агент удаляет локально. Значение — одно из"enabled"(по умолчанию),"log_only"или"disabled"в Python и TypeScript и одна из константenvironments.MemorySyncDeletionsEnabled(нулевое значение),environments.MemorySyncDeletionsLogOnlyилиenvironments.MemorySyncDeletionsDisabledв Go. Когда параметр включён, воркер удаляет воспоминание из хранилища, как только последующая синхронизация подтверждает, что файл по-прежнему отсутствует; в режиме только журналирования он выполняет те же проверки, но лишь записывает в журнал, что он удалил бы, что позволяет вам наблюдать, что удаляли бы ваши воркеры, прежде чем довериться включённому режиму; когда параметр отключён, воркер никогда не удаляет из хранилища. Выгрузки и скачивания этим параметром не затрагиваются.
Задавайте эти параметры там, где вы создаёте воркер, — через конструктор EnvironmentWorker или, в Python и TypeScript, через фабрику client.beta.environments.work.worker(), которую использует обработчик вебхуков.
Например, чтобы синхронизироваться каждые 10 секунд и только записывать в журнал удаления, которые воркер выполнил бы:
worker = EnvironmentWorker(
client,
environment_id=environment_id,
environment_key=environment_key,
workdir="/workspace",
memory_sync_interval=10, # seconds
memory_sync_deletions="log_only",
)Хранилища только для чтения и конфликты
Для хранилища, подключённого с access: "read_only", инструменты write и edit отказываются изменять файлы внутри его каталога, и воркер никогда ничего из него не выгружает. Изменения, внесённые через bash или через пользовательский инструмент либо сервер MCP, который вы обслуживаете из песочницы, локально не блокируются: они никогда не синхронизируются с хранилищем, и следующее удалённое изменение этого воспоминания их перезаписывает. Если вам нужно, чтобы сама локальная копия оставалась неизменной в течение сеанса, отключите инструмент bash для этого агента и не давайте ему пользовательских инструментов, которые пишут в файловую систему песочницы; не монтируйте путь хранилища только для чтения, потому что сам воркер должен создать каталог и записать в него скачанные воспоминания.
Конфликты разрешаются в пользу хранилища. Когда агент изменяет файл воспоминания, который также изменился в хранилище с момента последней синхронизации сеансом, воркер при следующей синхронизации сохраняет версию хранилища, перезаписывает ею локальный файл и записывает предупреждение в журнал; сами инструменты write и edit завершаются успешно, и никакая ошибка до агента не доходит. Если изменение агента всё ещё актуально, он может перечитать файл после синхронизации и внести изменение снова.
Устранение неполадок монтирования памяти
Воркер записывает сбои монтирования и фоновой синхронизации в журнал, а не сообщает о них в сеанс; до агента доходят только отказы для хранилищ только для чтения — в виде ошибок инструментов (см. Хранилища только для чтения и конфликты). Если хранилище памяти не удаётся смонтировать, когда воркер забирает сеанс, воркер завершает элемент работы ошибкой: сеанс не выдаёт события ошибки и остаётся в состоянии idle.
| Симптом | Причина | Исправление |
|---|---|---|
Журнал воркера содержит the work item carried no sessions token (в Go — ошибка ErrSessionMemoryNoToken), и элемент работы завершается ошибкой. | Посеансовый secret элемента работы не дошёл до воркера: хранилища памяти в самостоятельно размещаемых песочницах не включены для вашей организации, или ваш скрипт запуска не передал секрет в песочницу. | В шаблоне «песочница на сеанс» передавайте ANTHROPIC_WORK_SECRET в песочницу, как показано в разделе Запуск одной песочницы на сеанс. Если воркер опрашивает и выполняет сеансы в одном процессе и всё равно записывает это в журнал, обратитесь в поддержку. |
Журнал воркера содержит something already exists at the memory store's path. | Каталог, оставшийся от предыдущего сеанса, обычно такого, чей воркер был убит до выполнения его завершающей очистки. | Удалите оставшийся каталог, указанный в строке журнала. Несинхронизированные правки в нём теряются. |
Журнал воркера содержит cannot create the memory store's folder и the worker host must make this mount path writable. | Пользователь, от имени которого работает воркер, не может создавать каталоги в /mnt/memory. | Создайте /mnt/memory и выполните chown на этого пользователя; см. Подготовка хоста. |
Сеанс находится в состоянии idle с причиной остановки requires_action и без события ошибки вскоре после того, как воркер его забрал. | Воркер завершил элемент работы ошибкой, потому что не смог смонтировать хранилище памяти по одной из перечисленных выше причин. | Устраните причину на хосте, затем отправьте событие user.interrupt: работа сеанса снова ставится в очередь, и следующий воркер, который её заберёт, повторит попытку монтирования. |
Обслуживание пользовательских инструментов из вашей песочницы
Пользовательские инструменты — это инструменты, которые выполняет ваш собственный код: агент выдаёт событие agent.custom_tool_use и ожидает соответствующего user.custom_tool_result. Этим кодом может быть воркер, и поскольку он работает внутри вашей песочницы, инструмент получает доступ к внутренним сервисам, учётным данным и исходящему сетевому трафику, которые вы настроили для песочницы, и ни к чему более. Ключ окружения авторизует отправку результатов пользовательских инструментов, поэтому ваш ключ API Claude не попадает на хост воркера.
Объявите инструмент на агенте
Добавьте в
toolsагента записьcustom, чьёnameсовпадает с инструментом, который регистрирует ваш воркер. Полную форму объявления см. в разделе Пользовательские инструменты.{ "type": "custom", "name": "get_order_status", "description": "Look up an order in the internal fulfillment system by order ID.", "input_schema": { "type": "object", "properties": { "order_id": { "type": "string", "description": "The order ID" } }, "required": ["order_id"] } }Зарегистрируйте реализацию в воркере
Передайте инструмент через фабрику
toolsворкера (см. Вспомогательные средства SDK) вместе со встроенным набором инструментов:import asyncio import os from anthropic import AsyncAnthropic, beta_async_tool from anthropic.lib.environments import EnvironmentWorker from anthropic.lib.tools.agent_toolset import beta_agent_toolset_20260401 @beta_async_tool async def get_order_status(order_id: str) -> str: """Look up an order in the internal fulfillment system by order ID.""" # Выполняется на хосте воркера: можно вызывать всё, к чему у песочницы есть доступ. return f"Order {order_id}: shipped" async def main() -> None: environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"] environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"] async with AsyncAnthropic(auth_token=environment_key) as client: await EnvironmentWorker( client, environment_id=environment_id, environment_key=environment_key, workdir="/workspace", tools=lambda env: [*beta_agent_toolset_20260401(env), get_order_status], ).run() asyncio.run(main())
Воркер отвечает только на зарегистрированные в нём инструменты. Пользовательский инструмент, объявленный на агенте, но не зарегистрированный ни в одном воркере или клиенте, оставляет сеанс приостановленным с причиной остановки requires_action, пока что-либо не отправит его результат; поток событий см. в разделе Обработка вызовов пользовательских инструментов.
Обёртывание сервера MCP в пользовательские инструменты
Коннектор MCP подключается к серверам MCP со стороны Anthropic, поэтому сервер должен предоставлять HTTP-эндпоинт, доступный для Anthropic напрямую или через туннель MCP. Чтобы использовать сервер, доступный только из вашей сети, сделайте клиентом MCP сам воркер и объявите инструменты сервера как пользовательские инструменты. Серверу MCP не требуется входящее подключение извне вашей сети; Anthropic получает определения инструментов, которые вы объявляете на агенте, входные данные каждого вызова и результат, который ваш воркер отправляет обратно. Во время выполнения модель вызывает обёрнутый инструмент как любой другой пользовательский инструмент:
- Агент выдаёт событие
agent.custom_tool_use. - Воркер внутри вашей песочницы пересылает вызов по своему открытому сеансу MCP серверу в вашей сети.
- Воркер отправляет ответ сервера как
user.custom_tool_result.
Клиентские вспомогательные средства MCP в SDK преобразуют инструменты сервера в исполняемые инструменты, которые принимает воркер; установите SDK MCP вместе с SDK Anthropic (pip install "anthropic[mcp]" "mcp>=1.24", npm install @modelcontextprotocol/sdk, go get github.com/modelcontextprotocol/go-sdk). Примеры подключаются без аутентификации; чтобы отправлять учётные данные, настройте HTTP-клиент или параметры запроса, которые вы передаёте транспорту MCP (http_client в Python, requestInit в TypeScript, HTTPClient в Go).
Объявите инструменты сервера на агенте
Получите список инструментов сервера MCP и объявите каждый из них как инструмент
custom; поля MCPname,descriptionиinputSchemaодин к одному отображаются на поля пользовательского инструмента. Если сервер разбивает список инструментов на страницы, объявите каждую страницу; воркер должен перечислить те же страницы.import asyncio from typing import Any, cast from anthropic import AsyncAnthropic from anthropic.types.beta import BetaManagedAgentsCustomToolParams from mcp import ClientSession, types # Требуется mcp >= 1.24, где streamablehttp_client переименован в streamable_http_client. from mcp.client.streamable_http import streamable_http_client MCP_SERVER_URL = "http://mcp.internal.example.com:8000/mcp" def to_custom_tool(tool: types.Tool) -> BetaManagedAgentsCustomToolParams: # Поля MCP один к одному соответствуют объявлению пользовательского инструмента. Приведение типа # передаёт словарь схемы в типизированный параметр SDK без изменений. return { "type": "custom", "name": tool.name, "description": tool.description or tool.name, "input_schema": cast(Any, tool.inputSchema), } async def main() -> None: # Запускайте это там, где вы создаёте агентов, а не на рабочем хосте: скрипт # аутентифицируется с помощью вашего ключа API Claude (ANTHROPIC_API_KEY). async with ( streamable_http_client(MCP_SERVER_URL) as (read, write, _), ClientSession(read, write) as mcp_session, AsyncAnthropic() as client, ): await mcp_session.initialize() listed = await mcp_session.list_tools() agent = await client.beta.agents.create( name="Internal tools agent", model="claude-opus-5", tools=[ {"type": "agent_toolset_20260401"}, *[to_custom_tool(tool) for tool in listed.tools], ], ) print(agent.id) asyncio.run(main())Обслуживайте инструменты из воркера
Подключитесь к тому же серверу MCP при запуске, преобразуйте его инструменты с помощью вспомогательных средств MCP и зарегистрируйте их вместе со встроенным набором инструментов. Держите один сеанс MCP открытым на протяжении всей жизни воркера.
import asyncio import os from datetime import timedelta from anthropic import AsyncAnthropic from anthropic.lib.environments import EnvironmentWorker from anthropic.lib.tools.agent_toolset import beta_agent_toolset_20260401 from anthropic.lib.tools.mcp import async_mcp_tool from mcp import ClientSession # Требуется mcp >= 1.24, где streamablehttp_client переименован в streamable_http_client. from mcp.client.streamable_http import streamable_http_client MCP_SERVER_URL = "http://mcp.internal.example.com:8000/mcp" async def main() -> None: environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"] environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"] # Подключаемся к серверу MCP один раз при запуске и держим сессию открытой # на всё время жизни воркера. Тайм-аут превращает зависший вызов инструмента в результат # с ошибкой вместо застрявшего вызова. async with ( streamable_http_client(MCP_SERVER_URL) as (read, write, _), ClientSession(read, write, read_timeout_seconds=timedelta(seconds=60)) as mcp_session, AsyncAnthropic(auth_token=environment_key) as client, ): await mcp_session.initialize() listed = await mcp_session.list_tools() mcp_tools = [async_mcp_tool(tool, mcp_session) for tool in listed.tools] await EnvironmentWorker( client, environment_id=environment_id, environment_key=environment_key, workdir="/workspace", tools=lambda env: [*beta_agent_toolset_20260401(env), *mcp_tools], ).run() asyncio.run(main())
При обёртывании сервера MCP учитывайте следующее:
- Инструменты объявляются, а не обнаруживаются во время выполнения. Воркер получает список инструментов сервера MCP один раз при запуске и не может добавлять инструменты в работающий сеанс. Когда инструменты сервера меняются, объявите их заново — на агенте или на простаивающем сеансе через Обновление конфигурации агента — и перезапустите воркер.
- Имена и описания должны соответствовать Managed Agents API. Имена пользовательских инструментов уникальны в пределах агента и состоят из букв, цифр, подчёркиваний и дефисов (1–128 символов); требуется непустое описание; а массив
toolsагента принимает не более 128 записей (каждый обёрнутый инструмент — одна запись, и встроенный набор инструментов — ещё одна). API отклоняет объявление, которое повторно использует имя инструмента, называет пользовательский инструмент именем встроенного инструмента агента, такого какbashилиread, или использует зарезервированный префиксmcp__. Вспомогательные средства MCP сохраняют имена и описания сервера, поэтому переименовывайте или сокращайте их там, где это необходимо. Когда два сервера предоставляют инструмент с одним и тем же именем, определите обёртку самостоятельно под именем с префиксом и пусть она вызывает исходное имя инструмента сервера. - Большинство схем проходят без изменений. API принимает ключевые слова JSON Schema, которые обычно выдают серверы MCP, такие как
additionalPropertiesиtitle. Он отклоняет ссылочные ключевые слова, такие как$ref, в любом местеinput_schemaпользовательского инструмента, поэтому встраивайте схемы, которые генераторы вроде pydantic выносят в$defs. Он также отклоняетoneOf,anyOfиallOfна верхнем уровне, а также имена свойств, содержащие что-либо кроме букв, цифр, подчёркиваний, точек и дефисов (1–64 символа). - Сбои инструментов проявляются как результаты инструментов с ошибкой. Когда сервер MCP сообщает об ошибке инструмента, воркер отправляет результат инструмента с ошибкой, на который модель может отреагировать. Содержимое MCP, не имеющее эквивалента в результатах инструментов, такое как аудиоблоки и ссылки на ресурсы, также проявляется как ошибка. Установите тайм-аут на клиенте MCP для более быстрого и понятного сбоя, как это делает пример воркера на Python с помощью
read_timeout_seconds. Без него зависший вызов становится результатом с ошибкой только тогда, когда срабатывает тайм-аут запроса по умолчанию в SDK MCP для TypeScript (около минуты) или собственный страховочный механизм воркера: около двух с половиной минут в Python и две минуты в Go, где воркер отменяет вызов инструмента, превысивший его 120-секундное значение по умолчанию, и отправляет результат с ошибкой. - Обёртывайте серверы, которыми вы управляете или которым доверяете. Имя, описание и результаты обёрнутого инструмента попадают в контекст модели так же, как и у любого другого инструмента: это недоверенный ввод, который может повлиять на то, что агент делает с другими своими инструментами, включая
bashна хосте воркера. Объявляйте только те инструменты, которые вы намерены дать агенту в использование. - Политики разрешений не применяются к пользовательским инструментам. Политики разрешений управляют встроенным набором инструментов и наборами инструментов MCP; воркер выполняет каждый вызов обёрнутого инструмента, который делает модель, поэтому размещайте любой шаг одобрения в коде вашего собственного инструмента.
Мониторинг и эксплуатация
Эти вызовы выполняются из ваших инструментов мониторинга или эксплуатации, аутентифицированных вашим ключом API Claude, для наблюдения за парком воркеров и управления им. Цикл забора работы и поддержания активности обрабатывается внутри вспомогательных средств воркера, поэтому вы не вызываете эти эндпоинты напрямую.
Чтение глубины очереди
work.stats возвращает состояние очереди для окружения:
depth— количество элементов, ожидающих забора. Масштабируйте парк воркеров или настраивайте оповещения о накопившейся очереди на основе этого значения.pending— количество элементов, забранных воркером, но ещё не подтверждённых. Вспомогательные средства воркера подтверждают каждый элемент перед его обработкой, поэтому при нормальной работе это значение остаётся близким к нулю; устойчиво ненулевое значение означает, что воркер застрял между забором и подтверждением.oldest_queued_at— временная метка самого старого элемента, всё ещё находящегося в очереди, — ожидающего забора или забранного, но ещё не подтверждённого, — либоnull, если такого нет.workers_polling— количество воркеров, выполнявших опрос за последние 30 секунд. Используйте это для оповещений о работоспособности.
import os
import anthropic
client = anthropic.Anthropic()
stats = client.beta.environments.work.stats(os.environ["ANTHROPIC_ENVIRONMENT_ID"])
print(f"depth={stats.depth} pending={stats.pending}"){
"type": "work_queue_stats",
"depth": 0,
"pending": 0,
"oldest_queued_at": null,
"workers_polling": 0
}Корректная остановка сеанса
Используйте work.stop, чтобы попросить воркер, обрабатывающий конкретный сеанс, завершить его. По умолчанию элемент работы переходит в состояние stopping: воркер замечает это при следующем heartbeat-сигнале аренды, отменяет выполняющийся вызов инструмента сеанса и подтверждает завершение, после чего элемент работы становится stopped. Передайте force: true в теле запроса (в CLI передайте --force), чтобы немедленно пометить элемент работы как stopped, не дожидаясь подтверждения воркера.
Поскольку эти вызовы выполняются из ваших инструментов эксплуатации, а не с хоста воркера, ANTHROPIC_WORK_ID не устанавливается автоматически. Установите его в идентификатор целевого элемента работы перед запуском следующих примеров. Чтобы найти идентификатор элемента работы, получите список элементов работы окружения через эндпоинты Environments Work.
import os
import anthropic
client = anthropic.Anthropic()
work = client.beta.environments.work.stop(
os.environ["ANTHROPIC_WORK_ID"],
environment_id=os.environ["ANTHROPIC_ENVIRONMENT_ID"],
)
print(work.state)Следующие шаги
Модель разделённой ответственности для самостоятельно размещаемых окружений песочниц.
Создайте сеанс, чтобы запустить вашего агента и начать выполнение задач.
Безопасно подключайте Claude к серверам MCP, работающим в вашей частной сети, не открывая входящие порты и не выставляя сервисы в публичный интернет.
Was this page helpful?