---
title: 자체 호스팅 샌드박스
url: https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes
description: Claude Managed Agents 세션을 자체 호스팅 샌드박스에서 실행하여 도구 실행, 파일, 네트워크 egress를 자체 인프라 내에 유지합니다.
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

"Self-hosted sandbox"(자체 호스팅 샌드박스)는 에이전트의 도구 실행을 Anthropic이 관리하는 클라우드 샌드박스에서 사용자가 제어하는 인프라로 옮기며, 에이전트 실행은 계속 Anthropic이 담당합니다. 이것이 무엇을 의미하는지 알아보고 에이전트에 적합한지 판단하려면 [에이전트 환경 선택하기](https://platform.claude.com/docs/ko/managed-agents/choosing-an-environment)를 참조하세요.

## 작동 방식

`self_hosted` 환경은 작업 큐 역할을 합니다. 사용자는 해당 큐를 처리하는 자체 인프라상의 프로세스인 **environment worker**(환경 워커)를 실행합니다:

1. 환경을 대상으로 하는 [세션](https://platform.claude.com/docs/ko/managed-agents/sessions)을 생성합니다. Anthropic은 세션을 작업 항목으로 큐에 추가합니다.
2. 워커가 작업 항목을 가져오고 에이전트의 [스킬](https://platform.claude.com/docs/ko/managed-agents/skills)과 세션의 [메모리 스토어](https://platform.claude.com/docs/ko/managed-agents/memory)를 다운로드합니다.
3. Claude는 Anthropic 측에서 실행되며 도구 호출을 요청합니다. 워커는 각 호출을 로컬에서 실행하고 결과를 다시 전송합니다.

도구 입력과 출력은 여전히 Anthropic의 "control plane"(제어 플레인)으로 전달되므로, 모델은 결과를 확인하고 다음에 수행할 작업을 결정할 수 있습니다. Anthropic은 스킬과 메모리 스토어를 저장합니다. 사용자의 샌드박스는 세션을 위한 사본을 보유합니다. 전체 데이터 흐름 경계는 [보안 모델](https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes-security)을 참조하세요.

자체 호스팅 샌드박스는 Managed Agents에서 사용할 수 있는 모든 Claude 모델을 지원합니다. 모델은 환경이 아닌 에이전트에서 구성됩니다.

`ant` CLI와 Python, TypeScript, Go SDK는 사전 빌드된 워커를 제공합니다. Cloudflare, Daytona, Modal과 같은 샌드박스 제공업체도 자체 [플랫폼 가이드](https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes#platform-guides)를 게시합니다.

## 빠른 시작

이 빠른 시작에서는 `ant` CLI로 상시 실행되는 워커 하나를 실행하고, 세션을 보낸 다음, 에이전트의 도구 호출이 사용자의 호스트에서 실행되었는지 확인합니다.

### 사전 요구 사항

* **에이전트:** 에이전트가 없다면 먼저 [Claude Managed Agents 시작하기](https://platform.claude.com/docs/ko/managed-agents/quickstart)를 완료하고 에이전트 ID를 기록해 두세요.
* **Linux 호스트:** 호스트에는 정확히 해당 경로에 `/bin/bash`가 있어야 합니다. 워커에는 아웃바운드 HTTPS만 필요합니다.
* **Claude API 키:** 세션을 생성하고 큐 통계를 읽기 위해 사용자 자신의 머신에서 사용합니다. 에이전트 도구 호출이 읽을 수 있는 워커 호스트에는 두지 마세요.
* **사용자 자신의 머신에 설치된 `ant` CLI 또는 SDK:** 이 빠른 시작의 통계 및 세션 단계는 워커 호스트가 아닌 사용자의 머신에서 실행됩니다. 워커용 [설치 단계](https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes#run-your-first-session)와 같은 방식으로 CLI를 설치하거나 [SDK](https://platform.claude.com/docs/ko/cli-sdks-libraries/overview)를 설치하세요.

<Note>
  [Claude Platform on AWS](https://platform.claude.com/docs/ko/build-with-claude/claude-platform-on-aws)에서는 워커가 환경 키가 아닌 AWS IAM(SigV4) 또는 [AWS Console에서 생성한 API 키](https://platform.claude.com/docs/ko/build-with-claude/claude-platform-on-aws#api-key-authentication)로 인증합니다. 워커가 실행되는 IAM 주체에 [`AnthropicSelfHostedEnvironmentAccess`](https://platform.claude.com/docs/ko/api/claude-platform-on-aws-iam-actions#managed-policies) 관리형 정책을 연결하세요. Claude Console에서 생성한 환경 키는 Claude Platform on AWS 엔드포인트에서 작동하지 않습니다.
</Note>

### 첫 번째 세션 실행하기

<Steps>
  <Step title="자체 호스팅 환경 생성하기">
    Claude Console에서 [Environments](https://platform.claude.com/environments) 페이지(`platform.claude.com/environments`)로 이동하여 **Create environment**를 클릭하고, **Hosting**에서 **Self-hosted**를 선택하세요.

    또는 API를 통해:

    <CodeGroup defaultLanguage="CLI">
      ```bash cURL
      curl -sS --fail-with-body https://api.anthropic.com/v1/environments \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -H "anthropic-beta: managed-agents-2026-04-01" \
        -H "content-type: application/json" \
        -d '{
          "name": "self-hosted",
          "config": {"type": "self_hosted"}
        }'
      ```

      <CodeGroupItem>
        ```bash CLI
        ant apply environment.yaml
        ```

        <File filename="environment.yaml">
          ```yaml
          # yaml-language-server: $schema=https://platform.claude.com/schemas/ant/beta/environment.json
          name: self-hosted
          config:
            type: self_hosted
          ```
        </File>
      </CodeGroupItem>

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

      environment = client.beta.environments.create(
          name="self-hosted", config={"type": "self_hosted"}
      )
      print(environment.id)
      ```

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

      const environment = await client.beta.environments.create({
        name: "self-hosted",
        config: { type: "self_hosted" }
      });
      console.log(environment.id);
      ```

      ```csharp C#
      using Anthropic.Models.Beta.Environments;

      var client = new AnthropicClient();

      var environment = await client.Beta.Environments.Create(
          new EnvironmentCreateParams
          {
              Name = "self-hosted",
              Config = new BetaSelfHostedConfigParams(),
          }
      );
      Console.WriteLine(environment.ID);
      ```

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

      environment, err := client.Beta.Environments.New(context.Background(), anthropic.BetaEnvironmentNewParams{
      	Name: "self-hosted",
      	Config: anthropic.BetaEnvironmentNewParamsConfigUnion{
      		OfSelfHosted: &anthropic.BetaSelfHostedConfigParams{},
      	},
      })
      if err != nil {
      	panic(err)
      }
      fmt.Println(environment.ID)
      ```

      ```java Java
      import com.anthropic.models.beta.environments.BetaSelfHostedConfigParams;
      import com.anthropic.models.beta.environments.EnvironmentCreateParams;

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

          var environment = client.beta().environments().create(
              EnvironmentCreateParams.builder()
                  .name("self-hosted")
                  .config(BetaSelfHostedConfigParams.builder().build())
                  .build()
          );
          IO.println(environment.id());
      }
      ```

      ```php PHP
      $client = new \Anthropic\Client();

      $environment = $client->beta->environments->create(
          name: 'self-hosted',
          config: ['type' => 'self_hosted'],
      );
      echo $environment->id, PHP_EOL;
      ```

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

      environment = client.beta.environments.create(
        name: "self-hosted",
        config: {type: :self_hosted}
      )
      puts environment.id
      ```
    </CodeGroup>
  </Step>

  <Step title="환경 키 생성하기">
    Console에서 환경을 열고 **Generate environment key**를 클릭합니다. 환경 키는 워커를 해당 큐에 인증합니다. API를 통해 생성한 환경이라도 환경 키는 Console에서만 생성할 수 있습니다.

    워커 호스트에서 환경 ID와 키를 export합니다:

    ```bash
    export ANTHROPIC_ENVIRONMENT_KEY="sk-ant-oat01-..."
    export ANTHROPIC_ENVIRONMENT_ID="env_..."
    ```
  </Step>

  <Step title="ant CLI 설치하기">
    워커 호스트에서 다음을 실행합니다.

    <Tabs>
      <Tab title="curl (Linux/WSL)">
        Linux 환경의 경우 릴리스 바이너리를 직접 다운로드합니다.

        ```bash
        VERSION=1.42.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 릴리스 페이지](https://github.com/anthropics/anthropic-cli/releases)에서 확인할 수 있습니다.
      </Tab>

      <Tab title="Homebrew (macOS)">
        ```bash
        brew install anthropics/tap/ant
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="워커 시작하기">
    작업 디렉터리를 생성한 다음 워커를 시작합니다. `--workdir`의 기본값은 현재 디렉터리이므로, 시스템 기본값과 일치하도록 `/workspace`를 전달하세요.

    ```bash
    sudo mkdir -p /workspace && sudo chown "$USER" /workspace
    ant beta:worker poll --workdir /workspace
    ```

    워커는 export한 두 변수를 읽고 중지할 때까지 폴링합니다.
  </Step>

  <Step title="워커 연결 확인하기">
    사용자 자신의 머신에서 `ANTHROPIC_API_KEY`를 Claude API 키(환경 키가 아님)로 설정하고 `ANTHROPIC_ENVIRONMENT_ID` (python, ruby: `environment_id`; typescript, java, csharp: `environmentId`; go: `environmentID`; php: `$environmentId`)를 환경 ID로 설정합니다. `workers_polling` (java, php: `workersPolling`; csharp, go: `WorkersPolling`)이 1 이상인지 확인하세요:

    <CodeGroup>
      ```bash cURL
      curl -sS --fail-with-body "https://api.anthropic.com/v1/environments/$ANTHROPIC_ENVIRONMENT_ID/work/stats" \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -H "anthropic-beta: managed-agents-2026-04-01"
      ```

      ```bash CLI
      ant beta:environments:work stats --environment-id "$ANTHROPIC_ENVIRONMENT_ID"
      ```

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

      stats = client.beta.environments.work.stats(environment_id)
      print(f"workers_polling={stats.workers_polling}")
      ```

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

      const stats = await client.beta.environments.work.stats(environmentId);

      console.log(`workers_polling=${stats.workers_polling}`);
      ```

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

      var stats = await client.Beta.Environments.Work.Stats(environmentId);

      Console.WriteLine($"workers_polling={stats.WorkersPolling}");
      ```

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

      stats, err := client.Beta.Environments.Work.Stats(
      	context.Background(),
      	environmentID,
      	anthropic.BetaEnvironmentWorkStatsParams{},
      )
      if err != nil {
      	panic(err)
      }

      fmt.Printf("workers_polling=%d\n", stats.WorkersPolling)
      ```

      ```java Java
      var client = AnthropicOkHttpClient.fromEnv();

      var stats = client.beta().environments().work().stats(environmentId);

      IO.println("workers_polling=" + stats.workersPolling().orElse(null));
      ```

      ```php PHP
      $client = new Client();

      $stats = $client->beta->environments->work->stats($environmentId);

      printf("workers_polling=%d\n", $stats->workersPolling);
      ```

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

      stats = client.beta.environments.work.stats(environment_id)

      puts "workers_polling=#{stats.workers_polling}"
      ```
    </CodeGroup>

    `workers_polling` (java, php: `workersPolling`; csharp, go: `WorkersPolling`)이 0으로 유지되면 [문제 해결](https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes-operations#troubleshooting)을 참조하세요.
  </Step>

  <Step title="세션 시작하기">
    `AGENT_ID` (python, ruby: `agent_id`; typescript, java, csharp: `agentId`; go: `agentID`; php: `$agentId`)를 에이전트 ID로 설정합니다. 환경을 대상으로 하는 세션을 생성한 다음 작업을 보냅니다:

    <CodeGroup>
      ```bash cURL
      SESSION_ID=$(curl -sS --fail-with-body https://api.anthropic.com/v1/sessions \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -H "anthropic-beta: managed-agents-2026-04-01" \
        -H "content-type: application/json" \
        -d '{
          "agent": "'"$AGENT_ID"'",
          "environment_id": "'"$ANTHROPIC_ENVIRONMENT_ID"'"
        }' | jq -er '.id'
      )

      curl -sS --fail-with-body "https://api.anthropic.com/v1/sessions/$SESSION_ID/events" \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -H "anthropic-beta: managed-agents-2026-04-01" \
        -H "content-type: application/json" \
        -d '{
          "events": [
            {
              "type": "user.message",
              "content": [
                {
                  "type": "text",
                  "text": "Write the output of \"uname -a\" to hello.txt in your working directory."
                }
              ]
            }
          ]
        }'
      ```

      ```bash CLI
      SESSION_ID=$(ant beta:sessions create \
        --agent "$AGENT_ID" \
        --environment-id "$ANTHROPIC_ENVIRONMENT_ID" \
        --transform id --raw-output)

      ant beta:sessions:events send --session-id "$SESSION_ID" <<'YAML'
      events:
        - type: user.message
          content:
            - type: text
              text: Write the output of "uname -a" to hello.txt in your working directory.
      YAML
      ```

      ```python Python
      session = client.beta.sessions.create(
          agent=agent_id,
          environment_id=environment_id,
      )

      client.beta.sessions.events.send(
          session.id,
          events=[
              {
                  "type": "user.message",
                  "content": [
                      {
                          "type": "text",
                          "text": 'Write the output of "uname -a" to hello.txt in your working directory.',
                      },
                  ],
              },
          ],
      )
      ```

      ```typescript TypeScript
      const session = await client.beta.sessions.create({
        agent: agentId,
        environment_id: environmentId
      });

      await client.beta.sessions.events.send(session.id, {
        events: [
          {
            type: "user.message",
            content: [
              {
                type: "text",
                text: 'Write the output of "uname -a" to hello.txt in your working directory.'
              }
            ]
          }
        ]
      });
      ```

      ```csharp C#
      var session = await client.Beta.Sessions.Create(new()
      {
          Agent = agentId,
          EnvironmentID = environmentId,
      });

      await client.Beta.Sessions.Events.Send(session.ID, new()
      {
          Events =
          [
              new BetaManagedAgentsUserMessageEventParams
              {
                  Type = BetaManagedAgentsUserMessageEventParamsType.UserMessage,
                  Content =
                  [
                      new BetaManagedAgentsTextBlock
                      {
                          Type = BetaManagedAgentsTextBlockType.Text,
                          Text = "Write the output of \"uname -a\" to hello.txt in your working directory.",
                      },
                  ],
              },
          ],
      });
      ```

      ```go Go
      session, err := client.Beta.Sessions.New(context.Background(), anthropic.BetaSessionNewParams{
      	Agent:         anthropic.BetaSessionNewParamsAgentUnion{OfString: anthropic.String(agentID)},
      	EnvironmentID: environmentID,
      })
      if err != nil {
      	panic(err)
      }

      _, err = client.Beta.Sessions.Events.Send(context.Background(), session.ID, anthropic.BetaSessionEventSendParams{
      	Events: []anthropic.BetaManagedAgentsEventParamsUnion{{
      		OfUserMessage: &anthropic.BetaManagedAgentsUserMessageEventParams{
      			Type: anthropic.BetaManagedAgentsUserMessageEventParamsTypeUserMessage,
      			Content: []anthropic.BetaManagedAgentsUserMessageEventParamsContentUnion{{
      				OfText: &anthropic.BetaManagedAgentsTextBlockParam{
      					Type: anthropic.BetaManagedAgentsTextBlockTypeText,
      					Text: "Write the output of \"uname -a\" to hello.txt in your working directory.",
      				},
      			}},
      		},
      	}},
      })
      if err != nil {
      	panic(err)
      }
      ```

      ```java Java
      var session = client.beta().sessions().create(SessionCreateParams.builder()
          .agent(agentId)
          .environmentId(environmentId)
          .build());

      client.beta().sessions().events().send(
          session.id(),
          EventSendParams.builder()
              .addEvent(BetaManagedAgentsUserMessageEventParams.builder()
                  .type(BetaManagedAgentsUserMessageEventParams.Type.USER_MESSAGE)
                  .addTextContent("Write the output of \"uname -a\" to hello.txt in your working directory.")
                  .build())
              .build());
      ```

      ```php PHP
      $session = $client->beta->sessions->create(
          agent: $agentId,
          environmentID: $environmentId,
      );

      $client->beta->sessions->events->send(
          $session->id,
          events: [
              [
                  'type' => 'user.message',
                  'content' => [['type' => 'text', 'text' => 'Write the output of "uname -a" to hello.txt in your working directory.']],
              ],
          ],
      );
      ```

      ```ruby Ruby
      session = client.beta.sessions.create(
        agent: agent_id,
        environment_id: environment_id
      )

      client.beta.sessions.events.send_(
        session.id,
        events: [
          {
            type: :"user.message",
            content: [{type: :text, text: 'Write the output of "uname -a" to hello.txt in your working directory.'}]
          }
        ]
      )
      ```
    </CodeGroup>

    세션은 워커가 가져갈 때까지 환경의 큐에서 대기합니다. 연결된 워커가 없으면 세션은 실패하지 않고 큐에 남아 있습니다.
  </Step>

  <Step title="도구가 호스트에서 실행되었는지 확인하기">
    워커 호스트에서 에이전트가 작성한 파일을 읽습니다:

    ```bash
    cat /workspace/hello.txt
    ```

    이 파일은 사용자 자신의 호스트 커널을 설명하므로, 에이전트의 도구 호출이 해당 호스트에서 실행되었음을 알 수 있습니다. 에이전트의 작업을 실시간으로 확인하려면 [세션 이벤트 스트림](https://platform.claude.com/docs/ko/managed-agents/events-and-streaming)을 참조하세요.
  </Step>
</Steps>

## 세션 리소스

자체 호스팅 샌드박스는 `memory_store` 리소스만 지원합니다. 자체 호스팅 환경의 세션에 `file` 또는 `github_repository` 리소스가 포함되면 400 오류와 함께 거부됩니다:

```text wrap
Environment env_... is a self-hosted environment. `resources` are not supported with self-hosted environments.
```

자체 호스팅 환경을 대상으로 하는 [배포](https://platform.claude.com/docs/ko/managed-agents/scheduled-deployments)에도 동일한 규칙이 적용됩니다. 세션에 자체 입력 파일을 제공하려면 [세션용 파일 준비하기](https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes-workers#stage-files-for-a-session)를 참조하세요.

## 자체 호스팅 샌드박스와 MCP 터널

자체 호스팅은 *에이전트의 코드가 실행되는 위치*를 제어합니다. [MCP 터널](https://platform.claude.com/docs/ko/agents-and-tools/mcp-tunnels/overview)은 *Anthropic이 사용자 네트워크의 MCP 서버에 접근하는 방식*을 제어합니다. 두 기능은 서로 독립적입니다:

* Anthropic의 클라우드 샌드박스에 있는 세션은 터널을 통해 비공개 MCP 서버에 접근할 수 있습니다. 예를 들어, 비공개 MCP 서버는 방화벽 뒤의 데이터베이스나 내부 API 앞에 위치할 수 있습니다.
* 자체 호스팅 세션은 터널링된 MCP 서버와 공개 MCP 서버 중 어느 것이든 사용할 수 있습니다.

실행과 도구 접근을 모두 경계 내에 유지하려면 두 기능을 함께 사용하세요. 터널을 사용하지 않으려면 워커가 제공하는 [커스텀 도구로 MCP 서버를 래핑](https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes-custom-tools#wrap-an-mcp-server-as-custom-tools)하세요.

## 플랫폼 가이드

이 페이지들은 모든 샌드박싱 플랫폼에서 워커를 구축하는 방법을 설명합니다. 플랫폼별 가이드도 제공됩니다:

* [AWS Lambda MicroVMs](https://docs.aws.amazon.com/lambda/latest/dg/microvms-integrations-claude-managed-agents.html)
* [Blaxel](https://docs.blaxel.ai/Tutorials/Claude-Managed-Agents)
* [Cloudflare](https://developers.cloudflare.com/sandbox/claude-managed-agents/)
* [Daytona](https://www.daytona.io/docs/en/guides/claude/claude-managed-agents)
* [E2B](https://e2b.dev/docs/agents/claude-managed-agents)
* [Fly.io](https://docs.sprites.dev/integrations/claude-managed-agents/)
* [GKE Agent Sandbox](https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/main/ai-ml/anthropic-agent-sandbox)
* [Modal](https://github.com/modal-labs/claude-managed-agents-modal-sandbox)
* [Namespace](https://namespace.so/docs/integrations/claude)
* [Superserve](https://docs.superserve.ai/integrations/managed-agents/claude-managed-agents)
* [Vercel](https://vercel.com/kb/guide/run-claude-managed-agent-tools-with-vercel-sandbox)

## 다음 단계

<CardGroup cols={2}>
  <Card title="워커 배포하기" icon="play" href="https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes-workers">
    SDK 워커를 실행하거나, 웹훅에서 워커를 트리거하거나, 각 세션에 자체 샌드박스를 제공합니다.
  </Card>

  <Card title="메모리 스토어" icon="brain" href="https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes-memory">
    호스트를 준비하고, 동기화를 구성하고, 읽기 전용 스토어와 충돌을 처리합니다.
  </Card>

  <Card title="커스텀 도구 및 MCP 서버" icon="tool" href="https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes-custom-tools">
    네트워크 내부 MCP 서버의 도구를 포함하여 워커에서 자체 도구를 제공합니다.
  </Card>

  <Card title="모니터링 및 문제 해결" icon="lightning" href="https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes-operations">
    큐 깊이를 읽고, 세션과 워커를 깔끔하게 중지하고, 일반적인 오류를 해결합니다.
  </Card>

  <Card title="워커 레퍼런스" icon="book" href="https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes-reference">
    CLI 플래그, 환경 변수, 파일 시스템 경로 및 SDK 헬퍼 옵션.
  </Card>

  <Card title="보안 모델" icon="lock" href="https://platform.claude.com/docs/ko/managed-agents/self-hosted-sandboxes-security">
    자체 호스팅 샌드박스 환경을 위한 공동 책임 모델.
  </Card>
</CardGroup>
