LangChain Deep Agents
Give your LangChain Deep Agent a full sandbox environment with file operations, code execution, and persistent state in 3 lines of code.
Get started
Section titled “Get started”-
Install
Terminal window pip install baponi[deepagents] -
Set your API keys
Terminal window export BAPONI_API_KEY=sk-your-key-hereexport ANTHROPIC_API_KEY=your-anthropic-key-hereGet a Baponi key from console.baponi.ai. 1,000 free credits/month, no credit card.
-
Create and run your agent
from baponi.deepagents import BaponiSandboxfrom deepagents import create_deep_agentwith BaponiSandbox() as sandbox:agent = create_deep_agent("anthropic:claude-sonnet-4-6", backend=sandbox)result = agent.invoke({"messages": [("human", "Use Python to calculate the SHA-256 hash of 'hello world'")]})print(result["messages"][-1].content)
The agent writes a Python script, executes it inside an isolated sandbox, and returns the result. Files, installed packages, and environment changes persist across calls.
What your agent can do
Section titled “What your agent can do”Your agent gets these tools automatically:
| Tool | Example |
|---|---|
| execute | Run pip install pandas, compile code, start servers |
| read_file | Inspect source files, configs, logs |
| write_file | Generate code, create configs, save results |
| edit_file | Refactor code, fix bugs, update settings |
| ls | Explore project structure |
| grep | Find function definitions, error patterns, TODOs |
| glob | Find all *.py files, match naming patterns |
Persistent sessions
Section titled “Persistent sessions”Files and installed packages persist automatically across calls within the same sandbox. Your agent can install dependencies, write code, then test it, all building on previous steps.
To resume a session from a separate process (e.g., a new API request or a cron job), pass the same thread_id:
# Process Awith BaponiSandbox(thread_id="my-project") as sandbox: agent = create_deep_agent("anthropic:claude-sonnet-4-6", backend=sandbox) agent.invoke({"messages": [("human", "Install pandas and write a CSV parser")]})
# Process B - picks up right where A left offwith BaponiSandbox(thread_id="my-project") as sandbox: agent = create_deep_agent("anthropic:claude-sonnet-4-6", backend=sandbox) agent.invoke({"messages": [("human", "Add error handling to the CSV parser you wrote")]})Configuration
Section titled “Configuration”sandbox = BaponiSandbox( thread_id="data-pipeline-run-42", # session ID for persistent state timeout=60, # default 60s, Pro plan supports up to 3600 metadata={"user": "agent-1"}, # attached to every execution for audit env_vars={"ENV": "prod"}, # environment variables injected into every execution sub_paths=["/data/shared"], # storage path scoping for BYOB mounts)For self-hosted Baponi deployments:
sandbox = BaponiSandbox( base_url="https://baponi.internal.company.com", api_key="sk-your-enterprise-key",)Per-call overrides
Section titled “Per-call overrides”Override constructor defaults on individual execute() or aexecute() calls. Pass None (the default) to use the constructor value. Pass an explicit value to replace the constructor default for that call only - values are replaced, not merged.
sandbox = BaponiSandbox( env_vars={"ENV": "prod"}, metadata={"team": "data"}, sub_paths=["/data/shared"],)
# Override env_vars for this call onlyresult = sandbox.execute("echo $ENV", env_vars={"ENV": "staging"})
# Override metadata for this call onlyresult = sandbox.execute("cmd", metadata={"step": "cleanup"})
# Narrow storage scope to a specific subdirectory for this call onlyresult = sandbox.execute("ls /data/shared", sub_paths=["/data/shared/2026-03-22"])
# Override timeout for this call onlyresult = sandbox.execute("long-running-task", timeout=300)All four parameters (timeout, env_vars, metadata, sub_paths) are available as per-call overrides on execute(), aexecute(), and execute_stream().
Context managers
Section titled “Context managers”BaponiSandbox supports with and async with to ensure HTTP connections are properly closed:
# Syncwith BaponiSandbox(api_key="sk-...", thread_id="session-1") as sandbox: result = sandbox.execute("echo hello")# connections closed automatically
# Asyncasync with BaponiSandbox(api_key="sk-...") as sandbox: result = await sandbox.aexecute("echo hello")You can also call sandbox.close() or await sandbox.aclose() manually. Both are idempotent.
Streaming
Section titled “Streaming”execute_stream() provides real-time NDJSON streaming for long-running commands. Events arrive as they happen rather than waiting for the full result.
stream = sandbox.execute_stream("pip install -r requirements.txt && python train.py")with stream: for event in stream: print(event) result = stream.get_final_result()execute_stream() accepts the same per-call overrides as execute():
stream = sandbox.execute_stream( "python train.py", timeout=600, env_vars={"CUDA_VISIBLE_DEVICES": "0"},)Sandbox provider
Section titled “Sandbox provider”BaponiSandboxProvider manages multiple sandbox instances by ID. Use it when your application needs to create, reuse, and clean up sandboxes programmatically - for example, one sandbox per user session in a server.
from baponi.deepagents import BaponiSandboxProvider
provider = BaponiSandboxProvider(api_key="sk-...")
# Create or reuse sandbox by IDsandbox = provider.get_or_create(sandbox_id="user-123")result = sandbox.execute("echo hello")
# Different user gets a different sandboxsandbox_b = provider.get_or_create(sandbox_id="user-456")
# Clean up when doneprovider.delete("user-123")The provider also has async variants: await provider.aget_or_create() and await provider.adelete().
Constructor arguments (timeout, metadata, env_vars, sub_paths) are passed through to every sandbox the provider creates. Configuration falls back to BAPONI_API_KEY and BAPONI_BASE_URL environment variables when not provided explicitly.
Do I need to manage sandbox lifecycles?
Section titled “Do I need to manage sandbox lifecycles?”For most use cases, no. Create a BaponiSandbox and use it - Baponi handles provisioning, isolation, and cleanup. If you need to manage multiple sandboxes programmatically (e.g., one per user in a multi-tenant server), use BaponiSandboxProvider.
What languages can my agent run?
Section titled “What languages can my agent run?”Python, Node.js, and Bash are available in the default sandbox image.
Does it support async and streaming?
Section titled “Does it support async and streaming?”Yes. BaponiSandbox works with both sync (execute) and async (aexecute) out of the box. For real-time output, use execute_stream() to get NDJSON events as they arrive (Pro plan required).
Can I override settings per execution?
Section titled “Can I override settings per execution?”Yes. execute(), aexecute(), and execute_stream() accept timeout, env_vars, metadata, and sub_paths as keyword arguments. Passing a value overrides the constructor default for that call only.