AI Code Execution
This guide shows how to use Firecase as a secure code execution backend for AI agents. The pattern: your agent generates code, Firecase runs it in an isolated sandbox, and returns the output.
Why Firecase for AI Agents?
AI agents that generate and execute code need:
- Isolation — Untrusted code must not access your infrastructure
- Speed — Sub-second sandbox creation for interactive workflows
- Persistence — Maintain state across multiple execution rounds
- Forking — Branch from a known state for parallel exploration
Firecase provides all of these. Each sandbox is a Firecracker microVM with hardware-level isolation, ~150ms boot time, persistent disk state, and instant copy-on-write forking.
Basic Pattern: Execute and Return
The simplest integration: create a sandbox, execute the agent's code, return the result.
import requests
API_KEY = "fc_live_..."
BASE = "https://api.firecase.ai"
headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
# Create a persistent sandbox for this conversation
instance = requests.post(f"{BASE}/instances", headers=headers,
json={"name": f"agent-session-{session_id}"}).json()
# Start the VM
requests.post(f"{BASE}/instances/{instance['id']}/vm", headers=headers)
# Agent generates code → execute it
def run_code(instance_id: str, code: str, language: str = "python3") -> dict:
if language == "python3":
command = ["python3", "-c", code]
elif language == "bash":
command = ["bash", "-c", code]
elif language == "node":
command = ["node", "-e", code]
else:
raise ValueError(f"Unsupported language: {language}")
result = requests.post(
f"{BASE}/instances/{instance_id}/exec",
headers=headers,
json={"command": command, "timeout_ms": 30000}
).json()
return {
"exit_code": result["exit_code"],
"stdout": result["stdout"],
"stderr": result["stderr"],
}
# Use it
output = run_code(instance["id"], "print(2 + 2)")
# {"exit_code": 0, "stdout": "4\n", "stderr": ""}Stateful Sessions
Since instances persist disk state, the agent can install packages, write files, and build up an environment across multiple rounds:
# Round 1: Install dependencies
run_code(instance_id, "pip install pandas matplotlib", language="bash")
# Round 2: Write a data analysis script
requests.post(f"{BASE}/instances/{instance_id}/files", headers=headers,
json={
"path": "/home/user/analyze.py",
"content": """
import pandas as pd
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
df = pd.DataFrame({'x': range(10), 'y': [i**2 for i in range(10)]})
df.to_csv('/home/user/results.csv', index=False)
plt.plot(df['x'], df['y'])
plt.savefig('/home/user/plot.png')
print(f"Saved {len(df)} rows to results.csv")
"""
})
# Round 3: Execute the script
result = run_code(instance_id, "python3 /home/user/analyze.py", language="bash")
# Round 4: Read the results
csv = requests.get(
f"{BASE}/instances/{instance_id}/files",
headers=headers,
params={"path": "/home/user/results.csv"}
).json()Checkpoint and Branch
Use checkpoints to create "save points" that the agent can branch from:
# After setting up the environment, checkpoint
checkpoint = requests.post(
f"{BASE}/instances/{instance_id}/checkpoints",
headers=headers,
json={"label": "env-ready"}
).json()
# Try approach A
result_a = run_code(instance_id, approach_a_code)
if result_a["exit_code"] != 0:
# Approach A failed — rollback and try approach B
requests.delete(f"{BASE}/instances/{instance_id}/vm", headers=headers)
requests.post(f"{BASE}/instances/{instance_id}/rollback", headers=headers,
json={"checkpoint_id": checkpoint["id"]})
requests.post(f"{BASE}/instances/{instance_id}/vm", headers=headers)
result_b = run_code(instance_id, approach_b_code)Parallel Exploration with Forks
Fork the sandbox to explore multiple approaches simultaneously:
import asyncio
# Checkpoint the current state
checkpoint = requests.post(
f"{BASE}/instances/{instance_id}/checkpoints",
headers=headers,
json={"label": "pre-exploration"}
).json()
# Fork 5 instances for parallel exploration
async def explore(approach_code: str, fork_name: str):
fork = requests.post(
f"{BASE}/instances/{instance_id}/fork",
headers=headers,
json={"name": fork_name, "checkpoint_id": checkpoint["id"]}
).json()
requests.post(f"{BASE}/instances/{fork['id']}/vm", headers=headers)
result = run_code(fork["id"], approach_code)
# Clean up
requests.delete(f"{BASE}/instances/{fork['id']}/vm", headers=headers)
requests.delete(f"{BASE}/instances/{fork['id']}", headers=headers)
return result
results = await asyncio.gather(*[
explore(code, f"explore-{i}")
for i, code in enumerate(candidate_solutions)
])
# Pick the best result
best = min(results, key=lambda r: r["exit_code"])Safety Patterns
Timeout Protection
Always set timeouts to prevent runaway processes:
result = requests.post(
f"{BASE}/instances/{instance_id}/exec",
headers=headers,
json={
"command": ["python3", "-c", agent_code],
"timeout_ms": 30000 # 30 second limit
}
).json()Resource Limits via Profiles
Create a restrictive profile for agent sandboxes:
profile = requests.post(f"{BASE}/profiles", headers=headers, json={
"name": "ai-agent-sandbox",
"default_vcpus": 2,
"default_memory_mib": 1024,
"max_vcpus": 2,
"max_memory_mib": 2048,
"max_storage_bytes": 2147483648, # 2 GiB
"idle_timeout_seconds": 600, # Auto-stop after 10 min idle
"network_egress_policy": "deny", # No internet access
"max_checkpoints": 5,
"auto_delete_on_stop": True # Clean up automatically
}).json()Network Isolation
For untrusted code, use "network_egress_policy": "deny" to completely block internet access from the sandbox.
Cleanup
Always clean up sandboxes when done:
# Stop the VM
requests.delete(f"{BASE}/instances/{instance_id}/vm", headers=headers)
# Delete the instance (optional — keeps disk state if you want to resume later)
requests.delete(f"{BASE}/instances/{instance_id}", headers=headers)Next Steps
- See the Exec API for all execution options
- Learn about Checkpoints for branching patterns
- Explore Port Forwarding if your agent runs web services