Official Python SDK for the Caged AI Agent Sandbox Platform
Project description
caged
Official Python SDK for the Caged AI Agent Sandbox Platform.
Installation
pip install caged-sdk
Quick Start
from caged import Caged
caged = Caged(api_key="caged_sk_...")
# Create a sandbox
sandbox = caged.sandboxes.create(template="node-20", memory_mb=1024)
print(f"Sandbox {sandbox.id} is {sandbox.status}")
# Run a command
result = caged.sandboxes.exec(sandbox.id, "echo 'hello world'")
print(result.output)
# Write and read files
caged.files.write(sandbox.id, "/workspace/hello.py", "print('hi')")
content = caged.files.read(sandbox.id, "/workspace/hello.py")
# Create a snapshot
snapshot = caged.snapshots.create(sandbox.id, name="checkpoint-1")
# Clean up
caged.sandboxes.destroy(sandbox.id)
Context Manager
with Caged(api_key="caged_sk_...") as caged:
sandbox = caged.sandboxes.create(template="python-312")
result = caged.sandboxes.exec(sandbox.id, "python --version")
print(result.output)
caged.sandboxes.destroy(sandbox.id)
Interactive Terminal (WebSocket)
import asyncio
from caged import Caged
async def main():
caged = Caged(api_key="caged_sk_...")
sandbox = caged.sandboxes.create(template="node-20")
terminal = await caged.sandboxes.terminal(sandbox.id)
terminal.on_output(lambda data: print(data, end=""))
await terminal.send("ls -la\n")
await asyncio.sleep(2)
await terminal.close()
asyncio.run(main())
Streaming Exec
import asyncio
from caged import Caged
async def main():
caged = Caged(api_key="caged_sk_...")
sandbox = caged.sandboxes.create(template="node-20")
stream = await caged.sandboxes.exec_stream(sandbox.id, "npm test")
async for chunk in stream:
print(chunk, end="")
print(f"\nExit code: {stream.exit_code}")
asyncio.run(main())
MCP (Model Context Protocol)
import asyncio
from caged import Caged
async def main():
caged = Caged(api_key="caged_sk_...")
sandbox = caged.sandboxes.create(template="node-20")
mcp = await caged.sandboxes.mcp(sandbox.id)
# List available tools
tools = await mcp.list_tools()
for tool in tools:
print(f" {tool.name}: {tool.description}")
# Call a tool
result = await mcp.call_tool("terminal_exec", {"command": "npm test"})
print(result["content"][0]["text"])
await mcp.close()
asyncio.run(main())
Session Replay
caged = Caged(api_key="caged_sk_...")
# List sessions for a sandbox
sessions = caged.sessions.list_by_sandbox("sandbox-id")
for s in sessions:
print(f"{s.id}: {s.agent_type} — ${s.cost_usd:.4f}")
# Get replay timeline
events = caged.sessions.replay(sessions[0].id)
for event in events:
print(f"[{event.timestamp}] {event.type}: {event.data}")
# Get summary
summary = caged.sessions.replay_summary(sessions[0].id)
print(f"Duration: {summary.duration_ms}ms, Cost: ${summary.cost_usd:.4f}")
Events Ingestion
from caged import Caged, EventPayload
caged = Caged(api_key="caged_sk_...")
response = caged.events.ingest([
EventPayload(
type="llm_call",
sandbox_id="sandbox-id",
data={"model": "claude-4", "tokens_in": 500, "tokens_out": 200},
),
])
print(f"Accepted: {response.accepted}, Errors: {response.errors}")
Alerts & Notifications
caged = Caged(api_key="caged_sk_...")
# List alerts
alerts = caged.alerts.list()
for alert in alerts:
print(f"[{alert.severity}] {alert.message}")
# Resolve an alert
caged.alerts.resolve(alerts[0].id)
# Check notifications
count = caged.notifications.unread_count()
print(f"Unread: {count}")
notifications = caged.notifications.list()
caged.notifications.mark_all_read()
Billing
caged = Caged(api_key="caged_sk_...")
sub = caged.billing.get_subscription()
print(f"Plan: {sub.plan}, Status: {sub.status}")
# Get checkout URL for upgrade
url = caged.billing.create_checkout("pro")
print(f"Upgrade: {url}")
Full API Reference
Sandboxes
| Method | Description |
|---|---|
sandboxes.create(template, cpus, memory_mb, ...) |
Create a sandbox |
sandboxes.list() |
List all sandboxes |
sandboxes.get(id) |
Get sandbox by ID |
sandboxes.destroy(id) |
Destroy a sandbox |
sandboxes.exec(id, command) |
Run a command (sync) |
await sandboxes.exec_stream(id, command) |
Stream command output (async) |
await sandboxes.terminal(id) |
Interactive terminal (async) |
await sandboxes.mcp(id) |
MCP tool client (async) |
sandboxes.pause(id) |
Pause a sandbox |
sandboxes.resume(id) |
Resume a paused sandbox |
sandboxes.logs(id, tail=N) |
Get sandbox logs |
sandboxes.ports(id) |
List open ports |
sandboxes.trust_scores(sandbox_id) |
Get trust scores |
Files
| Method | Description |
|---|---|
files.list(sandbox_id, path) |
List directory contents |
files.read(sandbox_id, path) |
Read file content |
files.write(sandbox_id, path, content) |
Write file content |
files.git_diff(sandbox_id) |
Get git diff |
Snapshots
| Method | Description |
|---|---|
snapshots.list(sandbox_id) |
List snapshots |
snapshots.create(sandbox_id, name, description) |
Create snapshot |
snapshots.get(snapshot_id) |
Get snapshot details |
snapshots.delete(snapshot_id) |
Delete snapshot |
snapshots.download_url(snapshot_id) |
Get download URL |
snapshots.restore(snapshot_id) |
Restore snapshot |
Sessions (Agent history & replay)
| Method | Description |
|---|---|
sessions.list_by_sandbox(sandbox_id) |
List agent sessions |
sessions.get(session_id) |
Get session details |
sessions.replay(session_id) |
Get replay timeline |
sessions.replay_summary(session_id) |
Get replay summary |
Events
| Method | Description |
|---|---|
events.ingest(events) |
Ingest observability events |
Alerts
| Method | Description |
|---|---|
alerts.list() |
List all alerts |
alerts.get(id) |
Get alert by ID |
alerts.resolve(id) |
Resolve an alert |
alerts.list_rules() |
List alert rules |
alerts.update_rule(id, **kwargs) |
Update alert rule |
Notifications
| Method | Description |
|---|---|
notifications.list() |
List notifications |
notifications.unread_count() |
Get unread count |
notifications.mark_read(id) |
Mark as read |
notifications.mark_all_read() |
Mark all as read |
notifications.get_config() |
Get notification config |
notifications.update_config(**kwargs) |
Update config |
Account
| Method | Description |
|---|---|
account.list_keys() |
List API keys |
account.create_key(name) |
Create new API key |
account.revoke_key(id) |
Revoke an API key |
account.list_sessions() |
List active sessions |
account.revoke_session(id) |
Revoke a session |
Billing
| Method | Description |
|---|---|
billing.get_subscription() |
Get subscription details |
billing.create_checkout(plan) |
Get Stripe checkout URL |
billing.create_portal() |
Get billing portal URL |
billing.cancel() |
Cancel subscription |
Error Handling
from caged import Caged, CagedAPIError, CagedTimeoutError
caged = Caged(api_key="caged_sk_...")
try:
caged.sandboxes.get("nonexistent")
except CagedAPIError as e:
print(f"API error {e.status}: {e}")
except CagedTimeoutError as e:
print(f"Timeout: {e}")
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file caged_sdk-0.2.0.tar.gz.
File metadata
- Download URL: caged_sdk-0.2.0.tar.gz
- Upload date:
- Size: 13.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab0f8b34a8bca8768be32d27f0aa9fabed614f833353de99591830b7f9f1021b
|
|
| MD5 |
5ccf73fc9a58db31f95e54c2f849ccb8
|
|
| BLAKE2b-256 |
9a00d9e6e67f5e91c9656e4e82f0b7a0dce050f9367bec5096581f42a5e43802
|
Provenance
The following attestation bundles were made for caged_sdk-0.2.0.tar.gz:
Publisher:
publish.yml on caged-dev/sdk-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
caged_sdk-0.2.0.tar.gz -
Subject digest:
ab0f8b34a8bca8768be32d27f0aa9fabed614f833353de99591830b7f9f1021b - Sigstore transparency entry: 1818626248
- Sigstore integration time:
-
Permalink:
caged-dev/sdk-python@bb6dda9fdd70e15dca624b7123b2d66221e13061 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/caged-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@bb6dda9fdd70e15dca624b7123b2d66221e13061 -
Trigger Event:
push
-
Statement type:
File details
Details for the file caged_sdk-0.2.0-py3-none-any.whl.
File metadata
- Download URL: caged_sdk-0.2.0-py3-none-any.whl
- Upload date:
- Size: 16.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
68afe0572a56cd425896cadf9144379c3f8de08e02e61aa2625ad056b9b38f1b
|
|
| MD5 |
c9e9e0c380bbdcba037dc37721242df7
|
|
| BLAKE2b-256 |
dbf7d913ffe986390e3beb8d7a4a44d0df34bc069433813962d4584e61b8b442
|
Provenance
The following attestation bundles were made for caged_sdk-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on caged-dev/sdk-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
caged_sdk-0.2.0-py3-none-any.whl -
Subject digest:
68afe0572a56cd425896cadf9144379c3f8de08e02e61aa2625ad056b9b38f1b - Sigstore transparency entry: 1818626304
- Sigstore integration time:
-
Permalink:
caged-dev/sdk-python@bb6dda9fdd70e15dca624b7123b2d66221e13061 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/caged-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@bb6dda9fdd70e15dca624b7123b2d66221e13061 -
Trigger Event:
push
-
Statement type: