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.1.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.1-py3-none-any.whl (39.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: baponi-0.2.1.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.1.tar.gz
Algorithm Hash digest
SHA256 73df799548b9033591751c47577d99fbab10b8c7d876e474146143a953a8c503
MD5 aeb0a545ade4c2ae027830b58f36a968
BLAKE2b-256 df95688ddc4d4a2ad78ad979621450d2a7bb940311eac22b83baff43826d0150

See more details on using hashes here.

File details

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

File metadata

  • Download URL: baponi-0.2.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c02c0917a37583a07e7938c4efaee30ca2560f187321ccb65d7d39914739658f
MD5 bd90fd2c42d377f526421529a13c7b64
BLAKE2b-256 c14ef5ae6a4d2480c5f6d517d912cbabd746e4daf7f3fdfd1f87963421a7fc17

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