Skip to main content

Sandboxed code execution for AI agents

Project description

Baponi Python SDK

Sandboxed code execution for AI agents. Run Bash, Python, and Node.js in secure, isolated containers with sub-20ms overhead.

Installation

pip install baponi

With framework integrations:

pip install baponi[langchain]     # LangChain
pip install baponi[openai]        # OpenAI Agents SDK
pip install baponi[anthropic]     # Anthropic
pip install baponi[google]        # Google Gemini
pip install baponi[crewai]        # CrewAI
pip install baponi[all]           # All frameworks

Quick Start

from baponi import Baponi

client = Baponi()  # reads BAPONI_API_KEY from env
result = client.execute("print('Hello!')")
print(result.stdout)  # Hello!

Async

from baponi import AsyncBaponi

async with AsyncBaponi() as client:
    result = await client.execute("print('Hello!')")
    print(result.stdout)

Supported Languages

client.execute("echo 'Bash'", language="bash")
client.execute("print('Python')")
client.execute("console.log('Node')", language="node")

Persistent State

Pass a thread_id to persist files and installed packages across calls:

client.execute("pip install pandas", language="bash", thread_id="analysis-session")
client.execute("""
import pandas as pd
df = pd.DataFrame({'x': [1, 2, 3]})
df.to_csv('/home/baponi/data.csv', index=False)
print(df.describe())
""", thread_id="analysis-session")

Framework Integrations

LangChain

from baponi.langchain import code_sandbox
from langchain.agents import create_react_agent

agent = create_react_agent(llm, tools=[code_sandbox])

OpenAI Agents SDK

from baponi.openai import code_sandbox
from agents import Agent

agent = Agent(name="coder", tools=[code_sandbox])

Anthropic

from baponi.anthropic import code_sandbox_tool, handle_tool_call
import anthropic

client = anthropic.Anthropic()
response = client.messages.create(
    model="claude-sonnet-4-20250514",
    tools=[code_sandbox_tool],
    messages=[{"role": "user", "content": "Calculate fibonacci(10) in Python"}],
)

for block in response.content:
    if block.type == "tool_use":
        result = handle_tool_call(block.name, block.input)
        print(result)

Google Gemini

from baponi.google import code_sandbox
from google import genai

client = genai.Client()
chat = client.chats.create(
    model="gemini-2.5-flash",
    config={"tools": [code_sandbox]},
)
response = chat.send_message("Calculate pi to 100 digits")

CrewAI

from baponi.crewai import code_sandbox
from crewai import Agent

agent = Agent(role="Data Analyst", tools=[code_sandbox])

Custom Configuration

All integrations support create_code_sandbox() for power users:

from baponi.langchain import create_code_sandbox

sandbox = create_code_sandbox(
    api_key="sk-...",
    base_url="https://your-baponi-instance.com",
    thread_id="shared-session",        # Default thread for all calls
    timeout=120,                        # Default timeout
    metadata={"user_id": "usr_123"},   # Metadata on every call
)

Error Handling

API errors and execution errors are separate concepts:

from baponi import Baponi, AuthenticationError, RateLimitError

client = Baponi()

# API errors raise exceptions
try:
    result = client.execute("print(1)")
except AuthenticationError:
    print("Invalid API key")
except RateLimitError as e:
    print(f"Rate limited, retry after {e.retry_after}s")

# Execution errors return SandboxResult with success=False
result = client.execute("raise ValueError('oops')")
if not result.success:
    print(f"Code failed with exit code {result.exit_code}")
    print(f"stderr: {result.stderr}")

Exception Hierarchy

Exception HTTP Status Description
BaponiError Base exception for all API errors
AuthenticationError 401 Invalid or missing API key
ForbiddenError 403 Insufficient permissions
RateLimitError 429 Rate limit exceeded
ThreadBusyError 409 Thread already executing
APITimeoutError 504 Server-side timeout
ServerError 500/503 Server error
APIValidationError 400 Invalid request

Configuration

from baponi import Baponi

# Self-hosted deployment
client = Baponi(
    api_key="sk-...",
    base_url="https://baponi.internal.company.com",
)

# Custom HTTP client (proxies, observability, custom TLS)
import httpx

http_client = httpx.Client(
    proxies="http://proxy.internal:8080",
    verify="/path/to/ca-bundle.crt",
)
client = Baponi(api_key="sk-...", http_client=http_client)

# Retry configuration
client = Baponi(
    api_key="sk-...",
    max_retries=0,    # Disable retries
    timeout=120.0,    # Connection timeout (not execution timeout)
)

SandboxResult

result = client.execute("print('hi')")

result.success              # bool — True if exit_code == 0
result.stdout               # str — standard output
result.stderr               # str — standard error
result.exit_code            # int — process exit code
result.network_egress_bytes # int — bytes sent to network
result.storage_egress_bytes # int — bytes written to storage
result.error                # str | None — error message if failed
result.model_dump()         # dict — Pydantic serialization

Environment Variables

Set environment variables in the sandbox:

result = client.execute(
    "import os; print(os.environ['DATABASE_URL'])",
    env_vars={"DATABASE_URL": "postgres://localhost/mydb", "DEBUG": "true"},
)

Keys must be uppercase (MY_VAR), max 50 variables. System-reserved names (PATH, HOME, etc.) are blocked.

Streaming Execution

Get real-time stdout/stderr as the code runs:

with client.execute_stream("for i in range(5): print(i)") as stream:
    for event in stream:
        if isinstance(event, baponi.OutputEvent):
            print(event.data, end="")
    result = stream.get_final_result()

Or just consume silently:

with client.execute_stream("print('hello')") as stream:
    result = stream.until_done()

Async:

async with await client.execute_stream("print('hi')") as stream:
    async for event in stream:
        print(event)

Event types: StatusEvent, OutputEvent, KeepaliveEvent, ResultEvent.

Webhook (Async) Execution

Fire-and-forget execution. The server accepts immediately and optionally POSTs the result to a webhook URL:

handle = client.execute_webhook(
    "import time; time.sleep(10); print('done')",
    webhook_url="https://example.com/webhook",  # optional
)
print(handle.trace_id)  # immediately available

# Poll for status
status = handle.poll()

# Or wait until completion
status = handle.wait(poll_interval=2.0, timeout=60.0)
print(status.status)  # "success"

Status Checking & Cancellation

Check execution status or cancel a running execution by trace_id:

status = client.get_execution("trc_abc12345")
print(status.status)

cancel = client.cancel_execution("trc_abc12345")
print(cancel.status)  # "cancelling" — poll to confirm "cancelled"

Coming Soon

  • Web Tools API — web search and fetch from within sandboxes (/v1/web/search, /v1/web/fetch)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

baponi-0.2.0.tar.gz (9.4 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

baponi-0.2.0-py3-none-any.whl (39.7 kB view details)

Uploaded Python 3

File details

Details for the file baponi-0.2.0.tar.gz.

File metadata

  • Download URL: baponi-0.2.0.tar.gz
  • Upload date:
  • Size: 9.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for baponi-0.2.0.tar.gz
Algorithm Hash digest
SHA256 bedcee870704cafaf6b39a4e2f1ac9bd6b65ee1f74fd2d1da6a01fc7f5da1ddc
MD5 3053c5560d03ca603210e1a11c8b495b
BLAKE2b-256 ea2fe0a99aeed8760b08a09d791f413e5f12458556371f840cd1f4a9d1368ad1

See more details on using hashes here.

File details

Details for the file baponi-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: baponi-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 39.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for baponi-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a65426178dca248ebcf5f5c609d20bffa2fc9f429ebc68b480f18fee83cb4cda
MD5 34216f76d184fe3cbb11b1b2fa8738e7
BLAKE2b-256 dc2a51795da7f8bf9839b8834eb5f7694d501d621e1433644687d5a833f32393

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page