코드 실행 도구

코드 실행 도구 (Code execution tool)

Claude는 API 대화 안에서 직접 데이터를 분석하고, 시각화를 만들고, 복잡한 계산을 수행하고, 시스템 명령을 실행하고, 파일을 생성·편집하고, 업로드된 파일을 처리할 수 있어요. 코드 실행 도구는 Claude가 안전한 샌드박스 환경에서 Bash 명령을 실행하고 코드 작성까지 포함한 파일을 조작할 수 있게 해줘요.

출처: 문서

본문

Claude는 API 대화 안에서 직접 데이터를 분석하고, 시각화를 만들고, 복잡한 계산을 수행하고, 시스템 명령을 실행하고, 파일을 생성·편집하고, 업로드된 파일을 처리할 수 있어요. 코드 실행 도구는 Claude가 안전한 샌드박스 환경에서 Bash 명령을 실행하고 파일을 조작(코드 작성 포함)할 수 있게 해줘요.

코드 실행은 웹 검색이나 웹 페치(web_search_20260209, web_fetch_20260209 이상)와 함께 쓸 때 무료예요. 그런 도구 중 하나가 요청에 있으면 그 요청의 코드 실행에는 표준 토큰 비용 외에 추가 요금이 없어요. 이것은 동적 필터링 뒤의 코드 실행과 Claude가 직접 실행하는 코드 모두를 포함해요. 포함되지 않으면 표준 코드 실행 요금이 적용돼요.

코드 실행은 웹 검색웹 페치 도구의 동적 필터링도 구동해요. Claude는 결과가 컨텍스트 창에 도달하기 전에 코드 실행 환경 안에서 결과를 필터링해요. 동적 필터링이 실행되면 API가 요청에 필요한 코드 실행을 자동으로 프로비저닝하므로, 코드 실행 도구를 요청에 추가할 필요가 없어요.

참고 (Note) 이 기능에 대한 피드백은 피드백 양식으로 보내주세요.

도구 버전 (Tool versions)

코드 실행 도구에는 현재 세 가지 버전이 있고, 모든 지원 모델이 세 가지를 모두 받아요. 각 버전은 이전 버전을 기반으로 해요:

  • code_execution_20250825는 Bash 명령과 파일 작업을 지원해요.
  • code_execution_20260120은 REPL 상태 지속과 샌드박스 안에서의 프로그래매틱 도구 호출을 추가해요. Claude Haiku 4.5는 code_execution_20260120code_execution_20260521 도구 타입을 받지만, 프로그래매틱 도구 호출과 그것에 의존하는 REPL 상태 지속은 지원되지 않으므로 새 버전은 그곳에서 code_execution_20250825처럼 동작해요.
  • code_execution_20260521code_execution_20260120과 같은 런타임이에요. 차이는 도구 설명이 Claude에게 프로그래매틱 도구 호출에서 각 Python 셀에 적용되는 90초 벽시계 제한을 알려주어, Claude가 오래 실행되는 셀을 예산할 수 있다는 점이에요. 그 한도를 초과하는 셀은 0이 아닌 return_code와 출력의 detection_timeout 상태 메시지가 있는 일반 코드 실행 결과를 반환해요. 이것은 API가 전체 도구 호출이 최대 실행 시간을 초과할 때 반환하는 execution_time_exceeded 오류 코드와는 별개예요.

세 도구 버전 모두 anthropic-beta 헤더가 필요하지 않아요. 레거시 코드 실행 베타 헤더는 유효한 옵트인으로 남아요.

이 페이지의 예시는 code_execution_20250825를 사용하는데, 이는 그들이 보여주는 Bash와 파일 작업을 다루고 모든 지원 모델에서 같은 방식으로 동작해요. 프로그래매틱 도구 호출이나 REPL 상태 지속이 필요하면 code_execution_20260120 이상을 사용하세요. 현재 웹 검색웹 페치 도구(web_search_20260209, web_fetch_20260209 이상)는 코드 실행 버전으로 code_execution_20260120 이상이 필요해요.

이전 도구 버전이 새 모델과 계속 호환된다는 보장은 없어요. 새 모델을 도입할 때 도구 버전호환성을 확인하고, 여러분의 통합이 지원하는 가장 새로운 도구 버전을 선호하세요.

참고 (Note) 여전히 레거시 code_execution_20250522(Python 전용)를 사용 중이라면 최신 도구 버전으로 업그레이드를 참고해 마이그레이션하세요.

빠른 시작 (Quick start)

다음은 Claude에게 계산을 수행하라고 요청하는 예시예요:

```bash cURL curl --fail-with-body -sS https://api.anthropic.com/v1/messages \ -H "x-api-key: $ANTHR...KEY" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-opus-5-5", "max_tokens": 4096, "messages": [ { "role": "user", "content": "Use the code execution tool to calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" } ], "tools": [ { "type": "code_execution_20250825", "name": "code_execution" } ] }' ```
ant messages create \
  --model claude-opus-5-5 \
  --max-tokens 4096 \
  --message '{
    role: user,
    content: "Use the code execution tool to calculate the mean and standard
      deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
  }' \
  --tool '{type: code_execution_20250825, name: code_execution}'
client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=4096,
    messages=[
        {
            "role": "user",
            "content": "Use the code execution tool to calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]",
        }
    ],
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)

print(response.to_json())
const client = new Anthropic();

const response = await client.messages.create({
  model: "claude-opus-5-5",
  max_tokens: 4096,
  messages: [
    {
      role: "user",
      content:
        "Use the code execution tool to calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
    }
  ],
  tools: [{ type: "code_execution_20250825", name: "code_execution" }]
});

console.log(JSON.stringify(response));
AnthropicClient client = new();

var message = await client.Messages.Create(new()
{
    Model = Model.ClaudeOpus5_5,
    MaxTokens = 4096,
    Messages = [new() { Role = Role.User, Content = "Use the code execution tool to calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" }],
    Tools = [new CodeExecutionTool20250825()]
});

Console.WriteLine(message);
client := anthropic.NewClient()

response, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
	Model:     anthropic.ModelClaudeOpus5_5,
	MaxTokens: 4096,
	Messages: []anthropic.MessageParam{
		anthropic.NewUserMessage(anthropic.NewTextBlock("Use the code execution tool to calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]")),
	},
	Tools: []anthropic.ToolUnionParam{
		{OfCodeExecutionTool20250825: &anthropic.CodeExecutionTool20250825Param{}},
	},
})
if err != nil {
	log.Fatal(err)
}
fmt.Println(response.RawJSON())
AnthropicClient client = AnthropicOkHttpClient.fromEnv();

MessageCreateParams params = MessageCreateParams.builder()
    .model(Model.CLAUDE_OPUS_5_5)
    .maxTokens(4096L)
    .addUserMessage("Use the code execution tool to calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]")
    .addTool(CodeExecutionTool20250825.builder().build())
    .build();

Message response = client.messages().create(params);
IO.println(ObjectMappers.jsonMapper().valueToTree(response));
$client = new Client();

$message = $client->messages->create(
    maxTokens: 4096,
    messages: [
        [
            'role' => 'user',
            'content' => 'Use the code execution tool to calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]',
        ],
    ],
    model: Model::CLAUDE_OPUS_5_5,
    tools: [new CodeExecutionTool20250825()],
);

echo json_encode($message, JSON_PRETTY_PRINT), PHP_EOL;
client = Anthropic::Client.new

message = client.messages.create(
  model: Anthropic::Model::CLAUDE_OPUS_5_5,
  max_tokens: 4096,
  messages: [
    {
      role: "user",
      content: "Use the code execution tool to calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
    }
  ],
  tools: [Anthropic::CodeExecutionTool20250825.new]
)

puts message.to_json

응답은 server_tool_use 블록(Claude가 실행한 명령)과 그 도구 결과 블록을 번갈아 배치하고, 그 뒤에 Claude의 텍스트가 와요. 최상위에도 container 객체가 있으며, 그 id요청 간에 재사용할 수 있어요. 블록 형태는 응답 형식을 참고하세요.

코드 실행이 어떻게 작동하는지 (How code execution works)

API 요청에 코드 실행 도구를 추가하면:

  1. Claude가 코드 실행이 질문에 답하는 데 도움이 되는지 평가해요.
  2. 도구가 자동으로 다음 기능을 Claude에게 제공해요:
    • Bash 명령: 시스템 작업을 위한 셸 명령 실행
    • 파일 작업: 코드 작성까지 포함해 파일을 직접 생성, 보기, 편집
  3. Claude는 단일 요청에서 이러한 기능을 어떤 조합으로든 사용할 수 있어요.
  4. 모든 작업은 안전한 샌드박스 컨테이너에서 실행돼요. 컨테이너는 인터넷 접근이 없어서 Claude는 런타임에 패키지를 다운로드할 수 없어요. 사전 설치된 라이브러리만 사용할 수 있어요.
  5. API가 모든 명령을 서버 측에서 실행하고 같은 요청 안에서 결과를 Claude에게 반환하므로, 여러분은 코드를 실행하거나 직접 tool_result 블록을 다시 보내지 않아요. 한 예외로, Claude가 코드 실행과 함께 여러분의 클라이언트 도구 중 하나를 호출할 때는 API가 결과 없이 코드 실행 호출을 반환해요. 결과는 여러분이 클라이언트 도구의 tool_result 블록을 다시 보낸 후의 이후 응답에서 도착해요.
  6. 이전 응답의 컨테이너 ID를 다시 전달하지 않으면 각 요청은 새 컨테이너에서 실행돼요. (컨테이너 재사용 참고)
  7. Claude는 생성된 차트, 계산, 분석과 함께 결과를 제공해요.

컨테이너에는 Python이 사전 설치되어 있어요. Claude는 파일 작업 하위 도구로 Python을 작성하고 Bash 명령으로 실행해요. code_execution_20260120 이상과 프로그래매틱 도구 호출이 있는 경우 Python 인터프리터 상태(변수 바인딩 등)도 컨테이너를 재사용하는 요청 간에 지속돼요.

Claude가 코드를 실행하는 시점 (When Claude runs code)

Claude는 요청이 계산이나 파일 처리를 통해 이득을 볼 때 코드를 실행해요:

  • 사소하지 않은 수학 (큰 숫자, 많은 단계, 정밀도에 민감한 결과)
  • 데이터 분석, 파일 파싱, 시각화
  • 알고리즘 실행이나 시뮬레이션
  • "실행", "계산", "수행" 같은 명시적 요청

Claude는 다음에는 코드를 실행하지 않고 직접 답해요:

  • 간단한 산수와 잘 알려진 수학 사실
  • 사실적, 대화적, 창의적 요청
  • 간단한 단위 변환이나 번역

경계선 요청에 Claude가 코드를 실행하길 원하면 명시적으로 물어보세요 (예: "이것을 검증하기 위해 코드를 실행해줘").

파일 작업하기 (Work with files)

직접 파일 업로드하고 분석하기 (Upload and analyze your own files)

CSV, Excel, 이미지 같은 자체 데이터 파일을 분석하려면 Files API로 업로드하고 요청에서 참조하세요.

Python 환경은 Files API로 업로드된 다양한 파일 타입을 처리할 수 있어요:

  • CSV
  • Excel (.xlsx, .xls)
  • JSON
  • XML
  • 이미지 (JPEG, PNG, GIF, WebP)
  • 텍스트 파일 (.txt, .md, .py 등)

업로드하고 분석하기:

  1. Files API파일을 업로드해요.
  2. 메시지에서 container_upload 콘텐츠 블록으로 파일을 참조해요.
  3. API 요청에 코드 실행 도구를 포함해요.
```bash cURL # First, upload a file and capture the file ID (using jq) FILE_ID=$(curl --fail-with-body -sS https://api.anthropic.com/v1/files \ -H "x-api-key: $ANTHR...KEY" \ -H "anthropic-version: 2023-06-01" \ -F "[email protected]" | jq -r '.id')

Then use the file_id with code execution

curl --fail-with-body -sS https://api.anthropic.com/v1/messages
-H "x-api-key: $ANTHR...KEY"
-H "anthropic-version: 2023-06-01"
-H "content-type: application/json"
-d '{ "model": "claude-opus-5-5", "max_tokens": 4096, "messages": [{ "role": "user", "content": [ {"type": "text", "text": "Analyze this CSV data"}, {"type": "container_upload", "file_id": "'"$FILE_ID"'"} ] }], "tools": [{ "type": "code_execution_20250825", "name": "code_execution" }] }'


```bash CLI
# First, upload a file and capture the file ID
FILE_ID=$(ant files upload --file ./data.csv --transform id --raw-output)

# Then use the file_id with code execution
ant messages create <<YAML
model: claude-opus-5-5
max_tokens: 4096
messages:
  - role: user
    content:
      - type: text
        text: Analyze this CSV data
      - type: container_upload
        file_id: $FILE_ID
tools:
  - type: code_execution_20250825
    name: code_execution
YAML
client = anthropic.Anthropic()

# Upload a file
file_object = client.files.upload(file=Path("data.csv"))

# Use the file_id with code execution
response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=4096,
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Analyze this CSV data"},
                {"type": "container_upload", "file_id": file_object.id},
            ],
        }
    ],
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)

print(response.to_json())
import { createReadStream } from "node:fs";
// ...
const client = new Anthropic();

// Upload a file
const fileObject = await client.files.upload({
  file: createReadStream("data.csv")
});

// Use the file_id with code execution
const response = await client.messages.create({
  model: "claude-opus-5-5",
  max_tokens: 4096,
  messages: [
    {
      role: "user",
      content: [
        { type: "text", text: "Analyze this CSV data" },
        { type: "container_upload", file_id: fileObject.id }
      ]
    }
  ],
  tools: [
    {
      type: "code_execution_20250825",
      name: "code_execution"
    }
  ]
});

console.log(JSON.stringify(response));
AnthropicClient client = new();

// Upload a file
var fileObject = await client.Files.Upload(new FileUploadParams
{
    File = File.OpenRead("data.csv")
});

// Use the file_id with code execution
var parameters = new MessageCreateParams
{
    Model = Model.ClaudeOpus5_5,
    MaxTokens = 4096,
    Messages = [
        new()
        {
            Role = Role.User,
            Content = new([
                new TextBlockParam { Text = "Analyze this CSV data" },
                new ContainerUploadBlockParam { FileID = fileObject.ID }
            ])
        }
    ],
    Tools = [new CodeExecutionTool20250825()]
};

var response = await client.Messages.Create(parameters);
Console.WriteLine(response);
ctx := context.Background()
client := anthropic.NewClient()

// Upload a file
file, err := os.Open("data.csv")
if err != nil {
	log.Fatal(err)
}
defer file.Close()

fileObject, err := client.Files.Upload(ctx, anthropic.FileUploadParams{
	File: file,
})
if err != nil {
	log.Fatal(err)
}

// Use the file_id with code execution
response, err := client.Messages.New(ctx, anthropic.MessageNewParams{
	Model:     anthropic.ModelClaudeOpus5_5,
	MaxTokens: 4096,
	Messages: []anthropic.MessageParam{
		anthropic.NewUserMessage(
			anthropic.NewTextBlock("Analyze this CSV data"),
			anthropic.NewContainerUploadBlock(fileObject.ID),
		),
	},
	Tools: []anthropic.ToolUnionParam{
		{OfCodeExecutionTool20250825: &anthropic.CodeExecutionTool20250825Param{}},
	},
})
if err != nil {
	log.Fatal(err)
}

fmt.Println(response.RawJSON())
AnthropicClient client = AnthropicOkHttpClient.fromEnv();

// Upload a file
FileMetadata fileObject = client.files().upload(
    FileUploadParams.builder()
        .file(Path.of("data.csv"))
        .build()
);

// Use the file_id with code execution
Message response = client.messages().create(
    MessageCreateParams.builder()
        .model(Model.CLAUDE_OPUS_5_5)
        .maxTokens(4096L)
        .addUserMessageOfBlockParams(List.of(
            ContentBlockParam.ofText(TextBlockParam.builder()
                .text("Analyze this CSV data")
                .build()),
            ContentBlockParam.ofContainerUpload(ContainerUploadBlockParam.builder()
                .fileId(fileObject.id())
                .build())
        ))
        .addTool(CodeExecutionTool20250825.builder().build())
        .build()
);

IO.println(ObjectMappers.jsonMapper().valueToTree(response));
$client = new Client();

// Upload a file
$fileObject = $client->files->upload(
    file: FileParam::fromResource(fopen('data.csv', 'r')),
);

// Use the file_id with code execution
$response = $client->messages->create(
    model: Model::CLAUDE_OPUS_5_5,
    maxTokens: 4096,
    messages: [
        [
            'role' => 'user',
            'content' => [
                TextBlockParam::with(text: 'Analyze this CSV data'),
                ContainerUploadBlockParam::with(fileID: $fileObject->id),
            ],
        ],
    ],
    tools: [new CodeExecutionTool20250825()],
);

echo json_encode($response), PHP_EOL;
client = Anthropic::Client.new

# Upload a file
file_object = client.files.upload(
  file: Pathname("data.csv")
)

# Use the file_id with code execution
response = client.messages.create(
  model: Anthropic::Model::CLAUDE_OPUS_5_5,
  max_tokens: 4096,
  messages: [
    {
      role: "user",
      content: [
        { type: "text", text: "Analyze this CSV data" },
        { type: "container_upload", file_id: file_object.id }
      ]
    }
  ],
  tools: [
    Anthropic::CodeExecutionTool20250825.new
  ]
)

puts response.to_json

생성된 파일 검색하기 (Retrieve generated files)

Claude가 코드 실행 중에 파일을 자체 출력 디렉터리에 저장하면(생성된 파일이 어떻게 캡처되는지 참고) 각 파일의 ID가 코드 실행 도구 결과에 나타나고, Files API로 다운로드할 수 있어요:

```bash cURL # Downloading every generated file means looping over the file IDs in the tool # result, which doesn't translate to a one-off shell command. Use one of the # SDK examples instead. ```
# Extracting every file ID from the tool results and downloading each one
# requires a loop, which doesn't translate well to a one-off CLI command.
# Use one of the SDK examples instead.
client = Anthropic()

# Request code execution that creates files
response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=4096,
    messages=[
        {
            "role": "user",
            "content": "Create a matplotlib visualization and save it as output.png",
        }
    ],
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)


# Extract file IDs from the response
def extract_file_ids(response: Message) -> list[str]:
    file_ids: list[str] = []
    for item in response.content:
        if item.type == "bash_code_execution_tool_result":
            content_item = item.content
            if content_item.type == "bash_code_execution_result":
                for output_block in content_item.content:
                    file_ids.append(output_block.file_id)
    return file_ids


# Download the created files
for file_id in extract_file_ids(response):
    file_metadata = client.files.retrieve_metadata(file_id)
    file_content = client.files.download(file_id)
    file_content.write_to_file(file_metadata.filename)
    print(f"Downloaded: {file_metadata.filename}")
import { writeFile } from "node:fs/promises";

const client = new Anthropic();

// Request code execution that creates files
const response = await client.messages.create({
  model: "claude-opus-5-5",
  max_tokens: 4096,
  messages: [
    {
      role: "user",
      content: "Create a matplotlib visualization and save it as output.png"
    }
  ],
  tools: [
    {
      type: "code_execution_20250825",
      name: "code_execution"
    }
  ]
});

// Extract the file IDs from the response and download each created file
for (const block of response.content) {
  if (block.type === "bash_code_execution_tool_result") {
    const result = block.content;
    if (result.type === "bash_code_execution_result") {
      for (const outputBlock of result.content) {
        const [fileMetadata, fileResponse] = await Promise.all([
          client.files.retrieveMetadata(outputBlock.file_id),
          client.files.download(outputBlock.file_id)
        ]);
        await writeFile(fileMetadata.filename, await fileResponse.bytes());
        console.log(`Downloaded: ${fileMetadata.filename}`);
      }
    }
  }
}
AnthropicClient client = new();

var parameters = new MessageCreateParams
{
    Model = Model.ClaudeOpus5_5,
    MaxTokens = 4096,
    Messages = [new() { Role = Role.User, Content = "Create a matplotlib visualization and save it as output.png" }],
    Tools = [new CodeExecutionTool20250825()]
};

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

// Collect the file IDs from the tool results
List<string> fileIds = [];
foreach (var block in response.Content)
{
    if (!block.TryPickBashCodeExecutionToolResult(out var toolResult))
        continue;
    if (!toolResult.Content.TryPickBashCodeExecutionResultBlock(out var result))
        continue;
    foreach (var output in result.Content)
    {
        fileIds.Add(output.FileID);
    }
}

// Download each created file
foreach (var fileId in fileIds)
{
    var fileMetadata = await client.Files.RetrieveMetadata(fileId);
    using var download = await client.Files.Download(fileId);
    var downloadStream = await download.ReadAsStream();
    await using var target = File.Create(fileMetadata.Filename);
    await downloadStream.CopyToAsync(target);
    Console.WriteLine($"Downloaded: {fileMetadata.Filename}");
}
	client := anthropic.NewClient()
	ctx := context.Background()

	response, err := client.Messages.New(ctx, anthropic.MessageNewParams{
		Model:     anthropic.ModelClaudeOpus5_5,
		MaxTokens: 4096,
		Messages: []anthropic.MessageParam{
			anthropic.NewUserMessage(anthropic.NewTextBlock("Create a matplotlib visualization and save it as output.png")),
		},
		Tools: []anthropic.ToolUnionParam{
			{OfCodeExecutionTool20250825: &anthropic.CodeExecutionTool20250825Param{}},
		},
	})
	if err != nil {
		log.Fatal(err)
	}

	fileIDs := extractFileIDs(response)

	for _, fileID := range fileIDs {
		fileMetadata, err := client.Files.GetMetadata(ctx, fileID, anthropic.FileGetMetadataParams{})
		if err != nil {
			log.Fatal(err)
		}

		fileContent, err := client.Files.Download(ctx, fileID, anthropic.FileDownloadParams{})
		if err != nil {
			log.Fatal(err)
		}

		outFile, err := os.Create(fileMetadata.Filename)
		if err != nil {
			log.Fatal(err)
		}

		_, err = io.Copy(outFile, fileContent.Body)
		if err != nil {
			log.Fatal(err)
		}
		outFile.Close()
		fileContent.Body.Close()

		fmt.Printf("Downloaded: %s\n", fileMetadata.Filename)
	}
// ...

func extractFileIDs(response *anthropic.Message) []string {
	var fileIDs []string
	for _, item := range response.Content {
		switch variant := item.AsAny().(type) {
		case anthropic.BashCodeExecutionToolResultBlock:
			// Collect the file IDs from the tool result
			for _, file := range variant.Content.Content {
				if file.FileID != "" {
					fileIDs = append(fileIDs, file.FileID)
				}
			}
		}
	}
	return fileIDs
}
void main() throws Exception {
    AnthropicClient client = AnthropicOkHttpClient.fromEnv();

    MessageCreateParams params = MessageCreateParams.builder()
        .model(Model.CLAUDE_OPUS_5_5)
        .maxTokens(4096L)
        .addUserMessage("Create a matplotlib visualization and save it as output.png")
        .addTool(CodeExecutionTool20250825.builder().build())
        .build();

    Message response = client.messages().create(params);

    List<String> fileIds = extractFileIds(response);

    for (String fileId : fileIds) {
        FileMetadata fileMetadata = client.files().retrieveMetadata(fileId);
        try (HttpResponse fileContent = client.files().download(fileId)) {
            Files.copy(
                fileContent.body(),
                Path.of(fileMetadata.filename()),
                StandardCopyOption.REPLACE_EXISTING);
        }
        IO.println("Downloaded: " + fileMetadata.filename());
    }
}

List<String> extractFileIds(Message response) {
    List<String> fileIds = new ArrayList<>();
    // Collect the file IDs from the tool results
    for (ContentBlock item : response.content()) {
        item.bashCodeExecutionToolResult().ifPresent(toolResult -> {
            if (toolResult.content().isBashCodeExecutionResultBlock()) {
                BashCodeExecutionResultBlock result =
                    toolResult.content().asBashCodeExecutionResultBlock();
                for (BashCodeExecutionOutputBlock output : result.content()) {
                    fileIds.add(output.fileId());
                }
            }
        });
    }
    return fileIds;
}
$client = new Client();

// Request code execution that creates files
$response = $client->messages->create(
    maxTokens: 4096,
    messages: [
        [
            'role' => 'user',
            'content' => 'Create a matplotlib visualization and save it as output.png',
        ],
    ],
    model: Model::CLAUDE_OPUS_5_5,
    tools: [new CodeExecutionTool20250825()],
);

/**
 * Extract file IDs from the response.
 *
 * @return list<string>
 */
function extractFileIds(Message $response): array
{
    $fileIds = [];
    foreach ($response->content as $block) {
        if ($block->type !== 'bash_code_execution_tool_result') {
            continue;
        }
        $resultBlock = $block->content;
        if ($resultBlock->type !== 'bash_code_execution_result') {
            continue;
        }
        foreach ($resultBlock->content as $outputBlock) {
            $fileIds[] = $outputBlock->fileID;
        }
    }
    return $fileIds;
}

// Download the created files
foreach (extractFileIds($response) as $fileId) {
    $fileMetadata = $client->files->retrieveMetadata($fileId);
    $fileContent = $client->files->download($fileId);

    file_put_contents($fileMetadata->filename, $fileContent);
    echo "Downloaded: {$fileMetadata->filename}\n";
}
client = Anthropic::Client.new

response = client.messages.create(
  model: Anthropic::Model::CLAUDE_OPUS_5_5,
  max_tokens: 4096,
  messages: [
    {
      role: "user",
      content: "Create a matplotlib visualization and save it as output.png"
    }
  ],
  tools: [
    {
      type: "code_execution_20250825",
      name: "code_execution"
    }
  ]
)

def extract_file_ids(response)
  file_ids = []
  response.content.each do |item|
    if item.type == :bash_code_execution_tool_result
      # WORKAROUND for anthropic-sdk-ruby union coercion bug (SDK-636): item.content is a
      # nested content union, so the typed accessors on `item.content` are unreliable.
      # Read the raw response data through the public `BaseModel#[]` API instead.
      content_item = item.content
      if content_item[:type].to_s == "bash_code_execution_result"
        Array(content_item[:content]).each do |output_block|
          file_ids << output_block[:file_id]
        end
      end
    end
  end
  file_ids
end

extract_file_ids(response).each do |file_id|
  file_metadata = client.files.retrieve_metadata(file_id)
  file_content = client.files.download(file_id)

  File.open(file_metadata.filename, "wb") do |f|
    f.write(file_content.read)
  end

  puts "Downloaded: #{file_metadata.filename}"
end

생성된 파일이 어떻게 캡처되는지 (How generated files are captured):bash_code_execution 호출은 새 빈 디렉터리를 받고, 명령에 $OUTPUT_DIR로 제공돼요. 명령이 끝나면 그 디렉터리의 최상위 파일들이 캡처되어 결과의 content 목록에 file_id 항목으로 반환돼요. 다른 곳에 쓴 파일은 컨테이너에 남고 반환되지 않아요.

도구 설명은 Claude에게 파일을 $OUTPUT_DIR에 복사해서 공유하라고 알려줘요. 애플리케이션이 파일을 받는 것에 의존한다면 Claude에게 파일을 $OUTPUT_DIR에 복사하고 같은 명령에서 디렉터리를 나열하라고 프롬프트 하세요. ls 출력이 캡처를 확인해줘요 (Claude는 content 목록을 보지 못해요):

python /tmp/make_report.py && cp /tmp/report.pdf "$OUTPUT_DIR/" && ls "$OUTPUT_DIR"

Claude가 다른 곳에 쓴 파일은 여전히 컨테이너에 있으므로, 컨테이너를 재사용하고 Claude에게 $OUTPUT_DIR로 복사하라고 요청할 수 있어요.

생성된 파일의 콘텐츠 자격 증명 (Content Credentials on generated files)

Claude API에서 코드 실행 샌드박스에서 Claude가 만든 지원되는 이미지, 비디오, 오디오 파일은 Files API로 다운로드할 때 C2PA 콘텐츠 자격 증명을 담고 있어요. 지원 형식에는 PNG, JPEG, GIF, WebP, TIFF, HEIC, AVIF, SVG, MP4, MOV, MP3, WAV, FLAC, M4A가 포함돼요. 자격 증명은 파일 메타데이터에 내장된 암호 서명된 매니페스트예요. Anthropic을 발급자로 식별하고, 타임스탬프를 담고, "Claude provided this file at the request of a user and may have created or modified the file contents."라는 조치 설명을 기록해요.

서명에는 요청이나 응답 처리의 변경이 필요 없고, 매니페스트는 여러분, 조직, 요청에 대해 아무것도 기록하지 않아요. 파일의 보이는 내용은 변하지 않아요. 매니페스트는 몇 킬로바이트를 추가하므로 다운로드한 파일의 크기와 체크섬은 컨테이너 안에 존재하는 파일과 달라요. 텍스트 파일, PDF, 오피스 문서는 서명 지원 형식이 아니므로 서명되지 않아요. 업로드한 파일은 기존에 담고 있는 콘텐츠 자격 증명을 포함해 원래대로 저장돼요.

자격 증명을 검증하려면 오픈 소스 c2patool 명령줄 도구 같은 C2PA 호환 도구로 파일을 검사하세요. 재인코딩, 형식 변환, 스크린샷, 메타데이터를 제거하는 도구는 자격 증명을 제거하므로, 자격 증명이 없다고 해서 파일이 Claude로 만들어지지 않았다는 뜻은 아니에요. 자격 증명이 누락될 수 있는 이유에 대한 자세한 내용은 Claude가 AI 생성 콘텐츠를 표시하는 방법을 참고하세요.

도구 정의 (Tool definition)

코드 실행 도구는 추가 파라미터가 필요 없어요:

{
  "type": "code_execution_20250825",
  "name": "code_execution"
}

두 필드 모두 고정이에요. type이 도구 버전을 선택하고, namecode_execution이어야 해요.

이 도구를 제공하면 Claude는 자동으로 두 하위 도구에 접근해요:

  • bash_code_execution: 셸 명령 실행
  • text_editor_code_execution: 파일 보기, 생성, 편집 (코드 작성 포함)

Claude가 코드를 실행하면 응답에는 컨테이너의 idexpires_at 타임스탬프가 있는 최상위 container 객체도 포함돼요. 그 ID를 최상위 container 요청 파라미터에 다시 전달해 같은 컨테이너를 계속 사용하세요. 컨테이너 재사용을 참고하세요.

응답 형식 (Response format)

코드 실행 도구는 작업에 따라 두 가지 유형의 결과를 반환할 수 있어요:

Bash 명령 응답 (Bash command response)

{
  "type": "server_tool_use",
  "id": "srvtoolu_01B3C4D5E6F7G8H9I0J1K2L3",
  "name": "bash_code_execution",
  "input": {
    "command": "ls -la | head -5"
  }
},
{
  "type": "bash_code_execution_tool_result",
  "tool_use_id": "srvtoolu_01B3C4D5E6F7G8H9I0J1K2L3",
  "content": {
    "type": "bash_code_execution_result",
    "stdout": "total 24\ndrwxr-xr-x 2 user user 4096 Jan 1 12:00 .\ndrwxr-xr-x 3 user user 4096 Jan 1 11:00 ..\n-rw-r--r-- 1 user user  220 Jan 1 12:00 data.csv\n-rw-r--r-- 1 user user  180 Jan 1 12:00 config.json",
    "stderr": "",
    "return_code": 0,
    "content": []
  }
}

파일 작업 응답 (File operation responses)

파일 보기 (View file):

{
  "type": "server_tool_use",
  "id": "srvtoolu_01C4D5E6F7G8H9I0J1K2L3M4",
  "name": "text_editor_code_execution",
  "input": {
    "command": "view",
    "path": "config.json"
  }
},
{
  "type": "text_editor_code_execution_tool_result",
  "tool_use_id": "srvtoolu_01C4D5E6F7G8H9I0J1K2L3M4",
  "content": {
    "type": "text_editor_code_execution_view_result",
    "file_type": "text",
    "content": "{\n  \"setting\": \"value\",\n  \"debug\": true\n}",
    "num_lines": 4,
    "start_line": 1,
    "total_lines": 4
  }
}

파일 생성 (Create file):

{
  "type": "server_tool_use",
  "id": "srvtoolu_01D5E6F7G8H9I0J1K2L3M4N5",
  "name": "text_editor_code_execution",
  "input": {
    "command": "create",
    "path": "new_file.txt",
    "file_text": "Hello, World!"
  }
},
{
  "type": "text_editor_code_execution_tool_result",
  "tool_use_id": "srvtoolu_01D5E6F7G8H9I0J1K2L3M4N5",
  "content": {
    "type": "text_editor_code_execution_create_result",
    "is_file_update": false
  }
}

파일 편집 (str_replace) (Edit file (str_replace)):

{
  "type": "server_tool_use",
  "id": "srvtoolu_01E6F7G8H9I0J1K2L3M4N5O6",
  "name": "text_editor_code_execution",
  "input": {
    "command": "str_replace",
    "path": "config.json",
    "old_str": "\"debug\": true",
    "new_str": "\"debug\": false"
  }
},
{
  "type": "text_editor_code_execution_tool_result",
  "tool_use_id": "srvtoolu_01E6F7G8H9I0J1K2L3M4N5O6",
  "content": {
    "type": "text_editor_code_execution_str_replace_result",
    "old_start": 3,
    "old_lines": 1,
    "new_start": 3,
    "new_lines": 1,
    "lines": ["-  \"debug\": true", "+  \"debug\": false"]
  }
}

결과 (Results)

Bash 명령 결과(bash_code_execution_result)에는 다음이 포함돼요:

  • stdout: 성공적인 실행의 출력
  • stderr: 실행 실패 시 오류 메시지
  • return_code: 성공 0, 실패 0이 아님
  • content: 명령이 $OUTPUT_DIR에 남긴 각 파일에 대한 항목이 있는 목록(생성된 파일이 어떻게 캡처되는지 참고). 각 항목은 파일을 검색하기 위한 file_id를 Files API와 함께 담아요.

파일 작업 결과는 자체 필드가 있어요:

  • 보기 (text_editor_code_execution_view_result): file_type, content, num_lines, start_line, total_lines
  • 생성 (text_editor_code_execution_create_result): is_file_update (파일이 이미 존재했는지 여부)
  • 편집 (text_editor_code_execution_str_replace_result): old_start, old_lines, new_start, new_lines, lines (diff 형식)

오류 (Errors)

각 도구 유형은 특정 오류를 반환할 수 있어요:

공통 오류 (모든 도구):

{
  "type": "bash_code_execution_tool_result",
  "tool_use_id": "srvtoolu_01VfmxgZ46TiHbmXgy928hQR",
  "content": {
    "type": "bash_code_execution_tool_result_error",
    "error_code": "unavailable"
  }
}

도구 유형별 오류 코드:

도구 오류 코드 설명
모든 도구 unavailable 도구가 일시적으로 사용 불가
모든 도구 execution_time_exceeded 도구 호출이 최대 실행 시간 초과
모든 도구 invalid_tool_input 도구에 제공된 잘못된 파라미터
모든 도구 too_many_requests 도구 사용에 대한 요금 한도 초과
bash output_file_too_large 명령 출력이 최대 크기 초과
text_editor file_not_found 파일이 존재하지 않음 (보기/편집 작업)

만료된 컨테이너는 재사용할 수 없어요. 이를 참조하는 요청은 복원 대신 오류를 반환해요. container 파라미터 없이 요청을 다시 보내 새 컨테이너를 받으세요.

pause_turn 중지 이유

응답에는 pause_turn 중지 이유가 포함될 수 있는데, 이는 API가 오래 실행되는 턴을 일시 중지했음을 나타내요. 이후 요청에서 응답을 그대로 제공해 Claude가 턴을 계속하게 하거나, 대화를 중단하고 싶다면 콘텐츠를 수정할 수 있어요.

컨테이너 (Containers)

코드 실행 도구는 Python에 더 중점을 둔, 코드 실행 전용으로 설계된 안전한 컨테이너 환경에서 실행돼요.

런타임 환경 (Runtime environment)

  • Python 버전: 3.11
  • 운영 체제: Linux 기반 컨테이너
  • 아키텍처: x86_64 (AMD64)

리소스 한도 (Resource limits)

  • 메모리: 5 GiB RAM
  • 디스크 공간: 5 GiB 워크스페이스 저장
  • CPU: 1 CPU
  • 실행 시간: 최대 실행 시간을 넘어 실행되는 도구 호출은 execution_time_exceeded 오류를 반환해요. 프로그래매틱 도구 호출로 각 REPL 셀에는 90초 벽시계 한도도 있어요.

네트워킹과 보안 (Networking and security)

  • 인터넷 접근: 보안상 완전히 비활성화
  • 외부 연결: 아웃바운드 네트워크 요청 허용되지 않음
  • 샌드박스 격리: 호스트 시스템과 다른 컨테이너로부터 완전 격리
  • 파일 접근: 워크스페이스 디렉터리로만 제한
  • 워크스페이스 범위: Files API처럼 컨테이너는 요청의 워크스페이스로 범위가 지정돼요.
  • 만료: 컨테이너는 생성 후 30일 후 만료돼요.

사전 설치된 라이브러리 (Pre-installed libraries)

샌드박스 Python 환경에는 다음과 같은 흔히 쓰는 라이브러리가 포함돼요:

  • 데이터 과학: pandas, numpy, scipy, scikit-learn, statsmodels
  • 시각화: matplotlib, seaborn
  • 파일 처리: pyarrow, openpyxl, xlsxwriter, xlrd, pillow, python-pptx, python-docx, pypdf, pdfplumber, pypdfium2, pdf2image, pdfkit, tabula-py, reportlab[pycairo], Img2pdf
  • 수학과 컴퓨팅: sympy, mpmath
  • 유틸리티: tqdm, python-dateutil, pytz, joblib

컨테이너에는 unzip, unrar, 7zip, bc, rg (ripgrep), fd, sqlite 같은 명령줄 도구도 포함돼요.

컨테이너는 인터넷 접근이 없으므로 Claude는 런타임에 추가 패키지를 다운로드하거나 설치할 수 없어요. 사전 설치된 라이브러리만 사용할 수 있어요.

컨테이너 재사용 (Container reuse)

이전 응답의 컨테이너 ID를 제공해 여러 API 요청 간에 기존 컨테이너를 재사용할 수 있어요. 이렇게 하면 요청 간에 생성된 파일을 유지할 수 있어요. code_execution_20260120 이상과 프로그래매틱 도구 호출이 있으면 Python 인터프리터 상태도 지속돼요.

컨테이너는 생성 후 30일 후 만료돼요. 약 5분 비활성 후 체크포인트되고, 30일 창 안에서 ID로 요청을 보내면 복원돼요. 응답의 container 객체에 있는 expires_at 타임스탬프는 더 짧은 롤링 값이며 30일 한도를 보고하지 않아요. 만료된 컨테이너는 재사용할 수 없어요. container 파라미터 없이 요청을 다시 보내 새 컨테이너를 받으세요.

예시 (Example)

```bash cURL # First request: Create a file with a random number, capturing the container ID (using jq) CONTAINER_ID=$(curl -s https://api.anthropic.com/v1/messages \ -H "x-api-key: $ANTHR...KEY" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-opus-5-5", "max_tokens": 4096, "messages": [{ "role": "user", "content": "Write a file with a random number and save it to \"/tmp/number.txt\"" }], "tools": [{ "type": "code_execution_20250825", "name": "code_execution" }] }' | jq -r '.container.id')

Second request: Reuse the container to read the file

curl https://api.anthropic.com/v1/messages
-H "x-api-key: $ANTHR...KEY"
-H "anthropic-version: 2023-06-01"
-H "content-type: application/json"
-d '{ "container": "'"$CONTAINER_ID"'", "model": "claude-opus-5-5", "max_tokens": 4096, "messages": [{ "role": "user", "content": "Read the number from "/tmp/number.txt" and calculate its square" }], "tools": [{ "type": "code_execution_20250825", "name": "code_execution" }] }'


```bash CLI
# First request: Create a file with a random number
CONTAINER_ID=$(ant messages create \
  --model claude-opus-5-5 \
  --max-tokens 4096 \
  --message '{role: user, content: Write a file with a random number and save it to "/tmp/number.txt"}' \
  --tool '{type: code_execution_20250825, name: code_execution}' \
  --transform container.id --raw-output)

# Second request: Reuse the container to read the file
ant messages create \
  --container "$CONTAINER_ID" \
  --model claude-opus-5-5 \
  --max-tokens 4096 \
  --message '{role: user, content: Read the number from "/tmp/number.txt" and calculate its square}' \
  --tool '{type: code_execution_20250825, name: code_execution}'
client = anthropic.Anthropic()

# First request: create a file with a random number in a new container
response1 = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=4096,
    messages=[
        {
            "role": "user",
            "content": "Write a file with a random number and save it to '/tmp/number.txt'",
        }
    ],
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)

# Second request: pass the container ID back so Claude reuses the same container
response2 = client.messages.create(
    container=response1.container.id,
    model="claude-opus-5-5",
    max_tokens=4096,
    messages=[
        {
            "role": "user",
            "content": "Read the number from '/tmp/number.txt' and calculate its square",
        }
    ],
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)

print(response2.to_json())
const client = new Anthropic();

// First request: Claude creates a file inside a fresh code execution container
const response1 = await client.messages.create({
  model: "claude-opus-5-5",
  max_tokens: 4096,
  messages: [
    {
      role: "user",
      content: "Write a file with a random number and save it to '/tmp/number.txt'"
    }
  ],
  tools: [{ type: "code_execution_20250825", name: "code_execution" }]
});

// The response includes the container once the code execution tool has run
if (!response1.container) {
  throw new Error("Expected the first response to include a container");
}

// Second request: pass the container ID back so it reuses the same container
const response2 = await client.messages.create({
  container: response1.container.id,
  model: "claude-opus-5-5",
  max_tokens: 4096,
  messages: [
    { role: "user", content: "Read the number from /tmp/number.txt and calculate its square" }
  ],
  tools: [{ type: "code_execution_20250825", name: "code_execution" }]
});

console.log(JSON.stringify(response2));
AnthropicClient client = new();

// First request: Claude creates a file inside a fresh code execution container
var response1 = await client.Messages.Create(new()
{
    Model = Model.ClaudeOpus5_5,
    MaxTokens = 4096,
    Messages = [new() { Role = Role.User, Content = "Write a file with a random number and save it to '/tmp/number.txt'" }],
    Tools = [new CodeExecutionTool20250825()]
});

// Second request: pass the container ID back so Claude reuses the same container
var response2 = await client.Messages.Create(new()
{
    Container = response1.Container!.ID,
    Model = Model.ClaudeOpus5_5,
    MaxTokens = 4096,
    Messages = [new() { Role = Role.User, Content = "Read the number from '/tmp/number.txt' and calculate its square'" }],
    Tools = [new CodeExecutionTool20250825()]
});

Console.WriteLine(response2);
client := anthropic.NewClient()
ctx := context.Background()

codeExecution := []anthropic.ToolUnionParam{
	{OfCodeExecutionTool20250825: &anthropic.CodeExecutionTool20250825Param{}},
}

// First request: create a file with a random number in a new container
response1, err := client.Messages.New(ctx, anthropic.MessageNewParams{
	Model:     anthropic.ModelClaudeOpus5_5,
	MaxTokens: 4096,
	Messages: []anthropic.MessageParam{
		anthropic.NewUserMessage(anthropic.NewTextBlock("Write a file with a random number and save it to '/tmp/number.txt'")),
	},
	Tools: codeExecution,
})
if err != nil {
	log.Fatal(err)
}

// Reuse the container from the first request so the file is still there.
response2, err := client.Messages.New(ctx, anthropic.MessageNewParams{
	Container: anthropic.MessageCreateParamsContainerUnion{
		OfString: anthropic.String(response1.Container.ID),
	},
	Model:     anthropic.ModelClaudeOpus5_5,
	MaxTokens: 4096,
	Messages: []anthropic.MessageParam{
		anthropic.NewUserMessage(anthropic.NewTextBlock("Read the number from '/tmp/number.txt' and calculate its square")),
	},
	Tools: codeExecution,
})
if err != nil {
	log.Fatal(err)
}

fmt.Println(response2.RawJSON())
AnthropicClient client = AnthropicOkHttpClient.fromEnv();

// First request: create a file with a random number in a new container
MessageCreateParams params1 = MessageCreateParams.builder()
    .model(Model.CLAUDE_OPUS_5_5)
    .maxTokens(4096L)
    .addUserMessage("Write a file with a random number and save it to '/tmp/number.txt'")
    .addTool(CodeExecutionTool20250825.builder().build())
    .build();

Message response1 = client.messages().create(params1);

// Second request: pass the container ID back so it reuses the same container
MessageCreateParams params2 = MessageCreateParams.builder()
    .container(response1.container().orElseThrow().id())
    .model(Model.CLAUDE_OPUS_5_5)
    .maxTokens(4096L)
    .addUserMessage("Read the number from '/tmp/number.txt' and calculate its square")
    .addTool(CodeExecutionTool20250825.builder().build())
    .build();

Message response2 = client.messages().create(params2);
IO.println(ObjectMappers.jsonMapper().valueToTree(response2));
$client = new Client();

// First request: Claude writes the file inside a fresh code execution container
$response1 = $client->messages->create(
    maxTokens: 4096,
    messages: [
        [
            'role' => 'user',
            'content' => "Write a file with a random number and save it to '/tmp/number.txt'",
        ],
    ],
    model: Model::CLAUDE_OPUS_5_5,
    tools: [new CodeExecutionTool20250825()],
);

// Second request: reuse the container so '/tmp/number.txt' is still there
$response2 = $client->messages->create(
    container: $response1->container->id,
    maxTokens: 4096,
    messages: [
        [
            'role' => 'user',
            'content' => "Read the number from '/tmp/number.txt' and calculate its square",
        ],
    ],
    model: Model::CLAUDE_OPUS_5_5,
    tools: [new CodeExecutionTool20250825()],
);

echo json_encode($response2), PHP_EOL;
client = Anthropic::Client.new

# First request: Claude creates the file inside a fresh code execution container
response1 = client.messages.create(
  model: Anthropic::Model::CLAUDE_OPUS_5_5,
  max_tokens: 4096,
  messages: [
    {
      role: "user",
      content: "Write a file with a random number and save it to '/tmp/number.txt'"
    }
  ],
  tools: [Anthropic::CodeExecutionTool20250825.new]
)

# Second request: pass the container ID back so Claude reuses the same container
response2 = client.messages.create(
  container: response1.container.id,
  model: Anthropic::Model::CLAUDE_OPUS_5_5,
  max_tokens: 4096,
  messages: [
    {
      role: "user",
      content: "Read the number from '/tmp/number.txt' and calculate its square"
    }
  ],
  tools: [Anthropic::CodeExecutionTool20250825.new]
)

puts response2.to_json

다른 실행 도구와 함께 코드 실행 사용하기 (Using code execution with other execution tools)

코드 실행을 코드도 실행하는 클라이언트 제공 도구(예: Bash 도구나 커스텀 REPL)와 함께 제공하면 Claude는 멀티컴퓨터 환경에서 작동해요. 코드 실행 도구는 Anthropic의 샌드박스 컨테이너에서 실행되고, 클라이언트 제공 도구는 여러분이 제어하는 별도 환경에서 실행돼요. Claude가 때로 이 환경들을 혼동해서, 잘못된 도구를 사용하거나 상태가 그들 사이에서 공유된다고 가정할 수 있어요.

이를 피하려면 시스템 프롬프트에 그 차이를 명확히 하는 지침을 추가하세요:

When multiple code execution environments are available, be aware that:
- Variables, files, and state do NOT persist between different execution environments
- Use the code_execution tool for general-purpose computation in Anthropic's sandboxed environment
- Use client-provided execution tools (e.g., bash) when you need access to the user's local system, files, or data
- If you need to pass results between environments, explicitly include outputs in subsequent tool calls rather than assuming shared state

이것은 코드 실행을 자동으로 활성화하는 웹 검색이나 웹 페치와 코드 실행을 결합할 때 특히 중요해요. 애플리케이션이 이미 클라이언트 측 셸 도구를 제공한다면 자동 코드 실행이 Claude가 구분해야 할 두 번째 실행 환경을 만들어요.

Claude가 코드 실행과 함께 여러분의 클라이언트 도구 중 하나를 호출하면 API는 결과 없이 코드 실행 호출을 반환해요. 결과는 여러분이 클라이언트 도구의 tool_result 블록을 다시 보낸 후의 이후 응답에서 도착해요.

스트리밍 (Streaming)

스트리밍을 활성화하면("stream": true) 코드 실행 이벤트를 발생하는 대로 받게 돼요. 하위 도구 입력은 input_json_delta 이벤트로 스트리밍되고, 각 결과 블록은 단일 content_block_start 이벤트로 통째로 도착해요:

event: content_block_start
data: {"type": "content_block_start", "index": 1, "content_block": {"type": "server_tool_use", "id": "srvtoolu_xyz789", "name": "bash_code_execution"}}

// Tool input streamed as partial JSON
event: content_block_delta
data: {"type": "content_block_delta", "index": 1, "delta": {"type": "input_json_delta", "partial_json": "{\"command\": \"python analyze.py\"}"}}

// Pause while the command runs

// Execution result delivered as a complete block
event: content_block_start
data: {"type": "content_block_start", "index": 2, "content_block": {"type": "bash_code_execution_tool_result", "tool_use_id": "srvtoolu_xyz789", "content": {"type": "bash_code_execution_result", "stdout": "   A  B  C\n0  1  2  3\n1  4  5  6", "stderr": "", "return_code": 0, "content": []}}}

배치 요청 (Batch requests)

코드 실행 도구를 Messages Batches API에 포함할 수 있어요. Messages Batches API를 통한 코드 실행 도구 호출은 일반 Messages API 요청과 동일하게 가격이 책정돼요.

사용법과 요금 (Usage and pricing)

코드 실행은 웹 검색이나 웹 페치와 함께 쓸 때 무료예요. API 요청에 web_search_20260209(이상) 또는 web_fetch_20260209(이상)가 포함되면 표준 입력·출력 토큰 비용 외에 코드 실행 도구 호출에 대한 추가 요금이 없어요.

이 도구 없이 사용하면 코드 실행은 토큰 사용과 별도로 추적되는 실행 시간으로 청구돼요:

  • 실행 시간은 최소 5분이에요.
  • 각 조직은 월별 1,550 무료 시간을 받아요.
  • 1,550시간을 초과하는 추가 사용량은 컨테이너당 시간당 $0.05 USD로 청구돼요.
  • 요청에 파일이 포함되면 도구가 호출되지 않아도 실행 시간이 청구돼요. 파일이 컨테이너에 미리 로드되기 때문이에요.

코드 실행 사용량은 응답에서 추적돼요:

{
  "usage": {
    "input_tokens": 105,
    "output_tokens": 239,
    "server_tool_use": {
      "code_execution_requests": 1
    }
  }
}

최신 도구 버전으로 업그레이드 (Upgrade to latest tool version)

최신 도구 버전은 code_execution_20260521이에요. 세 가지 현재 버전 사이를 이동하려면 요청의 type 문자열을 업데이트하세요. 세 버전 모두 응답 형식에 문서화된 응답 블록을 반환해요. 각 버전이 추가하는 것을 도구 버전에서, 그들을 지원하는 모델을 호환성에서 확인하세요.

이 섹션의 나머지는 레거시 Python 전용 code_execution_20250522에서 현재 도구 버전으로 마이그레이션하는 방법을 다뤄요.

무엇이 바뀌었나 (What's changed)

구성 요소 레거시 현재
베타 헤더 code-execution-2025-05-22 필요 없음
도구 유형 code_execution_20250522 code_execution_20250825 또는 그 이후
기능 Python 전용 Bash 명령, 파일 작업
응답 유형 code_execution_result bash_code_execution_result, text_editor_code_execution_*_result

하위 호환성 (Backward compatibility)

  • 모든 기존 Python 코드 실행은 이전과 정확히 동일하게 계속 동작해요.
  • 기존 Python 전용 워크플로우에 변경이 필요 없어요.

업그레이드 단계 (Upgrade steps)

업그레이드하려면 API 요청에서 도구 유형을 업데이트하세요:

- "type": "code_execution_20250522"
+ "type": "code_execution_20250825"

응답 처리를 검토하세요 (응답을 프로그래매틱하게 파싱하는 경우):

  • API는 더 이상 Python 실행 응답에 이전 블록을 보내지 않아요.
  • 대신 API는 Bash 및 파일 작업에 대한 새 응답 유형을 보내요. (응답 형식 참고)

데이터 보존 (Data retention)

코드 실행은 서버 측 샌드박스 컨테이너에서 실행돼요. 실행 산출물, 업로드된 파일, 출력을 포함한 컨테이너 데이터는 최대 30일 동안 보존돼요. 이 보존은 컨테이너 환경 안에서 처리되는 모든 데이터에 적용돼요. 코드 실행이 Files API에서 생성한 파일(client.files.download()로 검색 가능)은 명시적으로 삭제될 때까지 지속돼요.

모든 기능의 ZDR 자격에 대해서는 API 및 데이터 보존을 참고하세요.

더 알아보기 (Learn more)