
Stateful Sandboxes in Claude's API: Persistent REPL and In-Code Tool Calls
Chris Harper
2 min read
Jun 26, 2026 · 19:15 UTC
TL;DR: Upgrade one string — "type": "code_execution_20260120" — and Claude gets a Python REPL where variables persist across conversation turns, and Claude can call your other API tools directly from inside sandbox code.
Most developers using Claude's API know the code execution tool for isolated Python/bash cells. The 20260120 version adds two capabilities that change how you structure multi-step agents: REPL state persistence and programmatic tool calling from within sandbox code.
What changes with code_execution_20260120
The original code_execution_20250825 runs isolated Python cells — each execution starts from scratch. With code_execution_20260120:
- Variables persist across turns.
df = pd.read_csv("data.csv")in turn 1 is still in scope when Claude doesdf.describe()in turn 5. No re-running expensive setup; Claude accumulates state across a whole conversation. - Programmatic tool calling. Code running in the sandbox can invoke your other tools directly via Claude's tool mechanism. Add
"allowed_callers": ["code_execution_20260120"]to any tool and Claude can call it from inside Python or bash.
Minimal example
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=4096,
tools=[{"type": "code_execution_20260120", "name": "code_execution"}],
messages=[
{"role": "user", "content": "Load [1, 4, 9, 16, 25] and compute their square roots."}
]
)
Follow up in the same conversation — the numbers variable stays in scope:
# Next turn — state persists
{"role": "user", "content": "Now compute the mean of those square roots."}
Programmatic tool calling from sandbox code
To let Claude call your tools from within sandbox code, add allowed_callers:
tools=[
{"type": "code_execution_20260120", "name": "code_execution"},
{
"name": "fetch_sales_data",
"description": "Retrieve daily sales by product SKU",
"input_schema": {
"type": "object",
"properties": {"sku": {"type": "string"}},
"required": ["sku"]
},
"allowed_callers": ["code_execution_20260120"]
}
]
Claude can now write Python that calls fetch_sales_data(sku="ABC123"), chains the result with pandas transforms, and passes cleaned data to the next step — all in one agentic flow, no wrapper loop in your application code.
Model and version notes
code_execution_20260120 requires Sonnet 4.5+ or Opus 4.5+, Fable 5, or Mythos 5. Haiku 4.5 supports only the 20250825 version.
Use code_execution_20260521 if you also want Claude to see the 90-second per-cell time limit in the tool description — so it can budget long-running cells before hitting the timeout. Both 20260120 and 20260521 support the same REPL persistence and programmatic tool calling; the only difference is the time limit disclosure.
Sources: Claude code execution tool docs | Anthropic programmatic tool calling