How to Build a Reliable AI Agent with Perplexity’s Sandbox Tool
Why this matters for builders
Perplexity’s Sandbox API, now exposed as a tool inside the Agent API, lets you delegate deterministic code execution from your AI orchestration runtime to a secure, isolated environment that matches Perplexity’s own internal execution engine.
This changes the game for anyone shipping production-grade AI agents. Instead of hoping an LLM’s Python interpreter doesn’t hallucinate a rm -rf / or leak secrets, you can hand off computation to a sandbox that is purpose-built for safety and reproducibility. The orchestration layer stays in control while the heavy, risky, or precise work runs in a deterministic sandbox. Builders finally get a clean separation between “creative reasoning” and “trustworthy execution.”
When to use it
- Your agent needs to run arbitrary user-provided code or complex calculations without risking the host environment.
- You require reproducible results (same code + same inputs = same output every time).
- You want to keep sensitive data or API keys out of the LLM’s context window.
- You are building long-running research agents, data-analysis copilots, or code-generation tools that must execute the code they write.
- You need auditability and isolation for enterprise or regulated use cases.
The full process
1. Define the goal (30 minutes)
Start by writing a one-paragraph spec. Good example:
“Build a research agent that can answer quantitative questions about public datasets. The agent reasons in natural language, decides when it needs computation, calls the Sandbox tool with clean Python code, receives deterministic results, then incorporates them into a final answer. The sandbox must never have access to my Perplexity API key or any production credentials.”
Capture success criteria:
- Zero prompt injection that can escape the sandbox
- Deterministic output for the same code + inputs
- Graceful error handling when code fails
- Clear separation between reasoning trace and execution log
2. Shape the spec into prompts
Create two reusable prompt templates.
System prompt for the agent
You are a careful research agent. You have access to a Sandbox tool that executes Python code in an isolated environment.
Rules:
- Never put secrets, API keys, or file paths in the code you send to the sandbox.
- Only use the sandbox for computation, data transformation, and analysis.
- Always validate inputs before sending code.
- If the sandbox returns an error, explain it to the user and suggest a fix.
- Show both the reasoning and the exact code that was executed.
Tool-use prompt (when calling Sandbox)
Use Perplexity’s Agent API tool format. A starter template:
{
"tool": "sandbox_execute",
"parameters": {
"code": "import pandas as pd\n...your safe code here...",
"timeout_seconds": 30,
"python_version": "3.11"
}
}
3. Scaffold the project
mkdir perplexity-sandbox-agent
cd perplexity-sandbox-agent
mkdir src
touch src/agent.py src/sandbox_client.py requirements.txt
requirements.txt
requests
pydantic
python-dotenv
rich
Initialize a simple client wrapper (check the official Perplexity Agent API docs for exact authentication and endpoint).
src/sandbox_client.py
import requests
from typing import Dict, Any
class SandboxClient:
def __init__(self, api_key: str, base_url: str = "https://api.perplexity.ai"):
self.api_key = api_key
self.base_url = base_url
def execute(self, code: str, timeout: int = 30) -> Dict[str, Any]:
response = requests.post(
f"{self.base_url}/agent/tools/sandbox_execute",
headers={
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
},
json={
"code": code,
"timeout_seconds": timeout
},
timeout=timeout + 5
)
response.raise_for_status()
return response.json()
4. Implement the agent loop
src/agent.py
from rich.console import Console
from rich.panel import Panel
from sandbox_client import SandboxClient
import os
import json
console = Console()
sandbox = SandboxClient(api_key=os.getenv("PERPLEXITY_API_KEY"))
def run_agent(query: str, max_steps: int = 5):
messages = [{"role": "user", "content": query}]
step = 0
while step < max_steps:
# Call Agent API with tool access (exact shape in official docs)
response = call_perplexity_agent(messages, available_tools=["sandbox_execute"])
if "tool_calls" in response and response["tool_calls"]:
for tool_call in response["tool_calls"]:
if tool_call["name"] == "sandbox_execute":
code = tool_call["parameters"]["code"]
console.print(Panel(code, title="Executing in Sandbox", border_style="blue"))
try:
result = sandbox.execute(code, timeout=25)
console.print(Panel(json.dumps(result, indent=2), title="Sandbox Result", border_style="green"))
messages.append({
"role": "tool",
"content": json.dumps(result),
"tool_call_id": tool_call["id"]
})
except Exception as e:
messages.append({
"role": "tool",
"content": f"Execution failed: {str(e)}",
"tool_call_id": tool_call["id"]
})
else:
# Final answer
console.print(Panel(response["content"], title="Final Answer", border_style="magenta"))
break
step += 1
5. Validate carefully
Run these tests before shipping:
- Safety test: Try to make the agent read environment variables or access the network inside the sandbox. It should be blocked.
- Determinism test: Execute the same numerical code 10 times. Results must be identical.
- Error test: Send deliberately broken code. Confirm the agent explains the error and recovers.
- Timeout test: Send an infinite loop. Confirm it is terminated cleanly.
- Data volume test: Process a 50k-row synthetic dataset. Verify memory limits are respected.
Add a simple validation script that runs all tests and logs results.
6. Ship it safely
- Store the Perplexity API key in a secret manager, never in code.
- Log every sandbox call (code sent, result received, latency) for auditing.
- Add rate-limit handling and retry logic with exponential backoff.
- Expose your agent behind a simple FastAPI endpoint with input validation.
- Document the exact sandbox limitations (allowed libraries, max runtime, memory caps) for your users.
Deploy the first version to a staging environment and run 20 real research queries. Fix any patterns that cause excessive sandbox calls.
Pitfalls and guardrails
### What if the LLM keeps generating dangerous code?
Force the system prompt to treat the sandbox as the only execution path. Add a pre-flight check that scans generated code for dangerous imports (os, subprocess, shutil) and rejects them before calling the tool.
### What if the sandbox result is too large for the context window?
Instruct the agent to ask the sandbox to summarize or compute aggregates instead of returning raw data. You can also chain multiple sandbox calls: one to process, one to summarize.
### What if latency feels high?
Cache deterministic results based on a hash of the code + input data. Many analytical queries are repetitive.
### What if I need libraries the sandbox doesn’t have?
Check the official docs for the current supported package list. If something is missing, request it or implement the logic in smaller, approved building blocks.
What to do next
- Add a second tool that lets the agent fetch public data (CSV from URL) into the sandbox.
- Build a simple UI (Gradio or Streamlit) that shows reasoning trace + sandbox execution side-by-side.
- Add cost tracking so you know how many sandbox seconds each query consumes.
- Experiment with letting the agent write and test small functions iteratively inside the sandbox before using them in the main flow.
- Ship a public demo and collect feedback on which workloads feel most valuable.
This pattern—reason in the agent, execute deterministically in the sandbox—will become the default architecture for trustworthy AI products in 2025.
Sources
- Original Perplexity announcement: https://x.com/perplexity_ai/status/2031828484096737712
- Sandbox API service description linked in the announcement
(Word count: 942)

