자체 호스팅 샌드박스
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 서버 중 어느 것이든 사용할 수 있습니다. 실행과 도구 접근을 모두 사용자의 경계 내에 유지하려면 둘 다 사용하세요. 터널을 실행하지 않고 네트워크 내부의 MCP 서버에서 에이전트에게 도구를 제공하려면, 워커가 제공하는 커스텀 도구로 서버를 래핑할 수도 있습니다.
환경 워커
"Environment worker"(환경 워커)는 사용자가 자체 인프라에서 실행하는 프로세스입니다. Anthropic으로부터 도구 실행 요청을 받아 로컬에서 실행합니다. self_hosted 환경은 작업 큐 역할을 합니다. 세션이 환경에 할당되면 Anthropic은 해당 세션을 작업 항목으로 큐에 넣습니다. 워커는 그 큐에서 작업 항목을 클레임하고, 각 항목에 대한 실행 컨텍스트를 생성하고, 에이전트의 스킬(에이전트에게 도메인별 전문성을 부여하는 재사용 가능한 파일시스템 기반 리소스)을 다운로드하고, 도구 호출을 실행하고, 결과를 다시 게시합니다.
작업 항목은 환경의 큐를 폴링하여 클레임합니다. 지속적으로 폴링하는 상시 실행 워커 또는 session.status_run_started에 깨어나 폴링을 시작하는 웹훅 트리거 핸들러 중 하나를 사용합니다.
CLI와 SDK 모두 사전 구축된 워커를 제공합니다. ant CLI는 상시 실행 패턴만 지원하며, SDK는 상시 실행과 웹훅 트리거를 모두 지원합니다. 둘 다 구성 가능합니다. CLI 플래그는 레퍼런스의 자체 호스팅 워커를, SDK 옵션은 이 페이지의 SDK 헬퍼를 참조하세요. 더 많은 제어가 필요하면 Environments Work 엔드포인트를 직접 호출하여 자체 워커를 구현하세요.
샌드박스 파일시스템
/workspace: 도구 실행 및 스킬 다운로드를 위한 시스템 기본 작업 디렉터리입니다. CLI의--workdir플래그는 현재 디렉터리를 기본값으로 사용합니다. 시스템 기본값과 일치시키려면--workdir /workspace를 전달하세요. 스킬은<workdir>/skills/<name>/에 다운로드됩니다. 다른 작업 디렉터리를 사용하는 경우 Claude가 스킬 파일을 찾을 수 있도록 에이전트의 시스템 프롬프트를 업데이트하세요.- 출력물: 자체 호스팅 환경에서는 세션의 시스템 프롬프트가 Anthropic 관리형 샌드박스에서 사용되는
/mnt/session/outputs지침을 생략하므로, 최종 결과물은 에이전트가 샌드박스 파일시스템에서 쓰는 위치(일반적으로 작업 디렉터리 아래)에 저장됩니다. /mnt/memory/: 세션에 연결된 메모리 스토어는 SDK 워커에 의해 여기에 구체화되며, 스토어의mount_path에 스토어당 하나의 디렉터리가 생성됩니다(예:/mnt/memory/user-preferences/). 워커는 세션을 클레임할 때 이 디렉터리들을 생성하고 세션이 끝나면 제거합니다. 메모리 스토어 사용을 참조하세요.
시작하기 전에
다음이 필요합니다.
- 기존 에이전트. 없다면 먼저 빠른 시작을 완료하고 에이전트 ID를 기록해 두세요.
- 정확히 해당 경로에
/bin/bash가 있는 Linux 호스트. 워커의 bash 도구는PATH를 참조하지 않고 이를 직접 호출합니다. TypeScript SDK는 추가로PATH에unzip과tar가 있어야 하며 Node.js 22 이상이 필요합니다. Python 및 Go SDK는 아카이브 추출에 표준 라이브러리를 사용하므로 추가 바이너리 요구 사항이 없습니다. - 워커 호스트에 설치된
antCLI 또는 Anthropic SDK(Python, TypeScript 또는 Go). - 자격 증명: 환경 키(다음 단계에서 Console에서 생성)는 워커를 큐에 인증합니다. Claude API 키는 워커 호스트 외부에서 세션을 생성하고 큐 통계를 읽습니다. 키 생성은 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에서 생성했든 API로 생성했든 관계없이 키 생성은 Console에서만 가능합니다. 그런 다음 워커 호스트에서 환경 ID와 키를 export하세요.
export ANTHROPIC_ENVIRONMENT_KEY="sk-ant-oat01-..." export ANTHROPIC_ENVIRONMENT_ID="env_..."
워커 실행
가장 간단한 설정을 원한다면 상시 실행을 선택하세요. 장기 실행 프로세스가 큐를 지속적으로 폴링하며 아웃바운드 HTTPS만 필요합니다. 유휴 폴러 실행을 피하려면 웹훅 트리거를 선택하세요. 이 경우 Anthropic이 도달할 수 있는 웹훅 엔드포인트가 필요합니다(엔드포인트 설정 및 서명 검증은 웹훅 참조).
ant CLI 설치
워커 호스트에서 실행하세요.
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으로 스크립트의 표준 입력에 씁니다. 여기에는 Anthropic이 발급한 경우 작업 항목의 세션별secret이 포함됩니다.ANTHROPIC_BASE_URL은 선택 사항이며 폴러 호스트에 설정된 경우에만 전달됩니다. 이는 기본 API 엔드포인트를 재정의합니다. 예제에서/host/outputs는 사용자가 선택하는 호스트 디렉터리이며, 샌드박스가 종료된 후 세션 결과물을 가져올 수 있도록 샌드박스의 작업 디렉터리(/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-imageant beta:worker run엔트리포인트는 메모리 스토어를 마운트하지 않습니다. 이 환경의 세션이 메모리 스토어를 연결한다면 폴러는 유지하되, SDK 워커를 중심으로 세션별 이미지를 빌드하고 세션당 하나의 샌드박스 실행에 나온 대로 작업 항목의secret을 샌드박스로 전달하도록 스폰 스크립트를 확장하세요.스크립트를 가리키도록 폴러를 시작하세요.
ant beta:worker poll --on-work ./spawn.sh
SDK 헬퍼
SDK는 서로 다른 제어 수준의 세 가지 헬퍼를 제공합니다. EnvironmentWorker는 대부분의 사용 사례를 다룹니다. 자체 세션별 프로세스를 시작하거나 이미 클레임된 세션에 대해 도구를 실행해야 할 때는 하위 수준 헬퍼를 사용하세요.
EnvironmentWorker: 즉시 사용 가능한 워커입니다. 폴링, 설정, 실행을 처음부터 끝까지 처리합니다..run(): 무기한 실행되며 세션이 도착하는 대로 처리합니다..handle_item(): 클레임된 단일 작업 항목을 처리하고 종료합니다. 작업, 세션, 환경 식별자를 명시적으로 전달하거나,ant beta:worker poll --on-work가 생성하는 프로세스에 설정하는ANTHROPIC_*변수를 읽도록 할 수 있습니다. 세션이 메모리 스토어를 마운트할 수 있도록 하려면 작업 항목의secret을work_secret(TypeScript에서는workSecret, Go에서는WorkSecret)으로 전달하거나ANTHROPIC_WORK_SECRET을 설정하세요.ant beta:worker poll --on-work는 해당 변수를 설정하지 않으므로, 세션당 하나의 샌드박스 실행에 나온 대로 스크립트의 표준 입력에 쓰는 작업 항목 JSON에서 secret을 읽으세요.memory_sync_interval(TypeScript에서는memorySyncIntervalMs, Go에서는MemorySyncInterval) 및memory_sync_deletions(memorySyncDeletions,MemorySyncDeletions): 세션이 실행되는 동안 연결된 메모리 스토어가 서버와 얼마나 자주 조정되는지, 그리고 에이전트가 로컬에서 삭제한 파일을 스토어에서도 삭제할지 여부입니다. 단위, 기본값, 메모리 지원 비활성화 방법은 동기화 구성을 참조하세요.
work.poller(): 사용자를 대신하여 작업 큐를 폴링하고 클레임된 각 세션을 제공합니다. 각 세션에 대해 무엇을 할지 직접 결정하고 싶을 때(예: 인프로세스로 도구를 실행하는 대신 샌드박스를 시작) 사용하세요.drain: 새 작업을 기다리지 않고 큐가 비면 폴링을 중지할지 여부입니다.block_ms: 반환하기 전에 작업이 도착하기를 기다리는 시간(밀리초)입니다. 1에서 999 사이여야 합니다(폴링당 대기 시간이며, 헬퍼가 자동으로 다시 폴링합니다). 논블로킹 확인을 하려면null(Python에서는None, Go에서는param.Null[int64]())을 전달하세요. 매개변수를 생략하면 기본값인 999ms 롱폴링을 사용합니다.reclaim_older_than_ms: 클레임되었지만 이 밀리초 내에 확인 응답되지 않은 작업 항목을 다시 클레임합니다.auto_stop(TypeScript에서는autoStop, Go에서는AutoStop): 루프 본문이 각 작업 항목 처리를 마치면 해당 항목에 대해 중지 신호를 게시할지 여부입니다. 작업 항목을 실행하는 쪽이 직접 중지를 게시하는 경우에는 항상 끄세요.handle_item()이 그렇게 하므로, 이 페이지의 웹훅 핸들러처럼 클레임된 항목을handle_item()에 넘길 때는 false로 설정하세요. 중지 호출을 소유하는 샌드박스를 시작하는 경우도 마찬가지입니다.
client.beta.sessions.events.tool_runner(): 세션 ID와 도구 목록이 주어지면 단일 세션에 대한 도구 호출을 실행합니다. 이미 작업을 클레임했고 실행 계층만 필요할 때 사용하세요.
자체 세션별 프로세스를 시작하려는 경우(예: 클레임된 각 세션에 대해 샌드박스를 띄우는 경우) 작업 폴러를 직접 사용하세요.
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(TypeScript에서는 allowedRoots, Go에서는 AllowedRoots)에 나열된 디렉터리로 제한되며, 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를 Claude API 키(환경 키가 아님)로 설정한 상태로 workers_polling이 최소 1인지 확인하세요.
ant beta:environments:work stats --environment-id "$ANTHROPIC_ENVIRONMENT_ID"workers_polling이 0에 머물러 있다면 워커가 큐에 도달하지 못하는 것입니다. 워커 호스트에 ANTHROPIC_ENVIRONMENT_KEY와 ANTHROPIC_ENVIRONMENT_ID가 설정되어 있는지 확인하세요. 전체 통계 응답과 다른 언어 예제는 큐 깊이 읽기를 참조하세요.
세션 시작
워커가 실행 중이면 해당 환경을 대상으로 하는 세션을 생성하세요. AGENT_ID를 시작하기 전에에서 기록한 에이전트 ID로 설정하세요. 세션은 환경의 작업 큐에 들어가 워커가 클레임할 때까지 대기합니다. 연결된 워커가 없으면 세션은 실패하지 않고 큐에 남아 있습니다.
Anthropic은 자체 호스팅 샌드박스에 파일이나 GitHub 리포지토리를 마운트하지 않습니다. 세션별 파일을 사용할 수 있게 하려면 세션 metadata 필드에 파일 참조(예: S3 경로 또는 커밋 SHA)를 전달하세요. 클레임된 작업 항목은 세션의 메타데이터를 포함하지 않지만 세션 ID는 포함합니다. 스폰 스크립트나 --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개의 메모리 스토어를 허용합니다. 자체 호스팅 환경에서는 Anthropic의 인프라가 아닌 SDK 워커가 에이전트를 위해 각 스토어를 구체화하므로, 메모리 스토어를 사용하려면 Python, TypeScript 또는 Go SDK의 EnvironmentWorker(또는 그 handle_item() 메서드)가 필요합니다.
ant CLI 워커(ant beta:worker poll 및 ant beta:worker run)는 메모리 스토어를 마운트하지 않습니다. CLI 폴러와 메모리 스토어를 함께 사용하려면 세션당 하나의 샌드박스 실행에 설명된 대로 세션별 샌드박스 내에서 SDK 워커를 실행하세요.
Claude Platform on AWS의 자체 호스팅 환경에서는 세션에 메모리 스토어를 연결할 수 없습니다.
워커가 메모리를 처리하는 방식
워커가 메모리 스토어가 연결된 세션의 작업 항목을 클레임하면 다음을 수행합니다.
- 작업 항목의 세션별
secret으로 인증하여 연결된 각 스토어를 워커 호스트의mount_path에 다운로드합니다.mount_path는 클라우드 세션이 사용하는 것과 동일한/mnt/memory/아래의 디렉터리(예: "User Preferences"라는 이름의 스토어는/mnt/memory/user-preferences/)이며, 세션의 시스템 프롬프트가 이를 에이전트에게 설명합니다. - 해당 디렉터리들을 파일 도구의 허용 루트에 추가하고,
access: "read_only"로 연결된 스토어의 디렉터리는 읽기 전용 루트에 추가하여, 에이전트가 작업 디렉터리에서 사용하는 것과 동일한read,write,edit,glob,grep도구로 메모리를 다룰 수 있게 합니다. - 도구 호출 후 동기화 간격(기본 15초)당 최대 한 번 로컬과 원격 변경 사항을 조정합니다. 스토어에서 변경된 메모리는 디스크에 기록되고, 에이전트가 변경한 파일은 스토어에 업로드됩니다.
- 세션이 끝나면 최종 동기화를 실행하고, 아직 대기 중인 업로드를 최대 30초 동안 플러시한 다음, 생성했던 디렉터리를 제거합니다. 세션 실행 중에 취소된 워커는 최종 동기화를 건너뛰지만 종료 전에 변경된 파일을 업로드하고 디렉터리를 제거합니다.
Anthropic 측의 메모리 스토어가 여전히 신뢰할 수 있는 원본입니다. 메모리 버전, 수정(redaction), Console에서의 메모리 보기 및 편집은 클라우드 세션과 동일하게 작동하며, 에이전트의 메모리 읽기 및 쓰기는 이벤트 스트림에 일반 도구 이벤트로 나타납니다. 각 워커가 간격을 두고 동기화하므로, 한 세션에서 기록된 변경 사항은 두 세션 모두 동기화한 후에야 실행 중인 다른 세션에 보이게 됩니다. 기본 간격에서는 일반적으로 1분보다 훨씬 짧습니다. 클라우드 샌드박스의 세션들은 서로의 변경 사항을 거의 즉시 봅니다.
각 스토어 디렉터리에는 디렉터리를 해당 스토어에 연결하는 .anthropic-memory-store라는 마커 파일이 있습니다. 그대로 두세요. 워커는 마커가 없거나 변경된 디렉터리를 동기화하지 않습니다.
호스트 준비
자체 호스팅 샌드박스의 메모리 스토어는 워커 호스트(시작하기 전에의 Linux 호스트)에 POSIX 파일시스템이 필요합니다. 워커가 메모리 파일을 열 때 O_NOFOLLOW를 요구하므로 Windows 호스트는 지원되지 않습니다. 대소문자만 다른 메모리 경로가 충돌하지 않도록 대소문자를 구분하는 파일시스템을 권장합니다.
워커를 시작하기 전에 상위 디렉터리를 생성하고 워커가 실행되는 사용자가 쓸 수 있도록 만드세요.
sudo mkdir -p /mnt/memory && sudo chown "$USER" /mnt/memory스토어별 디렉터리를 직접 생성하지 마세요. 워커는 세션이 시작될 때 각 스토어의 mount_path 디렉터리(예: /mnt/memory/user-preferences)를 생성하고, 해당 경로에 이미 무언가가 존재하면 세션의 작업 시작을 거부하며, 세션이 끝나면 디렉터리를 제거합니다. 여기서 두 가지 운영 규칙이 따릅니다.
- 세션들이 동일한 스토어를 연결하는 경우 파일시스템당 하나의 세션을 실행하세요. 두 세션 모두 동일한 경로가 필요하므로, 두 세션이 하나의 호스트에서 동시에 동일한 스토어를 마운트할 수 없습니다. 세션당 하나의 샌드박스 실행에 설명된 대로 각 세션에 자체 샌드박스를 부여하면 이 규칙이 충족됩니다.
- 워커를 정상적으로 중지하세요. 세션 실행 중에 워커를 중지할 때,
EnvironmentWorker는 강제 종료(kill)가 아닌 취소된 경우에만 세션의 변경된 메모리 파일을 업로드하고 스토어 디렉터리를 제거합니다. 강제 종료된 프로세스는 정리 작업을 실행하지 않으며, 워커는 자체적으로 시그널 핸들러를 설치하지 않습니다. 워커를 실행하는 프로세스에서 SIGTERM과 SIGINT를 취소에 연결하세요. TypeScript에서는 워커에 전달하는signal을 abort하고, Go에서는 context를 취소하고, Python에서는run()또는handle_item()을 실행하는 태스크를 취소하세요. 이 페이지의 독립 실행형 워커처럼 워커가 곧 프로세스인 경우에는 시그널 핸들러에서, 워커가 웹훅 핸들러 내부에서 실행되어 서버의 시그널을 가로채서는 안 되는 경우에는 서버 자체의 종료 훅에서 이를 수행하세요. 그런 다음 SIGTERM으로 워커를 중지하고, 최종 업로드에 그만큼 시간이 걸릴 수 있으므로 강제 종료 전에 최소 30초의 종료 시간을 주세요. 정리 작업이 실행되기 전에 워커가 강제 종료되었다면, 해당 스토어를 연결하는 다음 세션 전에/mnt/memory/아래에 남은 스토어 디렉터리를 제거하세요. 동기화되지 않은 편집 내용은 손실됩니다.
세션당 하나의 샌드박스 실행
워커 실행의 세션당 샌드박스 패턴은 각 세션에 새로운 파일시스템을 제공하며, 이는 세션들이 동일한 스토어를 연결할 때 호스트 준비에서 요구하는 사항입니다. 호스트의 폴러로는 ant beta:worker poll --on-work(또는 SDK의 work 폴러)를 그대로 유지하세요.
거기에 표시된 ant beta:worker run 엔트리포인트는 메모리 스토어를 마운트하지 않으므로, 대신 SDK 워커를 중심으로 세션당 이미지를 빌드하세요. 해당 엔트리포인트는 EnvironmentWorker를 생성하고 handle_item()(TypeScript에서는 handleItem, Go에서는 HandleItem)을 호출하며, 이는 ANTHROPIC_* 변수에서 세션, work, 환경 식별자를 읽고 ANTHROPIC_WORK_SECRET에서 work 항목의 세션별 secret을 읽습니다. secret을 work_secret(TypeScript에서는 workSecret, Go에서는 WorkSecret)으로 명시적으로 전달할 수도 있습니다.
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()은 spawn 스크립트가 전달한 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을 설정하지 않으므로, 생성 스크립트는 표준 입력의 work 항목 JSON에서 secret을 읽어 샌드박스로 전달합니다:
#!/bin/bash
# spawn.sh: 클레임된 작업 항목마다 한 번씩 호출됩니다
# 클레임된 작업 항목은 stdin을 통해 JSON으로 전달됩니다. 해당 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의 work 폴러로 work를 클레임하는 경우, 클레임한 각 항목의 secret을 동일한 방식으로 실행하는 샌드박스에 전달하세요. 해당 세션을 처리하는 샌드박스에만 전달하고, 절대 로그에 기록하지 마세요.
샌드박스 이미지에는 쓰기 가능한 /mnt/memory도 필요합니다(호스트 준비 참조). 각 샌드박스는 하나의 세션만 처리하고 이후 폐기되므로, 정리해야 할 남은 디렉터리가 없으며 메모리 디렉터리를 호스트에 바인드 마운트할 필요도 없습니다. 워커가 샌드박스가 종료되기 전에 그 내용을 스토어에 업로드하기 때문입니다. 세션이 끝나기 전에 컨테이너를 중지하는 경우, 컨테이너를 강제 종료하는 대신 엔트리포인트가 취소로 변환하는 시그널을 보내세요(호스트 준비 참조). 그래야 업로드가 여전히 실행됩니다. 컨테이너가 업로드를 마칠 시간도 주세요. Docker는 기본적으로 중지 시그널 후 10초 뒤에 SIGKILL을 보내므로, docker run의 --stop-timeout 또는 오케스트레이터의 종료 유예 기간을 사용하여 이 제한을 호스트 준비에서 요구하는 최소 30초 이상으로 늘리세요.
동기화 구성
두 가지 EnvironmentWorker 옵션이 메모리 동작을 제어합니다:
memory_sync_interval(Python, 초 단위; TypeScript에서는memorySyncIntervalMs, 밀리초 단위; Go에서는MemorySyncInterval, duration): 세션이 실행되는 동안 연결된 스토어가 서버와 조정되는 빈도입니다. 기본값은 15초이며 최소값은 5초입니다. 간격이 짧을수록 다른 세션이 오래된 메모리를 보게 되는 시간 창이 줄어들지만, 메모리 스토어 요청이 더 많아집니다. Python의None, TypeScript의null, 또는 Go의 음수 duration은 메모리 지원을 완전히 비활성화합니다. 워커는 스토어를 다운로드하지도 동기화하지도 않으며, 메모리 스토어가 연결된 세션은 시스템 프롬프트가 여전히 이를 설명하더라도 메모리 스토어 없이 실행됩니다. 따라서 세션이 메모리 스토어를 연결하지 않는 워커에서만 메모리 지원을 비활성화하세요. 메모리 지원이 활성화된 동안, 스토어가 연결된 세션에 대해 세션별secret없이 도착한 work 항목은 메모리 없이 실행되는 대신 실패합니다(메모리 마운트 문제 해결 참조).memory_sync_deletions(TypeScript에서는memorySyncDeletions, Go에서는MemorySyncDeletions): 에이전트가 로컬에서 삭제한 파일을 스토어에서도 삭제할지 여부입니다. 값은 Python과 TypeScript에서"enabled"(기본값),"log_only","disabled"중 하나이며, Go에서는 상수environments.MemorySyncDeletionsEnabled(제로 값),environments.MemorySyncDeletionsLogOnly,environments.MemorySyncDeletionsDisabled중 하나입니다. 활성화된 경우, 워커는 이후 동기화에서 파일이 여전히 없음을 확인하면 스토어에서 메모리를 삭제합니다. log-only 모드에서는 동일한 검사를 실행하지만 삭제했을 항목을 로그에만 기록하므로, enabled 모드를 신뢰하기 전에 워커가 무엇을 삭제할지 관찰할 수 있습니다. 비활성화된 경우, 스토어에서 절대 삭제하지 않습니다. 업로드와 다운로드는 이 설정의 영향을 받지 않습니다.
이 옵션들은 워커를 생성하는 곳에서 설정하세요. 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 도구 자체는 성공하며 에이전트에게 오류가 전달되지 않습니다. 에이전트의 변경이 여전히 적용되어야 한다면, 동기화 후 파일을 다시 읽고 변경을 다시 수행할 수 있습니다.
메모리 마운트 문제 해결
워커는 마운트 및 백그라운드 동기화 실패를 세션에 보고하는 대신 로그에 기록합니다. 읽기 전용 거부만이 도구 오류로 에이전트에게 전달됩니다(읽기 전용 스토어와 충돌 참조). 워커가 세션을 클레임할 때 메모리 스토어를 마운트할 수 없으면, 워커는 work 항목을 실패 처리합니다. 세션은 오류 이벤트를 내보내지 않고 idle 상태로 유지됩니다.
| 증상 | 원인 | 해결 방법 |
|---|---|---|
워커 로그에 the work item carried no sessions token(Go에서는 ErrSessionMemoryNoToken 오류)이 포함되고 work 항목이 실패합니다. | work 항목의 세션별 secret이 워커에 도달하지 않았습니다. 자체 호스팅 샌드박스의 메모리 스토어가 조직에 대해 활성화되지 않았거나, 생성 스크립트가 secret을 샌드박스로 전달하지 않았습니다. | 세션당 샌드박스 패턴에서는 세션당 하나의 샌드박스 실행에 표시된 대로 ANTHROPIC_WORK_SECRET을 샌드박스로 전달하세요. 워커가 하나의 프로세스에서 폴링하고 세션을 실행하는데도 여전히 이 로그가 기록된다면 지원팀에 문의하세요. |
워커 로그에 something already exists at the memory store's path가 포함됩니다. | 이전 세션에서 남은 디렉터리로, 보통 teardown이 실행되기 전에 워커가 강제 종료된 세션의 것입니다. | 로그 줄에 명시된 남은 디렉터리를 제거하세요. 동기화되지 않은 그 안의 편집 내용은 손실됩니다. |
워커 로그에 cannot create the memory store's folder 및 the worker host must make this mount path writable이 포함됩니다. | 워커가 실행되는 사용자가 /mnt/memory 아래에 디렉터리를 생성할 수 없습니다. | /mnt/memory를 생성하고 해당 사용자에게 chown하세요. 호스트 준비를 참조하세요. |
워커가 세션을 클레임한 직후 세션이 requires_action 중지 사유와 함께 오류 이벤트 없이 idle 상태로 머뭅니다. | 앞서 언급한 이유 중 하나로 메모리 스토어를 마운트할 수 없어 워커가 work 항목을 실패 처리했습니다. | 호스트에서 원인을 수정한 다음 user.interrupt 이벤트를 보내세요. 세션의 work가 다시 큐에 추가되고 이를 클레임하는 다음 워커가 마운트를 재시도합니다. |
샌드박스에서 커스텀 도구 제공
커스텀 도구는 여러분의 코드가 실행하는 도구입니다. 에이전트는 agent.custom_tool_use 이벤트를 내보내고 일치하는 user.custom_tool_result를 기다립니다. 워커가 그 코드가 될 수 있으며, 워커는 샌드박스 내부에서 실행되므로 도구는 샌드박스에 대해 구성한 내부 서비스, 자격 증명, 네트워크 이그레스에 접근할 수 있고 그 이상은 접근할 수 없습니다. 환경 키가 커스텀 도구 결과 게시를 승인하므로, Claude API 키는 워커 호스트에 두지 않아도 됩니다.
에이전트에 도구 선언
워커가 등록하는 도구와
name이 일치하는custom항목을 에이전트의tools에 추가하세요. 전체 선언 형태는 커스텀 도구를 참조하세요.{ "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 커넥터는 Anthropic 측에서 MCP 서버에 연결하므로, 서버는 Anthropic이 직접 또는 MCP 터널을 통해 도달할 수 있는 HTTP 엔드포인트를 노출해야 합니다. 여러분의 네트워크에서만 도달할 수 있는 서버를 사용하려면, 대신 워커를 MCP 클라이언트로 만들고 서버의 도구를 커스텀 도구로 선언하세요. MCP 서버는 네트워크 외부로부터의 인바운드 연결이 필요하지 않습니다. Anthropic은 에이전트에 선언한 도구 정의, 각 호출의 입력, 워커가 다시 게시하는 결과를 받습니다. 런타임에 모델은 래핑된 도구를 다른 커스텀 도구와 마찬가지로 호출합니다:
- 에이전트가
agent.custom_tool_use이벤트를 내보냅니다. - 샌드박스 내부의 워커가 열려 있는 MCP 세션을 통해 네트워크의 서버로 호출을 전달합니다.
- 워커가 서버의 응답을
user.custom_tool_result로 게시합니다.
SDK의 클라이언트 측 MCP 헬퍼는 서버의 도구를 워커가 받아들이는 실행 가능한 도구로 변환합니다. Anthropic SDK와 함께 MCP SDK를 설치하세요(pip install "anthropic[mcp]" "mcp>=1.24", npm install @modelcontextprotocol/sdk, go get github.com/modelcontextprotocol/go-sdk). 예제는 인증 없이 연결합니다. 자격 증명을 보내려면 MCP 전송에 전달하는 HTTP 클라이언트 또는 요청 옵션(Python에서는 http_client, TypeScript에서는 requestInit, Go에서는 HTTPClient)을 구성하세요.
에이전트에 서버의 도구 선언
MCP 서버의 도구를 나열하고 각각을
custom도구로 선언하세요. MCP의name,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: # 워커 호스트가 아니라 에이전트를 생성하는 곳에서 실행하세요. # Claude API 키(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 서버의 도구를 한 번 나열하며 실행 중인 세션에 도구를 추가할 수 없습니다. 서버의 도구가 변경되면, 에이전트에서 또는 에이전트 구성 업데이트를 통해 idle 세션에서 다시 선언하고 워커를 재시작하세요.
- 이름과 설명은 Managed Agents API에 맞아야 합니다. 커스텀 도구 이름은 에이전트별로 고유하며 문자, 숫자, 밑줄, 하이픈을 사용합니다(1–128자). 비어 있지 않은 설명이 필요하며, 에이전트의
tools배열은 최대 128개 항목을 받습니다(래핑된 각 도구가 하나의 항목이고, 내장 도구 세트가 하나 더 차지합니다). API는 도구 이름을 재사용하거나,bash또는read같은 내장 에이전트 도구의 이름을 커스텀 도구에 붙이거나, 예약된mcp__접두사를 사용하는 선언을 거부합니다. MCP 헬퍼는 서버의 이름과 설명을 유지하므로, 필요한 경우 이름을 바꾸거나 줄이세요. 두 서버가 동일한 도구 이름을 노출하는 경우, 접두사가 붙은 이름으로 래퍼를 직접 정의하고 서버의 원래 도구 이름을 호출하도록 하세요. - 대부분의 스키마는 변경 없이 통과합니다. API는
additionalProperties및title과 같이 MCP 서버가 일반적으로 내보내는 JSON Schema 키워드를 받아들입니다. 커스텀 도구의input_schema어디에서든$ref와 같은 참조 키워드는 거부하므로, pydantic 같은 생성기가$defs로 분리하는 스키마는 인라인하세요. 또한 최상위oneOf,anyOf,allOf와 문자, 숫자, 밑줄, 점, 하이픈(1–64자) 이외의 속성 이름도 거부합니다. - 도구 실패는 오류 도구 결과로 나타납니다. MCP 서버가 도구 오류를 보고하면, 워커는 모델이 반응할 수 있는 오류 도구 결과를 게시합니다. 오디오 블록 및 리소스 링크와 같이 도구 결과에 해당하는 것이 없는 MCP 콘텐츠도 오류로 나타납니다. Python 워커 예제가
read_timeout_seconds로 하는 것처럼, 더 빠르고 명확한 실패를 위해 MCP 클라이언트에 타임아웃을 설정하세요. 타임아웃이 없으면, 멈춘 호출은 TypeScript MCP SDK의 기본 요청 타임아웃(약 1분)이 발동하거나 워커 자체의 백스톱이 발동할 때에만 오류 결과가 됩니다. Python에서는 약 2분 30초, Go에서는 2분이며, Go에서는 워커가 120초 기본값을 초과한 도구 호출을 취소하고 오류 결과를 게시합니다. - 운영하거나 신뢰하는 서버를 래핑하세요. 래핑된 도구의 이름, 설명, 결과는 다른 도구와 마찬가지로 모델의 컨텍스트에 들어갑니다. 이는 워커 호스트의
bash를 포함하여 에이전트가 다른 도구로 수행하는 작업에 영향을 줄 수 있는 신뢰할 수 없는 입력입니다. 에이전트가 사용하도록 의도한 도구만 선언하세요. - 권한 정책은 커스텀 도구에 적용되지 않습니다. 권한 정책은 내장 및 MCP 도구 세트를 관리합니다. 워커는 모델이 수행하는 모든 래핑된 도구 호출을 실행하므로, 승인 단계는 여러분의 도구 코드에 넣으세요.
모니터링 및 운영
이 호출들은 워커 플릿을 관찰하고 관리하기 위해 Claude API 키로 인증된 모니터링 또는 운영 도구에서 실행됩니다. 클레임 및 keep-alive 루프는 워커 헬퍼 내부에서 처리되므로, 해당 엔드포인트를 직접 호출하지 않습니다.
큐 깊이 읽기
work.stats는 환경의 큐 상태를 반환합니다:
depth는 클레임되기를 기다리는 항목의 수입니다. 이 값을 기준으로 워커 플릿을 확장하거나 백로그에 대해 알림을 설정하세요.pending은 워커가 클레임했지만 아직 확인(acknowledge)하지 않은 항목의 수입니다. 워커 헬퍼는 각 항목을 처리하기 전에 확인하므로, 정상 운영에서는 이 값이 0에 가깝게 유지됩니다. 지속적으로 0이 아닌 값은 워커가 클레임과 확인 사이에서 멈췄음을 의미합니다.oldest_queued_at은 클레임되기를 기다리거나 클레임되었지만 아직 확인되지 않은, 큐에 여전히 남아 있는 가장 오래된 항목의 타임스탬프이며, 없을 경우null입니다.workers_polling은 지난 30초 동안 폴링한 워커의 수입니다. 활성 상태(liveness) 알림에 사용하세요.
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을 사용하여 특정 세션을 처리하는 워커에게 세션 종료를 요청하세요. 기본적으로 work 항목은 stopping으로 이동합니다. 워커는 다음 리스 하트비트에서 이를 감지하고, 세션의 진행 중인 도구 호출을 취소하고, 종료를 확인하며, 이 시점에 work 항목은 stopped가 됩니다. 워커의 확인을 기다리는 대신 work 항목을 즉시 stopped로 표시하려면 요청 본문에 force: true를 전달하세요(CLI에서는 --force 전달).
이 호출들은 워커 호스트가 아닌 운영 도구에서 실행되므로, ANTHROPIC_WORK_ID가 자동으로 설정되지 않습니다. 다음 예제를 실행하기 전에 대상 work 항목의 ID로 설정하세요. work 항목의 ID를 찾으려면 Environments Work 엔드포인트를 통해 환경의 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)다음 단계
Was this page helpful?