Skip to main content
Podflare implements the same code_execution_20250825 tool spec that Anthropic’s hosted environment uses. You pass the tool definition to client.messages.create as usual, and when Claude responds with a tool_use block, you route it through handle_code_execution_tool_use instead of Anthropic’s servers. Your data never leaves your compute, and Python REPL state persists across every turn of the conversation.
Anthropic’s Messages API supports a hosted code_execution tool. Podflare can replace the hosted execution with a self-hosted Firecracker microVM — same tool spec, your compute, your data plane.

Install

pip install podflare anthropic

Quickstart

1

Create a sandbox

Open a Sandbox context manager. All tool calls within the with block share one persistent REPL.
from podflare import Sandbox

with Sandbox() as sbx:
    ...
2

Add the tool to your messages call

Declare the code_execution_20250825 tool in the tools list. Claude uses this spec to decide when to run code.
from anthropic import Anthropic

client = Anthropic()

resp = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
    messages=[{"role": "user", "content": "What's sqrt(12345)?"}],
)
3

Handle tool_use blocks with Podflare

Import handle_code_execution_tool_use and call it for every code_execution block in the response. It executes the code in your sandbox and returns the correctly shaped tool_result dict.
from podflare.integrations.anthropic import handle_code_execution_tool_use

tool_results = [
    handle_code_execution_tool_use(block, sbx)
    for block in resp.content
    if getattr(block, "type", None) == "tool_use"
    and getattr(block, "name", None) == "code_execution"
]

Full example

from anthropic import Anthropic
from podflare import Sandbox
from podflare.integrations.anthropic import handle_code_execution_tool_use

client = Anthropic()

with Sandbox() as sbx:
    messages = [{"role": "user", "content": "What's sqrt(12345)?"}]
    while True:
        resp = client.messages.create(
            model="claude-opus-4-7",
            max_tokens=1024,
            tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
            messages=messages,
        )
        messages.append({"role": "assistant", "content": resp.content})
        if resp.stop_reason != "tool_use":
            break

        tool_results = [
            handle_code_execution_tool_use(block, sbx)
            for block in resp.content
            if getattr(block, "type", None) == "tool_use"
            and getattr(block, "name", None) == "code_execution"
        ]
        messages.append({"role": "user", "content": tool_results})

    final = resp.content[-1].text
    print(final)

What handle_code_execution_tool_use does

The function accepts an Anthropic tool_use block — either the SDK object or a plain dict — in the shape:
{"type": "tool_use", "id": "toolu_xxx", "name": "code_execution", "input": {"code": "..."}}
It calls sandbox.run_code(code) and returns the matching tool_result dict:
{
  "type": "tool_result",
  "tool_use_id": "toolu_xxx",
  "content": [{"type": "text", "text": "stdout:\n...\nstderr:\n...\nexit_code: 0"}],
  "is_error": false
}
is_error is set to true whenever exit_code != 0, so Claude can detect and react to execution failures automatically.

Persistent REPL state across turns

Passing the same Sandbox instance to every handle_code_execution_tool_use call gives Claude a single, continuous Python REPL for the entire conversation. Variables, imports, and loaded files from earlier turns are available in later ones — the single biggest advantage over Anthropic’s hosted container, where state lifetime depends on tool version and model.

Fork-aware conversations

Use sandbox.fork(n=...) between turns to let Claude explore multiple execution paths in parallel, then pick a winner and commit it with merge_into.
children = sbx.fork(n=3)
try:
    # Run parent_messages down three branches, each with its own sandbox
    ...
finally:
    for c in children:
        c.close()
See the Python SDK reference for full documentation on fork, diff, and merge_into.