import anthropic
from tensorlake.sandbox import SandboxClient
SYSTEM_PROMPT = """You are a data analysis assistant. You have access to a Python sandbox.
Use the run_code tool whenever you need to compute something, analyze data, or verify your
reasoning with code. Each run_code call is a fresh Python process — include all imports and
redefine any variables you need. Installed packages and files written to disk persist across calls."""
# Define the tool schema Claude will use
RUN_CODE_TOOL = {
"name": "run_code",
"description": (
"Execute Python code in a secure sandbox. "
"Each call is a fresh Python process — include all imports and redefine any variables you need. "
"Installed packages and files written to disk persist across calls. "
"Returns stdout and stderr."
),
"input_schema": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "Python code to execute.",
}
},
"required": ["code"],
},
}
def run_agent(user_message: str) -> str:
anthropic_client = anthropic.Anthropic()
tl_client = SandboxClient()
# Create one sandbox for the entire agent session
sandbox = tl_client.create_and_connect(
cpus=1.0,
memory_mb=512,
timeout_secs=600,
allow_internet_access=False, # lock down network for untrusted code
)
messages = [{"role": "user", "content": user_message}]
try:
while True:
response = anthropic_client.messages.create(
model="claude-opus-4-5",
max_tokens=4096,
system=SYSTEM_PROMPT,
tools=[RUN_CODE_TOOL],
messages=messages,
)
# Append assistant's response to history
messages.append({"role": "assistant", "content": response.content})
# If no tool use, we're done
if response.stop_reason == "end_turn":
# Extract the final text response
for block in response.content:
if hasattr(block, "text"):
return block.text
# Process all tool calls in this response
tool_results = []
for block in response.content:
if block.type != "tool_use":
continue
code = block.input["code"]
print(f"\n[sandbox] executing:\n{code}\n")
result = sandbox.run("python", ["-c", code])
output = result.stdout or ""
if result.stderr:
output += f"\n[stderr]\n{result.stderr}"
if result.exit_code != 0:
output += f"\n[exit code: {result.exit_code}]"
print(f"[sandbox] output:\n{output}")
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": output or "(no output)",
})
# Feed all results back to Claude in one message
messages.append({"role": "user", "content": tool_results})
finally:
sandbox.close() # always clean up
if __name__ == "__main__":
answer = run_agent(
"I have a list of numbers: [4, 8, 15, 16, 23, 42]. "
"What is the mean, median, and standard deviation? "
"Also plot a histogram and tell me if the distribution looks normal."
)
print("\n=== Final answer ===")
print(answer)