chore(site): fix code block spacing and update feature grid layout

This commit is contained in:
Nicholas Kissel 2026-01-27 23:20:41 -08:00
parent 046ef71433
commit 2090508511
32 changed files with 262 additions and 103 deletions

1
.agent/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

View file

@ -0,0 +1,149 @@
---
name: Sandbox
description: Documentation and capabilities reference for Sandbox
metadata:
mintlify-proj: sandbox
version: "1.0"
---
## Capabilities
Sandbox Agent SDK provides a unified interface for orchestrating multiple coding agents within isolated sandbox environments. Agents can execute code, interact with files, handle human approvals, and stream real-time events through a standardized API. The daemon normalizes agent-specific behaviors into a universal event schema, enabling consistent multi-agent support across Claude Code, Codex, OpenCode, and Amp.
## Skills
### Session Management
- **Create sessions**: Initialize agent sessions with `POST /v1/sessions/` specifying agent type, mode, and permission settings
- **Session lifecycle**: Track session state including pending questions, permissions, and event history
- **Session configuration**: Set agent mode (build/plan/custom), permission mode (default/plan/bypass), and optional model overrides
- **Session state tracking**: Monitor session_id, agent type, agent_mode, permission_mode, model, events, pending_questions, pending_permissions, and termination status
### Message Handling
- **Send messages**: Post user messages via `POST /v1/sessions/{id}/messages` to trigger agent execution
- **Stream responses**: Use `POST /v1/sessions/{id}/messages/stream` for single-turn streaming with real-time event output
- **Message content**: Support text, tool calls, tool results, file references, images, reasoning, and status updates
- **Multi-turn conversations**: Resume sessions using agent-specific flags (--resume for Claude, --continue for Amp)
### Event Streaming
- **Poll events**: Retrieve events via `GET /v1/sessions/{id}/events` with offset/limit pagination
- **Stream events (SSE)**: Subscribe to real-time events using `GET /v1/sessions/{id}/events/sse` for Server-Sent Events
- **Event types**: Receive Message, Started, Error, QuestionAsked, PermissionAsked, and Unknown events
- **Event metadata**: Each event includes id, timestamp, session_id, agent, and structured data payload
### Human-in-the-Loop (HITL)
- **Answer questions**: Reply to agent questions via `POST /v1/sessions/{id}/questions/{id}/reply` with selected options
- **Reject questions**: Decline agent questions using `POST /v1/sessions/{id}/questions/{id}/reject`
- **Permission prompts**: Grant or deny permissions via `POST /v1/sessions/{id}/permissions/{id}/reply` with reply mode (once/always/reject)
- **Plan approval**: Normalize Claude plan approval into question events for consistent HITL workflows
### Agent Management
- **List agents**: Discover available agents with `GET /v1/agents` including installation status and versions
- **Install agents**: Install agent binaries via `POST /v1/agents/{id}/install` with auto-installation on session creation
- **Agent modes**: Query supported modes per agent using `GET /v1/agents/{id}/modes`
- **Supported agents**: Claude Code, Codex, OpenCode, Amp, and Mock agents for testing
### Content Rendering
- **Text content**: Render standard chat messages and assistant responses
- **Tool calls**: Display tool execution requests with parameters and expected results
- **Tool results**: Show tool execution outcomes and return values
- **File operations**: Preview file read/write/patch operations with file_ref content parts
- **Images**: Render image outputs from agent execution
- **Reasoning**: Display agent reasoning and planning steps when supported
- **Status updates**: Show progress indicators and execution status
### Agent Capabilities Detection
- **Capability flags**: Check agent support for tool_calls, tool_results, questions, permissions, plan_mode, reasoning, status, and item_started
- **UI affordances**: Enable/disable UI components based on agent capabilities (tool panels, approval buttons, reasoning displays)
- **Feature coverage**: Verify support for streaming, file operations, HITL workflows, and plan approval normalization
## Workflows
### Basic Chat Workflow
1. Create a session: `POST /v1/sessions/` with agent="claude", agentMode="build"
2. Send a message: `POST /v1/sessions/{id}/messages` with user prompt
3. Stream events: `GET /v1/sessions/{id}/events/sse` to receive real-time responses
4. Parse events: Extract text, tool calls, and status updates from UniversalEvent objects
5. Render UI: Display content based on event types and agent capabilities
### Tool Execution Workflow
1. Send message requesting code execution
2. Receive tool_call event with function name and parameters
3. Agent executes tool and emits tool_result event
4. Continue conversation with tool results available to agent
5. Stream continues until agent completes response
### Human Approval Workflow
1. Agent emits permissionAsked event with action requiring approval
2. Display permission prompt to user with options (once/always/reject)
3. Reply via `POST /v1/sessions/{id}/permissions/{id}/reply` with chosen mode
4. Agent resumes execution with approval decision
5. Continue streaming remaining events
### Plan-Only Execution
1. Create session with agentMode="plan" and permissionMode="plan"
2. Send message to agent
3. Receive questionAsked event with plan approval options
4. User reviews plan and replies with approval/rejection
5. Agent executes approved plan or stops based on response
### Multi-Turn Conversation
1. Create initial session and send first message
2. Stream and process all events from first turn
3. Send follow-up message to same session_id
4. Agent resumes with session history via --resume/--continue flags
5. Continue streaming new events from offset
### File-Based Workflow
1. Send message requesting file operations
2. Receive file_ref content parts showing read/write/patch previews
3. Agent executes file operations in sandbox
4. Receive tool_result events confirming changes
5. Display file diffs and confirmations to user
## Integration
### Deployment Targets
- **Local development**: Run daemon on localhost with `sandbox-agent server --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 2468`
- **Docker**: Deploy in containers with volume mounts for artifacts: `docker run -p 2468:2468 -v "$PWD/artifacts:/artifacts" ...`
- **E2B**: Run daemon inside E2B sandboxes with network access and agent binary installation
- **Daytona**: Deploy in Daytona workspaces with port forwarding to expose daemon
- **Vercel Sandboxes**: Run daemon inside Vercel Sandboxes for serverless execution
### Client Integration
- **TypeScript SDK**: Use `npm install sandbox-agent` for typed client with session and event management
- **HTTP API**: Direct REST calls with Bearer token authentication via `Authorization: Bearer <token>`
- **CLI**: Mirror HTTP API with `sandbox-agent` commands for sessions, agents, and messages
- **SSE Streaming**: Integrate Server-Sent Events for real-time event consumption
### Agent Providers
- **Claude Code**: Anthropic's coding agent with JSONL streaming and session resumption
- **Codex**: OpenAI's agent with JSON-RPC over stdio and thread-based sessions
- **OpenCode**: Multi-provider agent with SSE or JSONL streaming
- **Amp**: Sourcegraph's agent with JSONL streaming and dynamic flag detection
## Context
### Universal Event Schema
All agents emit events normalized to UniversalEvent with id, timestamp, session_id, agent, and data. The schema includes UniversalMessage (role, parts, metadata), UniversalMessagePart (text, tool_call, tool_result, file, image, reasoning, status), and HITL events (questionAsked, permissionAsked).
### Agent Architecture Patterns
Subprocess agents (Claude, Amp) spawn new processes per message with automatic termination. Server agents (Codex, OpenCode) run persistent processes with multiplexed sessions via RPC. The daemon abstracts these differences through unified session management and event conversion.
### Permission and Agent Modes
Agent mode controls behavior/system prompt strategy (build/plan/custom). Permission mode controls capability restrictions (default/plan/bypass). These are independent configurations that must be set separately during session creation.
### Session State Tracking
Sessions maintain in-memory state including full event history, pending questions/permissions, and broadcaster channels for SSE streaming. Session state is not persisted to disk; clients must implement their own storage if needed.
### Event Streaming Semantics
Events are assigned monotonically increasing IDs per session. Polling uses offset/limit pagination (offset is exclusive). SSE streaming uses the same offset semantics for resumption. New events are broadcast to all SSE subscribers immediately upon recording.
### Content Part Types
Content parts include text (chat messages), tool_call (function invocation), tool_result (execution outcome), file_ref (file operations), image (visual output), reasoning (agent planning), status (progress), and error (failures). UI rendering should branch on part.type for appropriate display.
### Agent Compatibility
Claude Code supports session resumption via --resume flag. Codex uses thread IDs for multi-turn conversations. OpenCode discovers modes via server API. Amp uses --continue flag for resumption. Mock agents are built-in for testing without external dependencies.
---
> For additional documentation and navigation, see: https://sandboxagent.dev/docs/llms.txt

1
.claude/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.cline/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.codex/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.commandcode/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.continue/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.crush/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.cursor/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.factory/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.gemini/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.github/skills/sandbox vendored Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.goose/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.kilocode/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.kiro/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.mcpjam/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.neovate/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.opencode/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.openhands/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.pi/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.qoder/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.qwen/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.roo/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.trae/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.windsurf/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

1
.zencoder/skills/sandbox Symbolic link
View file

@ -0,0 +1 @@
../../.agents/skills/sandbox

View file

@ -0,0 +1 @@
[["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.16.15","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true,\"allowedDomains\":[]},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false,\"failOnPrerenderConflict\":false,\"svgo\":false},\"legacy\":{\"collections\":false}}"]

View file

@ -0,0 +1,5 @@
{
"_variables": {
"lastUpdateCheck": 1769576078224
}
}

View file

@ -1,2 +1 @@
/// <reference types="astro/client" />
/// <reference path="content.d.ts" />

View file

@ -42,12 +42,11 @@ export function FeatureGrid() {
<section id="features" className="relative overflow-hidden border-t border-white/5 py-32">
<div className="relative z-10 mx-auto max-w-7xl px-6">
<div className="mb-16">
<h2 className="mb-6 text-3xl font-medium tracking-tight text-white md:text-5xl">
Full feature coverage. <br />
<span className="text-zinc-500">Available as an HTTP API or TypeScript SDK.</span>
<h2 className="mb-4 text-3xl font-medium tracking-tight text-white md:text-5xl">
Full feature coverage.
</h2>
<p className="text-lg leading-relaxed text-zinc-400">
Everything you need to integrate coding agents in record time.
Available as an HTTP API or TypeScript SDK.
</p>
</div>

View file

@ -122,12 +122,12 @@ export function GetStarted() {
</div>
</div>
<p className="relative z-10 mb-4 text-sm leading-relaxed text-zinc-400">
<p className="relative z-10 mb-4 text-sm leading-relaxed text-zinc-400 min-h-[4.5rem]">
Import the TypeScript SDK directly into your Node or browser application. Full type safety and streaming support.
</p>
<div className="relative z-10 mt-auto">
<div className="overflow-hidden rounded-lg border border-white/5 bg-black/50">
<div className="relative z-10 flex-1 flex flex-col">
<div className="overflow-hidden rounded-lg border border-white/5 bg-black/50 flex-1 flex flex-col">
<div className="flex items-center justify-between border-b border-white/5 bg-white/5 px-3 py-2">
<span className="text-[10px] font-medium text-zinc-500">example.ts</span>
<CopyButton text={sdkCodeRaw} />
@ -153,26 +153,27 @@ export function GetStarted() {
</div>
</div>
<p className="relative z-10 mb-4 text-sm leading-relaxed text-zinc-400">
<p className="relative z-10 mb-4 text-sm leading-relaxed text-zinc-400 min-h-[4.5rem]">
Run as an HTTP server and connect from any language. Deploy to E2B, Daytona, Vercel, or your own infrastructure.
</p>
<div className="relative z-10 mt-auto">
<div className="overflow-hidden rounded-lg border border-white/5 bg-black/50 p-3">
<div className="flex items-start justify-between gap-2">
<pre className="font-mono text-[11px] leading-relaxed overflow-x-auto">
<code>
<span className="text-zinc-500">$ </span>
<span className="text-zinc-300">curl -fsSL \</span>
{"\n"}
<span className="text-zinc-300">{" "}</span>
<span className="text-green-400">https://releases.rivet.dev/sandbox-agent/latest/install.sh</span>
<span className="text-zinc-300"> | </span>
<span className="text-blue-400">sh</span>
</code>
</pre>
<div className="relative z-10 flex-1 flex flex-col">
<div className="overflow-hidden rounded-lg border border-white/5 bg-black/50 flex-1 flex flex-col">
<div className="flex items-center justify-between border-b border-white/5 bg-white/5 px-3 py-2">
<span className="text-[10px] font-medium text-zinc-500">terminal</span>
<CopyButton text={sandboxCommand} />
</div>
<pre className="overflow-x-auto p-3 font-mono text-[11px] leading-relaxed flex-1">
<code>
<span className="text-zinc-500">$ </span>
<span className="text-zinc-300">curl -fsSL \</span>
{"\n"}
<span className="text-zinc-300">{" "}</span>
<span className="text-green-400">https://releases.rivet.dev/sandbox-agent/latest/install.sh</span>
<span className="text-zinc-300"> | </span>
<span className="text-blue-400">sh</span>
</code>
</pre>
</div>
</div>
</div>
@ -193,31 +194,32 @@ export function GetStarted() {
</div>
</div>
<p className="relative z-10 mb-4 text-sm leading-relaxed text-zinc-400">
<p className="relative z-10 mb-4 text-sm leading-relaxed text-zinc-400 min-h-[4.5rem]">
Clone the repo and build with Cargo. Customize, contribute, or embed directly in your Rust project.
</p>
<div className="relative z-10 mt-auto">
<div className="overflow-hidden rounded-lg border border-white/5 bg-black/50 p-3">
<div className="flex items-start justify-between gap-2">
<pre className="font-mono text-[11px] leading-relaxed overflow-x-auto">
<code>
<span className="text-zinc-500">$ </span>
<span className="text-blue-400">git clone</span>
<span className="text-zinc-300"> </span>
<span className="text-green-400">https://github.com/rivet-dev/sandbox-agent</span>
{"\n"}
<span className="text-zinc-500">$ </span>
<span className="text-blue-400">cd</span>
<span className="text-zinc-300"> sandbox-agent</span>
{"\n"}
<span className="text-zinc-500">$ </span>
<span className="text-blue-400">cargo run</span>
<span className="text-zinc-300"> -p sandbox-agent --release</span>
</code>
</pre>
<div className="relative z-10 flex-1 flex flex-col">
<div className="overflow-hidden rounded-lg border border-white/5 bg-black/50 flex-1 flex flex-col">
<div className="flex items-center justify-between border-b border-white/5 bg-white/5 px-3 py-2">
<span className="text-[10px] font-medium text-zinc-500">terminal</span>
<CopyButton text={sourceCommands} />
</div>
<pre className="overflow-x-auto p-3 font-mono text-[11px] leading-relaxed flex-1">
<code>
<span className="text-zinc-500">$ </span>
<span className="text-blue-400">git clone</span>
<span className="text-zinc-300"> </span>
<span className="text-green-400">https://github.com/rivet-dev/sandbox-agent</span>
{"\n"}
<span className="text-zinc-500">$ </span>
<span className="text-blue-400">cd</span>
<span className="text-zinc-300"> sandbox-agent</span>
{"\n"}
<span className="text-zinc-500">$ </span>
<span className="text-blue-400">cargo run</span>
<span className="text-zinc-300"> -p sandbox-agent --release</span>
</code>
</pre>
</div>
</div>
</div>

View file

@ -66,77 +66,65 @@ export function Hero() {
</div>
<div className="font-mono text-xs text-zinc-500">example_agent.ts</div>
</div>
<div className="overflow-x-auto p-6 font-mono text-sm leading-relaxed">
<CodeLine num="01">
<pre className="overflow-x-auto p-6 font-mono text-sm leading-relaxed">
<code>
<span className="text-purple-400">const</span>
<span className="text-white"> agents = </span>
<span className="text-zinc-300"> agents = </span>
<span className="text-purple-400">await</span>
<span className="text-white"> client.</span>
<span className="text-zinc-300"> client.</span>
<span className="text-blue-400">listAgents</span>
<span className="text-white">();</span>
</CodeLine>
<div className="h-4" />
<CodeLine num="02">
<span className="text-zinc-300">();</span>
{"\n\n"}
<span className="text-purple-400">await</span>
<span className="text-white"> client.</span>
<span className="text-zinc-300"> client.</span>
<span className="text-blue-400">createSession</span>
<span className="text-white">(</span>
<span className="text-zinc-300">(</span>
<span className="text-green-400">"demo"</span>
<span className="text-white">{", {"}</span>
</CodeLine>
<CodeLine num="03">
<span className="text-white">{" agent: "}</span>
<span className="text-zinc-300">{", {"}</span>
{"\n"}
<span className="text-zinc-300">{" agent: "}</span>
<span className="text-green-400">"codex"</span>
<span className="text-white">,</span>
</CodeLine>
<CodeLine num="04">
<span className="text-white">{" agentMode: "}</span>
<span className="text-zinc-300">,</span>
{"\n"}
<span className="text-zinc-300">{" agentMode: "}</span>
<span className="text-green-400">"default"</span>
<span className="text-white">,</span>
</CodeLine>
<CodeLine num="05">
<span className="text-white">{" permissionMode: "}</span>
<span className="text-zinc-300">,</span>
{"\n"}
<span className="text-zinc-300">{" permissionMode: "}</span>
<span className="text-green-400">"plan"</span>
<span className="text-white">,</span>
</CodeLine>
<CodeLine num="06">
<span className="text-white">{"});"}</span>
</CodeLine>
<div className="h-4" />
<CodeLine num="07">
<span className="text-zinc-300">,</span>
{"\n"}
<span className="text-zinc-300">{"});"}</span>
{"\n\n"}
<span className="text-purple-400">await</span>
<span className="text-white"> client.</span>
<span className="text-zinc-300"> client.</span>
<span className="text-blue-400">postMessage</span>
<span className="text-white">(</span>
<span className="text-zinc-300">(</span>
<span className="text-green-400">"demo"</span>
<span className="text-white">{", { message: "}</span>
<span className="text-zinc-300">{", { message: "}</span>
<span className="text-green-400">"Hello from the SDK."</span>
<span className="text-white">{" });"}</span>
</CodeLine>
<div className="h-4" />
<CodeLine num="08">
<span className="text-zinc-300">{" });"}</span>
{"\n\n"}
<span className="text-purple-400">for await</span>
<span className="text-white"> (</span>
<span className="text-zinc-300"> (</span>
<span className="text-purple-400">const</span>
<span className="text-white"> event </span>
<span className="text-zinc-300"> event </span>
<span className="text-purple-400">of</span>
<span className="text-white"> client.</span>
<span className="text-zinc-300"> client.</span>
<span className="text-blue-400">streamEvents</span>
<span className="text-white">(</span>
<span className="text-zinc-300">(</span>
<span className="text-green-400">"demo"</span>
<span className="text-white">{", { offset: "}</span>
<span className="text-zinc-300">{", { offset: "}</span>
<span className="text-amber-400">0</span>
<span className="text-white">{" })) {"}</span>
</CodeLine>
<CodeLine num="09">
<span className="text-white">{" console."}</span>
<span className="text-zinc-300">{" })) {"}</span>
{"\n"}
<span className="text-zinc-300">{" console."}</span>
<span className="text-blue-400">log</span>
<span className="text-white">(event.type, event.data);</span>
</CodeLine>
<CodeLine num="10">
<span className="text-white">{"}"}</span>
</CodeLine>
</div>
<span className="text-zinc-300">(event.type, event.data);</span>
{"\n"}
<span className="text-zinc-300">{"}"}</span>
</code>
</pre>
</div>
</div>
</div>
@ -146,12 +134,3 @@ export function Hero() {
);
}
function CodeLine({ num, children }: { num: string; children: React.ReactNode }) {
return (
<div className="flex gap-4 whitespace-nowrap">
<span className="text-zinc-600 select-none">{num}</span>
{children}
</div>
);
}