mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 09:01:17 +00:00
feat: refresh docs and agent schema
This commit is contained in:
parent
a49ea094f3
commit
0fbf6272b1
39 changed files with 3127 additions and 1806 deletions
26
docs/agent-compatibility.mdx
Normal file
26
docs/agent-compatibility.mdx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
title: "Agent Compatibility"
|
||||
description: "Supported agents, install methods, and streaming formats."
|
||||
---
|
||||
|
||||
## Compatibility matrix
|
||||
|
||||
| Agent | Provider | Binary | Install method | Session ID | Streaming format |
|
||||
|-------|----------|--------|----------------|------------|------------------|
|
||||
| Claude Code | Anthropic | `claude` | curl raw binary from GCS | `session_id` | JSONL via stdout |
|
||||
| Codex | OpenAI | `codex` | curl tarball from GitHub releases | `thread_id` | JSONL via stdout |
|
||||
| OpenCode | Multi-provider | `opencode` | curl tarball from GitHub releases | `session_id` | SSE or JSONL |
|
||||
| Amp | Sourcegraph | `amp` | curl raw binary from GCS | `session_id` | JSONL via stdout |
|
||||
|
||||
## Agent modes
|
||||
|
||||
- **OpenCode**: discovered via the server API.
|
||||
- **Claude Code / Codex / Amp**: hardcoded modes (typically `build`, `plan`, or `custom`).
|
||||
|
||||
## Capability notes
|
||||
|
||||
- **Questions / permissions**: OpenCode natively supports these workflows. Claude plan approval is normalized into a question event.
|
||||
- **Streaming**: all agents stream events; OpenCode uses SSE while others use JSONL.
|
||||
- **Files and images**: normalized via `UniversalMessagePart` with `File` and `Image` parts.
|
||||
|
||||
See [Universal API](/universal-api) for feature coverage details.
|
||||
45
docs/architecture.mdx
Normal file
45
docs/architecture.mdx
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
title: "Architecture"
|
||||
description: "How the daemon, schemas, and agents fit together."
|
||||
---
|
||||
|
||||
Sandbox Agent SDK is built around a single daemon that runs inside the sandbox and exposes a universal HTTP API. Clients use the API (or the TypeScript SDK / CLI) to create sessions, send messages, and stream events.
|
||||
|
||||
## Components
|
||||
|
||||
- **Daemon**: Rust HTTP server that manages agent processes and streaming.
|
||||
- **Universal schema**: Shared input/output types for messages and events.
|
||||
- **SDKs & CLI**: Convenience wrappers around the HTTP API.
|
||||
|
||||
## Session model
|
||||
|
||||
- **Session ID**: Client-provided primary session identifier.
|
||||
- **Agent session ID**: Underlying ID from the agent (thread/session). This is surfaced in events but is not the primary key.
|
||||
|
||||
## Event streaming
|
||||
|
||||
- Events are stored in memory per session and assigned a monotonically increasing `id`.
|
||||
- `/events` returns a slice of events by offset/limit.
|
||||
- `/events/sse` streams new events from the same offset semantics.
|
||||
|
||||
## Agent integration strategies
|
||||
|
||||
### Subprocess per session
|
||||
|
||||
Claude Code, Codex, and Amp run as subprocesses. The daemon reads JSONL output from stdout and converts each event into a UniversalEvent.
|
||||
|
||||
### Shared server (OpenCode)
|
||||
|
||||
OpenCode runs as a shared server. The daemon connects via HTTP and SSE, then converts OpenCode events to UniversalEvents.
|
||||
|
||||
## Human-in-the-loop
|
||||
|
||||
Questions and permission prompts are normalized into the universal schema:
|
||||
|
||||
- Question events surface as `questionAsked` with selectable options.
|
||||
- Permission events surface as `permissionAsked` with `reply: once | always | reject`.
|
||||
- Claude plan approval is normalized into a question event (approve/reject).
|
||||
|
||||
## Authentication
|
||||
|
||||
The daemon uses a **global token** configured at startup. All HTTP and CLI operations reuse the same token and are validated against the `Authorization` header (`Bearer` or `Token`) or `x-sandbox-token`.
|
||||
111
docs/cli.mdx
Normal file
111
docs/cli.mdx
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
---
|
||||
title: "CLI"
|
||||
description: "CLI reference and server flags."
|
||||
---
|
||||
|
||||
The `sandbox-agent` CLI mirrors the HTTP API so you can script everything without writing client code.
|
||||
|
||||
## Server flags
|
||||
|
||||
```bash
|
||||
sandbox-agent --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 8787
|
||||
```
|
||||
|
||||
- `--token`: global token for all requests.
|
||||
- `--no-token`: disable auth (local dev only).
|
||||
- `--host`, `--port`: bind address.
|
||||
- `--cors-allow-origin`, `--cors-allow-method`, `--cors-allow-header`, `--cors-allow-credentials`: configure CORS.
|
||||
|
||||
## Agent commands
|
||||
|
||||
<details>
|
||||
<summary><strong>agents list</strong></summary>
|
||||
|
||||
```bash
|
||||
sandbox-agent agents list --endpoint http://127.0.0.1:8787
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>agents install</strong></summary>
|
||||
|
||||
```bash
|
||||
sandbox-agent agents install claude --reinstall --endpoint http://127.0.0.1:8787
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>agents modes</strong></summary>
|
||||
|
||||
```bash
|
||||
sandbox-agent agents modes claude --endpoint http://127.0.0.1:8787
|
||||
```
|
||||
</details>
|
||||
|
||||
## Session commands
|
||||
|
||||
<details>
|
||||
<summary><strong>sessions create</strong></summary>
|
||||
|
||||
```bash
|
||||
sandbox-agent sessions create my-session \
|
||||
--agent claude \
|
||||
--agent-mode build \
|
||||
--permission-mode default \
|
||||
--endpoint http://127.0.0.1:8787
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>sessions send-message</strong></summary>
|
||||
|
||||
```bash
|
||||
sandbox-agent sessions send-message my-session \
|
||||
--message "Summarize the repository" \
|
||||
--endpoint http://127.0.0.1:8787
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>sessions events</strong></summary>
|
||||
|
||||
```bash
|
||||
sandbox-agent sessions events my-session --offset 0 --limit 50 --endpoint http://127.0.0.1:8787
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>sessions events-sse</strong></summary>
|
||||
|
||||
```bash
|
||||
sandbox-agent sessions events-sse my-session --offset 0 --endpoint http://127.0.0.1:8787
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>sessions reply-question</strong></summary>
|
||||
|
||||
```bash
|
||||
sandbox-agent sessions reply-question my-session QUESTION_ID \
|
||||
--answers "yes" \
|
||||
--endpoint http://127.0.0.1:8787
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>sessions reject-question</strong></summary>
|
||||
|
||||
```bash
|
||||
sandbox-agent sessions reject-question my-session QUESTION_ID --endpoint http://127.0.0.1:8787
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>sessions reply-permission</strong></summary>
|
||||
|
||||
```bash
|
||||
sandbox-agent sessions reply-permission my-session PERMISSION_ID \
|
||||
--reply once \
|
||||
--endpoint http://127.0.0.1:8787
|
||||
```
|
||||
</details>
|
||||
21
docs/deployments/cloudflare-sandboxes.mdx
Normal file
21
docs/deployments/cloudflare-sandboxes.mdx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
title: "Cloudflare Sandboxes"
|
||||
description: "Deploy the daemon in Cloudflare Sandboxes."
|
||||
---
|
||||
|
||||
## Steps
|
||||
|
||||
1. Create a Cloudflare Sandbox with a Linux runtime.
|
||||
2. Install the agent binaries and the sandbox-agent daemon.
|
||||
3. Start the daemon and expose the HTTP port.
|
||||
|
||||
```bash
|
||||
export SANDBOX_TOKEN="..."
|
||||
|
||||
cargo run -p sandbox-agent -- \
|
||||
--token "$SANDBOX_TOKEN" \
|
||||
--host 0.0.0.0 \
|
||||
--port 8787
|
||||
```
|
||||
|
||||
4. Connect your client to the sandbox endpoint.
|
||||
21
docs/deployments/daytona.mdx
Normal file
21
docs/deployments/daytona.mdx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
title: "Daytona"
|
||||
description: "Run the daemon in a Daytona workspace."
|
||||
---
|
||||
|
||||
## Steps
|
||||
|
||||
1. Create a Daytona workspace with Rust and curl available.
|
||||
2. Install or build the sandbox-agent binary.
|
||||
3. Start the daemon and expose port `8787` (or your preferred port).
|
||||
|
||||
```bash
|
||||
export SANDBOX_TOKEN="..."
|
||||
|
||||
cargo run -p sandbox-agent -- \
|
||||
--token "$SANDBOX_TOKEN" \
|
||||
--host 0.0.0.0 \
|
||||
--port 8787
|
||||
```
|
||||
|
||||
4. Use your Daytona port forwarding to reach the daemon from your client.
|
||||
27
docs/deployments/docker.mdx
Normal file
27
docs/deployments/docker.mdx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
title: "Docker (dev)"
|
||||
description: "Build and run the daemon in a Docker container."
|
||||
---
|
||||
|
||||
## Build the binary
|
||||
|
||||
Use the release Dockerfile to build a static binary:
|
||||
|
||||
```bash
|
||||
docker build -f docker/release/linux-x86_64.Dockerfile -t sandbox-agent-build .
|
||||
|
||||
docker run --rm -v "$PWD/artifacts:/artifacts" sandbox-agent-build
|
||||
```
|
||||
|
||||
The binary will be written to `./artifacts/sandbox-agent-x86_64-unknown-linux-musl`.
|
||||
|
||||
## Run the daemon
|
||||
|
||||
```bash
|
||||
docker run --rm -p 8787:8787 \
|
||||
-v "$PWD/artifacts:/artifacts" \
|
||||
debian:bookworm-slim \
|
||||
/artifacts/sandbox-agent-x86_64-unknown-linux-musl --token "$SANDBOX_TOKEN" --host 0.0.0.0 --port 8787
|
||||
```
|
||||
|
||||
You can now access the API at `http://localhost:8787`.
|
||||
25
docs/deployments/e2b.mdx
Normal file
25
docs/deployments/e2b.mdx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
title: "E2B"
|
||||
description: "Deploy the daemon inside an E2B sandbox."
|
||||
---
|
||||
|
||||
## Steps
|
||||
|
||||
1. Start an E2B sandbox with network access.
|
||||
2. Install the agent binaries you need (Claude, Codex, OpenCode, Amp).
|
||||
3. Run the daemon and expose its port.
|
||||
|
||||
Example startup script:
|
||||
|
||||
```bash
|
||||
export SANDBOX_TOKEN="..."
|
||||
|
||||
# Install sandbox-agent binary (or build from source)
|
||||
# TODO: replace with release download once published
|
||||
cargo run -p sandbox-agent -- \
|
||||
--token "$SANDBOX_TOKEN" \
|
||||
--host 0.0.0.0 \
|
||||
--port 8787
|
||||
```
|
||||
|
||||
4. Configure your client to connect to the sandbox endpoint.
|
||||
21
docs/deployments/vercel-sandboxes.mdx
Normal file
21
docs/deployments/vercel-sandboxes.mdx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
title: "Vercel Sandboxes"
|
||||
description: "Run the daemon inside Vercel Sandboxes."
|
||||
---
|
||||
|
||||
## Steps
|
||||
|
||||
1. Provision a Vercel Sandbox with network access and storage.
|
||||
2. Install the agent binaries you need.
|
||||
3. Run the daemon and expose the port.
|
||||
|
||||
```bash
|
||||
export SANDBOX_TOKEN="..."
|
||||
|
||||
cargo run -p sandbox-agent -- \
|
||||
--token "$SANDBOX_TOKEN" \
|
||||
--host 0.0.0.0 \
|
||||
--port 8787
|
||||
```
|
||||
|
||||
4. Configure your client to use the sandbox URL.
|
||||
82
docs/docs.json
Normal file
82
docs/docs.json
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
{
|
||||
"$schema": "https://mintlify.com/docs.json",
|
||||
"theme": "dark",
|
||||
"name": "Sandbox Agent SDK",
|
||||
"colors": {
|
||||
"primary": "#ff4f00",
|
||||
"light": "#ff6a2a",
|
||||
"dark": "#cc3f00",
|
||||
"background": "#000000",
|
||||
"card": "#1c1c1e",
|
||||
"border": "#2c2c2e",
|
||||
"inputBackground": "#2c2c2e",
|
||||
"inputBorder": "#3a3a3c",
|
||||
"text": "#ffffff",
|
||||
"muted": "#8e8e93",
|
||||
"success": "#30d158",
|
||||
"warning": "#ff4f00",
|
||||
"danger": "#ff3b30",
|
||||
"purple": "#bf5af2"
|
||||
},
|
||||
"favicon": "/favicon.svg",
|
||||
"logo": {
|
||||
"light": "/logo/light.svg",
|
||||
"dark": "/logo/dark.svg"
|
||||
},
|
||||
"navigation": {
|
||||
"tabs": [
|
||||
{
|
||||
"tab": "Guides",
|
||||
"groups": [
|
||||
{
|
||||
"group": "Getting started",
|
||||
"pages": [
|
||||
"index",
|
||||
"quickstart",
|
||||
"architecture",
|
||||
"agent-compatibility",
|
||||
"universal-api"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Operations",
|
||||
"pages": [
|
||||
"frontend"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tab": "Reference",
|
||||
"groups": [
|
||||
{
|
||||
"group": "Interfaces",
|
||||
"pages": [
|
||||
"cli",
|
||||
"http-api",
|
||||
"typescript-sdk"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tab": "Deployments",
|
||||
"groups": [
|
||||
{
|
||||
"group": "Examples",
|
||||
"pages": [
|
||||
"deployments/docker",
|
||||
"deployments/e2b",
|
||||
"deployments/daytona",
|
||||
"deployments/vercel-sandboxes",
|
||||
"deployments/cloudflare-sandboxes"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"styles": [
|
||||
"/theme.css"
|
||||
]
|
||||
}
|
||||
19
docs/favicon.svg
Normal file
19
docs/favicon.svg
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.06145 23.1079C5.26816 22.3769 -3.39077 20.6274 1.4173 5.06384C9.6344 6.09939 16.9728 14.0644 9.06145 23.1079Z" fill="url(#paint0_linear_17557_2021)"/>
|
||||
<path d="M8.91928 23.0939C5.27642 21.2223 0.78371 4.20891 17.0071 0C20.7569 7.19341 19.6212 16.5452 8.91928 23.0939Z" fill="url(#paint1_linear_17557_2021)"/>
|
||||
<path d="M8.91388 23.0788C8.73534 19.8817 10.1585 9.08525 23.5699 13.1107C23.1812 20.1229 18.984 26.4182 8.91388 23.0788Z" fill="url(#paint2_linear_17557_2021)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_17557_2021" x1="3.77557" y1="5.91571" x2="5.23185" y2="21.5589" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#18E299"/>
|
||||
<stop offset="1" stop-color="#15803D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_17557_2021" x1="12.1711" y1="-0.718425" x2="10.1897" y2="22.9832" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#16A34A"/>
|
||||
<stop offset="1" stop-color="#4ADE80"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_17557_2021" x1="23.1327" y1="15.353" x2="9.33841" y2="18.5196" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#4ADE80"/>
|
||||
<stop offset="1" stop-color="#0D9373"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
20
docs/frontend.mdx
Normal file
20
docs/frontend.mdx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
title: "Frontend Demo"
|
||||
description: "Run the Vite + React UI for testing the daemon."
|
||||
---
|
||||
|
||||
The demo frontend lives at `frontend/packages/web`.
|
||||
|
||||
## Run locally
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm --filter @sandbox-agent/web dev
|
||||
```
|
||||
|
||||
The UI expects:
|
||||
|
||||
- Endpoint (e.g. `http://127.0.0.1:8787`)
|
||||
- Optional token
|
||||
|
||||
If you see CORS errors, enable CORS on the daemon with `--cors-allow-origin` and related flags.
|
||||
157
docs/http-api.mdx
Normal file
157
docs/http-api.mdx
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
---
|
||||
title: "HTTP API"
|
||||
description: "Endpoint reference for the sandbox agent daemon."
|
||||
---
|
||||
|
||||
All endpoints are under `/v1`. Authentication uses the daemon-level token via `Authorization: Bearer <token>` or `x-sandbox-token`.
|
||||
|
||||
## Sessions
|
||||
|
||||
<details>
|
||||
<summary><strong>POST /v1/sessions/{sessionId}</strong> - Create session</summary>
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{
|
||||
"agent": "claude",
|
||||
"agentMode": "build",
|
||||
"permissionMode": "default",
|
||||
"model": "claude-3-5-sonnet",
|
||||
"variant": "high",
|
||||
"agentVersion": "latest"
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"healthy": true,
|
||||
"agentSessionId": "..."
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>POST /v1/sessions/{sessionId}/messages</strong> - Send message</summary>
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Describe the repository."
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>GET /v1/sessions/{sessionId}/events</strong> - Fetch events</summary>
|
||||
|
||||
Query params:
|
||||
|
||||
- `offset`: last-seen event id (exclusive)
|
||||
- `limit`: max number of events
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"events": [
|
||||
{
|
||||
"id": 1,
|
||||
"timestamp": "2026-01-25T10:00:00Z",
|
||||
"sessionId": "my-session",
|
||||
"agent": "claude",
|
||||
"agentSessionId": "...",
|
||||
"data": { "message": { "role": "assistant", "parts": [{ "type": "text", "text": "..." }] } }
|
||||
}
|
||||
],
|
||||
"hasMore": false
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>GET /v1/sessions/{sessionId}/events/sse</strong> - Stream events (SSE)</summary>
|
||||
|
||||
Query params:
|
||||
|
||||
- `offset`: last-seen event id (exclusive)
|
||||
|
||||
SSE payloads are `UniversalEvent` JSON.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>POST /v1/sessions/{sessionId}/questions/{questionId}/reply</strong></summary>
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{ "answers": [["Option A"], ["Option B", "Option C"]] }
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>POST /v1/sessions/{sessionId}/questions/{questionId}/reject</strong></summary>
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{}
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>POST /v1/sessions/{sessionId}/permissions/{permissionId}/reply</strong></summary>
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{ "reply": "once" }
|
||||
```
|
||||
</details>
|
||||
|
||||
## Agents
|
||||
|
||||
<details>
|
||||
<summary><strong>GET /v1/agents</strong> - List agents</summary>
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": [
|
||||
{ "id": "claude", "installed": true, "version": "...", "path": "/usr/local/bin/claude" }
|
||||
]
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>POST /v1/agents/{agentId}/install</strong> - Install agent</summary>
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{ "reinstall": false }
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>GET /v1/agents/{agentId}/modes</strong> - List modes</summary>
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"modes": [
|
||||
{ "id": "build", "name": "Build", "description": "Default coding mode" }
|
||||
]
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
## Error handling
|
||||
|
||||
All errors use RFC 7807 Problem Details and stable `type` strings (e.g. `urn:sandbox-agent:error:session_not_found`).
|
||||
68
docs/index.mdx
Normal file
68
docs/index.mdx
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
title: "Overview"
|
||||
description: "Universal API for running Claude Code, Codex, OpenCode, and Amp inside sandboxes."
|
||||
---
|
||||
|
||||
Sandbox Agent SDK is a universal API and daemon for running coding agents inside sandboxes. It standardizes agent sessions, events, and human-in-the-loop workflows across Claude Code, Codex, OpenCode, and Amp.
|
||||
|
||||
## At a glance
|
||||
|
||||
- Universal HTTP API and TypeScript SDK
|
||||
- Runs inside sandboxes with a lightweight Rust daemon
|
||||
- Streams events in a shared UniversalEvent schema
|
||||
- Supports questions and permission workflows
|
||||
- Designed for multi-provider sandbox environments
|
||||
|
||||
## Quickstart
|
||||
|
||||
Run the daemon locally:
|
||||
|
||||
```bash
|
||||
sandbox-agent --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 8787
|
||||
```
|
||||
|
||||
Send a message:
|
||||
|
||||
```bash
|
||||
curl -X POST "http://127.0.0.1:8787/v1/sessions/my-session" \
|
||||
-H "Authorization: Bearer $SANDBOX_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"agent":"claude"}'
|
||||
|
||||
curl -X POST "http://127.0.0.1:8787/v1/sessions/my-session/messages" \
|
||||
-H "Authorization: Bearer $SANDBOX_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"message":"Explain the repo structure."}'
|
||||
```
|
||||
|
||||
See the full quickstart in [Quickstart](/quickstart).
|
||||
|
||||
## What this project solves
|
||||
|
||||
- **Universal Coding Agent API**: standardize tool calls, messages, and events across agents.
|
||||
- **Agents in sandboxes**: run a single HTTP daemon inside any sandbox provider.
|
||||
- **Agent transcripts**: stream or persist a universal event log in your own storage.
|
||||
|
||||
## Project scope
|
||||
|
||||
**In scope**
|
||||
|
||||
- Agent session orchestration inside a sandbox
|
||||
- Streaming events in a universal schema
|
||||
- Human-in-the-loop questions and permissions
|
||||
- TypeScript SDK and CLI wrappers
|
||||
|
||||
**Out of scope**
|
||||
|
||||
- Persistent storage of sessions on disk
|
||||
- Building custom LLM agents (use Vercel AI SDK for that)
|
||||
- Sandbox provider APIs (use provider SDKs or custom glue)
|
||||
- Git repo management
|
||||
|
||||
## Next steps
|
||||
|
||||
- Read the [Architecture](/architecture) overview
|
||||
- Review [Agent compatibility](/agent-compatibility)
|
||||
- See the [HTTP API](/http-api) and [CLI](/cli)
|
||||
- Run the [Frontend demo](/frontend)
|
||||
- Use the [TypeScript SDK](/typescript-sdk)
|
||||
21
docs/logo/dark.svg
Normal file
21
docs/logo/dark.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 12 KiB |
21
docs/logo/light.svg
Normal file
21
docs/logo/light.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 12 KiB |
75
docs/quickstart.mdx
Normal file
75
docs/quickstart.mdx
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
title: "Quickstart"
|
||||
description: "Start the daemon and send your first message."
|
||||
---
|
||||
|
||||
## 1. Run the daemon
|
||||
|
||||
Use the installed binary, or `cargo run` in development.
|
||||
|
||||
```bash
|
||||
sandbox-agent --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 8787
|
||||
```
|
||||
|
||||
If you want to run without auth (local dev only):
|
||||
|
||||
```bash
|
||||
sandbox-agent --no-token --host 127.0.0.1 --port 8787
|
||||
```
|
||||
|
||||
### CORS (frontend usage)
|
||||
|
||||
If you are calling the daemon from a browser, enable CORS explicitly:
|
||||
|
||||
```bash
|
||||
sandbox-agent \
|
||||
--token "$SANDBOX_TOKEN" \
|
||||
--cors-allow-origin "http://localhost:5173" \
|
||||
--cors-allow-method "GET" \
|
||||
--cors-allow-method "POST" \
|
||||
--cors-allow-header "Authorization" \
|
||||
--cors-allow-header "Content-Type" \
|
||||
--cors-allow-credentials
|
||||
```
|
||||
|
||||
## 2. Create a session
|
||||
|
||||
```bash
|
||||
curl -X POST "http://127.0.0.1:8787/v1/sessions/my-session" \
|
||||
-H "Authorization: Bearer $SANDBOX_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"agent":"claude","agentMode":"build","permissionMode":"default"}'
|
||||
```
|
||||
|
||||
## 3. Send a message
|
||||
|
||||
```bash
|
||||
curl -X POST "http://127.0.0.1:8787/v1/sessions/my-session/messages" \
|
||||
-H "Authorization: Bearer $SANDBOX_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"message":"Summarize the repository and suggest next steps."}'
|
||||
```
|
||||
|
||||
## 4. Read events
|
||||
|
||||
```bash
|
||||
curl "http://127.0.0.1:8787/v1/sessions/my-session/events?offset=0&limit=50" \
|
||||
-H "Authorization: Bearer $SANDBOX_TOKEN"
|
||||
```
|
||||
|
||||
For streaming output, use SSE:
|
||||
|
||||
```bash
|
||||
curl "http://127.0.0.1:8787/v1/sessions/my-session/events/sse?offset=0" \
|
||||
-H "Authorization: Bearer $SANDBOX_TOKEN"
|
||||
```
|
||||
|
||||
## 5. CLI shortcuts
|
||||
|
||||
The CLI mirrors the HTTP API:
|
||||
|
||||
```bash
|
||||
sandbox-agent sessions create my-session --agent claude --endpoint http://127.0.0.1:8787 --token "$SANDBOX_TOKEN"
|
||||
|
||||
sandbox-agent sessions send-message my-session --message "Hello" --endpoint http://127.0.0.1:8787 --token "$SANDBOX_TOKEN"
|
||||
```
|
||||
72
docs/theme.css
Normal file
72
docs/theme.css
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
:root {
|
||||
color-scheme: dark;
|
||||
--sa-primary: #ff4f00;
|
||||
--sa-bg: #000000;
|
||||
--sa-card: #1c1c1e;
|
||||
--sa-border: #2c2c2e;
|
||||
--sa-input-bg: #2c2c2e;
|
||||
--sa-input-border: #3a3a3c;
|
||||
--sa-text: #ffffff;
|
||||
--sa-muted: #8e8e93;
|
||||
--sa-success: #30d158;
|
||||
--sa-warning: #ff4f00;
|
||||
--sa-danger: #ff3b30;
|
||||
--sa-purple: #bf5af2;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
background-color: var(--sa-bg);
|
||||
color: var(--sa-text);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--sa-primary);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--sa-warning);
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: var(--sa-border);
|
||||
}
|
||||
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
background-color: var(--sa-input-bg);
|
||||
border: 1px solid var(--sa-input-border);
|
||||
color: var(--sa-text);
|
||||
}
|
||||
|
||||
code,
|
||||
pre {
|
||||
background-color: var(--sa-card);
|
||||
border: 1px solid var(--sa-border);
|
||||
color: var(--sa-text);
|
||||
}
|
||||
|
||||
.card,
|
||||
.mintlify-card,
|
||||
.docs-card {
|
||||
background-color: var(--sa-card);
|
||||
border: 1px solid var(--sa-border);
|
||||
}
|
||||
|
||||
.muted,
|
||||
.text-muted {
|
||||
color: var(--sa-muted);
|
||||
}
|
||||
|
||||
.alert-success {
|
||||
border-color: var(--sa-success);
|
||||
}
|
||||
|
||||
.alert-warning {
|
||||
border-color: var(--sa-warning);
|
||||
}
|
||||
|
||||
.alert-danger {
|
||||
border-color: var(--sa-danger);
|
||||
}
|
||||
100
docs/typescript-sdk.mdx
Normal file
100
docs/typescript-sdk.mdx
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
---
|
||||
title: "TypeScript SDK"
|
||||
description: "Generated types and a thin fetch-based client."
|
||||
---
|
||||
|
||||
The TypeScript SDK is generated from the OpenAPI spec produced by the Rust server.
|
||||
|
||||
## Generate types
|
||||
|
||||
```bash
|
||||
pnpm --filter @sandbox-agent/typescript-sdk generate
|
||||
```
|
||||
|
||||
This runs:
|
||||
|
||||
- `cargo run -p sandbox-agent-openapi-gen` to emit OpenAPI JSON
|
||||
- `openapi-typescript` to generate types
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { SandboxDaemonClient } from "@sandbox-agent/typescript-sdk";
|
||||
|
||||
const client = new SandboxDaemonClient({
|
||||
baseUrl: "http://127.0.0.1:8787",
|
||||
token: process.env.SANDBOX_TOKEN,
|
||||
});
|
||||
|
||||
await client.createSession("my-session", { agent: "claude" });
|
||||
await client.postMessage("my-session", { message: "Hello" });
|
||||
const events = await client.getEvents("my-session", { offset: 0, limit: 50 });
|
||||
```
|
||||
|
||||
## Endpoint mapping
|
||||
|
||||
<details>
|
||||
<summary><strong>client.listAgents()</strong></summary>
|
||||
|
||||
Maps to `GET /v1/agents`.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>client.installAgent(agentId, body)</strong></summary>
|
||||
|
||||
Maps to `POST /v1/agents/{agentId}/install`.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>client.getAgentModes(agentId)</strong></summary>
|
||||
|
||||
Maps to `GET /v1/agents/{agentId}/modes`.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>client.createSession(sessionId, body)</strong></summary>
|
||||
|
||||
Maps to `POST /v1/sessions/{sessionId}`.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>client.postMessage(sessionId, body)</strong></summary>
|
||||
|
||||
Maps to `POST /v1/sessions/{sessionId}/messages`.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>client.getEvents(sessionId, params)</strong></summary>
|
||||
|
||||
Maps to `GET /v1/sessions/{sessionId}/events`.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>client.getEventsSse(sessionId, params)</strong></summary>
|
||||
|
||||
Maps to `GET /v1/sessions/{sessionId}/events/sse` (raw SSE response).
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>client.streamEvents(sessionId, params)</strong></summary>
|
||||
|
||||
Helper that parses SSE into `UniversalEvent` objects.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>client.replyQuestion(sessionId, questionId, body)</strong></summary>
|
||||
|
||||
Maps to `POST /v1/sessions/{sessionId}/questions/{questionId}/reply`.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>client.rejectQuestion(sessionId, questionId)</strong></summary>
|
||||
|
||||
Maps to `POST /v1/sessions/{sessionId}/questions/{questionId}/reject`.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>client.replyPermission(sessionId, permissionId, body)</strong></summary>
|
||||
|
||||
Maps to `POST /v1/sessions/{sessionId}/permissions/{permissionId}/reply`.
|
||||
</details>
|
||||
30
docs/universal-api.mdx
Normal file
30
docs/universal-api.mdx
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
title: "Universal API"
|
||||
description: "Feature checklist and normalization rules."
|
||||
---
|
||||
|
||||
## Feature checklist
|
||||
|
||||
- [x] Session creation and lifecycle events
|
||||
- [x] Message streaming (assistant and tool messages)
|
||||
- [x] Tool call and tool result normalization
|
||||
- [x] File and image parts
|
||||
- [x] Human-in-the-loop questions
|
||||
- [x] Permission prompts and replies
|
||||
- [x] Plan approval normalization (Claude -> question)
|
||||
- [x] Event streaming over SSE
|
||||
- [ ] Persistent storage (out of scope)
|
||||
|
||||
## Normalization rules
|
||||
|
||||
- **Session ID** is always the client-provided ID.
|
||||
- **Agent session ID** is surfaced in events but never replaces the primary session ID.
|
||||
- **Tool calls** map to `UniversalMessagePart::ToolCall` and results to `ToolResult`.
|
||||
- **File and image parts** map to `AttachmentSource` with `Path`, `Url`, or base64 `Data`.
|
||||
|
||||
## Agent mode vs permission mode
|
||||
|
||||
- **agentMode**: behavior or system prompt strategy (build/plan/custom).
|
||||
- **permissionMode**: capability restrictions (default/plan/bypass).
|
||||
|
||||
These are separate concepts and must be configured independently.
|
||||
Loading…
Add table
Add a link
Reference in a new issue