mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 22:03:48 +00:00
* remove website .astro * fix default origin * docs: comprehensive documentation overhaul - Add quickstart with multi-platform examples (E2B, Daytona, Docker, local) - Add environment variables setup with platform-specific tabs - Add Python SDK page (coming soon) - Add local deployment guide - Update E2B/Daytona/Docker guides with TypeScript examples - Configure OpenAPI auto-generation for API reference - Add CORS configuration guide - Update manage-sessions with Rivet Actors examples - Fix SDK method names and URLs throughout - Add icons to main documentation pages - Remove outdated universal-api and http-api pages * docs: add universal schema and agent compatibility docs - Create universal-schema.mdx with full event/item schema reference - Create agent-compatibility.mdx mirroring README feature matrix - Rename glossary.md to universal-schema.mdx - Update CLAUDE.md with sync requirements for new docs - Add links in README to building-chat-ui, manage-sessions, universal-schema - Fix CLI docs link (rivet.dev -> sandboxagent.dev) * docs: add inspector page and daytona network limits warning
291 lines
8.2 KiB
Text
291 lines
8.2 KiB
Text
---
|
|
title: "Universal Schema"
|
|
description: "Reference for the universal event and item schema."
|
|
icon: "brackets-curly"
|
|
---
|
|
|
|
The universal schema normalizes events from all supported agents (Claude Code, Codex, OpenCode, Amp) into a consistent format. This lets you build UIs and persistence layers that work with any agent without special-casing.
|
|
|
|
The schema is defined in [OpenAPI format](https://github.com/rivet-dev/sandbox-agent/blob/main/docs/openapi.json). See the [HTTP API Reference](/api-reference) for endpoint documentation.
|
|
|
|
## UniversalEvent
|
|
|
|
Every event from the API is wrapped in a `UniversalEvent` envelope.
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `event_id` | string | Unique identifier for this event |
|
|
| `sequence` | integer | Monotonic sequence number within the session (starts at 1) |
|
|
| `time` | string | RFC3339 timestamp |
|
|
| `session_id` | string | Daemon-generated session identifier |
|
|
| `native_session_id` | string? | Provider-native session/thread identifier (e.g., Codex `threadId`, OpenCode `sessionID`) |
|
|
| `source` | string | Event origin: `agent` (native) or `daemon` (synthetic) |
|
|
| `synthetic` | boolean | Whether this event was generated by the daemon to fill gaps |
|
|
| `type` | string | Event type (see [Event Types](#event-types)) |
|
|
| `data` | object | Event-specific payload |
|
|
| `raw` | any? | Original provider payload (only when `include_raw=true`) |
|
|
|
|
```json
|
|
{
|
|
"event_id": "evt_abc123",
|
|
"sequence": 1,
|
|
"time": "2025-01-28T12:00:00Z",
|
|
"session_id": "my-session",
|
|
"native_session_id": "thread_xyz",
|
|
"source": "agent",
|
|
"synthetic": false,
|
|
"type": "item.completed",
|
|
"data": { ... }
|
|
}
|
|
```
|
|
|
|
## Event Types
|
|
|
|
### Session Lifecycle
|
|
|
|
| Type | Description | Data |
|
|
|------|-------------|------|
|
|
| `session.started` | Session has started | `{ metadata?: any }` |
|
|
| `session.ended` | Session has ended | `{ reason, terminated_by }` |
|
|
|
|
**SessionEndedData**
|
|
|
|
| Field | Type | Values |
|
|
|-------|------|--------|
|
|
| `reason` | string | `completed`, `error`, `terminated` |
|
|
| `terminated_by` | string | `agent`, `daemon` |
|
|
|
|
### Item Lifecycle
|
|
|
|
| Type | Description | Data |
|
|
|------|-------------|------|
|
|
| `item.started` | Item creation | `{ item }` |
|
|
| `item.delta` | Streaming content delta | `{ item_id, native_item_id?, delta }` |
|
|
| `item.completed` | Item finalized | `{ item }` |
|
|
|
|
Items follow a consistent lifecycle: `item.started` → `item.delta` (0 or more) → `item.completed`.
|
|
|
|
### HITL (Human-in-the-Loop)
|
|
|
|
| Type | Description | Data |
|
|
|------|-------------|------|
|
|
| `permission.requested` | Permission request pending | `{ permission_id, action, status, metadata? }` |
|
|
| `permission.resolved` | Permission granted or denied | `{ permission_id, action, status, metadata? }` |
|
|
| `question.requested` | Question pending user input | `{ question_id, prompt, options, status }` |
|
|
| `question.resolved` | Question answered or rejected | `{ question_id, prompt, options, status, response? }` |
|
|
|
|
**PermissionEventData**
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `permission_id` | string | Identifier for the permission request |
|
|
| `action` | string | What the agent wants to do |
|
|
| `status` | string | `requested`, `approved`, `denied` |
|
|
| `metadata` | any? | Additional context |
|
|
|
|
**QuestionEventData**
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `question_id` | string | Identifier for the question |
|
|
| `prompt` | string | Question text |
|
|
| `options` | string[] | Available answer options |
|
|
| `status` | string | `requested`, `answered`, `rejected` |
|
|
| `response` | string? | Selected answer (when resolved) |
|
|
|
|
### Errors
|
|
|
|
| Type | Description | Data |
|
|
|------|-------------|------|
|
|
| `error` | Runtime error | `{ message, code?, details? }` |
|
|
| `agent.unparsed` | Parse failure | `{ error, location, raw_hash? }` |
|
|
|
|
The `agent.unparsed` event indicates the daemon failed to parse an agent payload. This should be treated as a bug.
|
|
|
|
## UniversalItem
|
|
|
|
Items represent discrete units of content within a session.
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `item_id` | string | Daemon-generated identifier |
|
|
| `native_item_id` | string? | Provider-native item/message identifier |
|
|
| `parent_id` | string? | Parent item ID (e.g., tool call/result parented to a message) |
|
|
| `kind` | string | Item category (see below) |
|
|
| `role` | string? | Actor role for message items |
|
|
| `status` | string | Lifecycle status |
|
|
| `content` | ContentPart[] | Ordered list of content parts |
|
|
|
|
### ItemKind
|
|
|
|
| Value | Description |
|
|
|-------|-------------|
|
|
| `message` | User or assistant message |
|
|
| `tool_call` | Tool invocation |
|
|
| `tool_result` | Tool execution result |
|
|
| `system` | System message |
|
|
| `status` | Status update |
|
|
| `unknown` | Unrecognized item type |
|
|
|
|
### ItemRole
|
|
|
|
| Value | Description |
|
|
|-------|-------------|
|
|
| `user` | User message |
|
|
| `assistant` | Assistant response |
|
|
| `system` | System prompt |
|
|
| `tool` | Tool-related message |
|
|
|
|
### ItemStatus
|
|
|
|
| Value | Description |
|
|
|-------|-------------|
|
|
| `in_progress` | Item is streaming or pending |
|
|
| `completed` | Item is finalized |
|
|
| `failed` | Item execution failed |
|
|
|
|
## Content Parts
|
|
|
|
The `content` array contains typed parts that make up an item's payload.
|
|
|
|
### text
|
|
|
|
Plain text content.
|
|
|
|
```json
|
|
{ "type": "text", "text": "Hello, world!" }
|
|
```
|
|
|
|
### json
|
|
|
|
Structured JSON content.
|
|
|
|
```json
|
|
{ "type": "json", "json": { "key": "value" } }
|
|
```
|
|
|
|
### tool_call
|
|
|
|
Tool invocation.
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `name` | string | Tool name |
|
|
| `arguments` | string | JSON-encoded arguments |
|
|
| `call_id` | string | Unique call identifier |
|
|
|
|
```json
|
|
{
|
|
"type": "tool_call",
|
|
"name": "read_file",
|
|
"arguments": "{\"path\": \"/src/main.ts\"}",
|
|
"call_id": "call_abc123"
|
|
}
|
|
```
|
|
|
|
### tool_result
|
|
|
|
Tool execution result.
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `call_id` | string | Matching call identifier |
|
|
| `output` | string | Tool output |
|
|
|
|
```json
|
|
{
|
|
"type": "tool_result",
|
|
"call_id": "call_abc123",
|
|
"output": "File contents here..."
|
|
}
|
|
```
|
|
|
|
### file_ref
|
|
|
|
File reference with optional diff.
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `path` | string | File path |
|
|
| `action` | string | `read`, `write`, `patch` |
|
|
| `diff` | string? | Unified diff (for patches) |
|
|
|
|
```json
|
|
{
|
|
"type": "file_ref",
|
|
"path": "/src/main.ts",
|
|
"action": "write",
|
|
"diff": "@@ -1,3 +1,4 @@\n+import { foo } from 'bar';"
|
|
}
|
|
```
|
|
|
|
### image
|
|
|
|
Image reference.
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `path` | string | Image file path |
|
|
| `mime` | string? | MIME type |
|
|
|
|
```json
|
|
{ "type": "image", "path": "/tmp/screenshot.png", "mime": "image/png" }
|
|
```
|
|
|
|
### reasoning
|
|
|
|
Model reasoning/thinking content.
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `text` | string | Reasoning text |
|
|
| `visibility` | string | `public` or `private` |
|
|
|
|
```json
|
|
{ "type": "reasoning", "text": "Let me think about this...", "visibility": "public" }
|
|
```
|
|
|
|
### status
|
|
|
|
Status indicator.
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `label` | string | Status label |
|
|
| `detail` | string? | Additional detail |
|
|
|
|
```json
|
|
{ "type": "status", "label": "Running tests", "detail": "3 of 10 passed" }
|
|
```
|
|
|
|
## Source & Synthetics
|
|
|
|
### EventSource
|
|
|
|
The `source` field indicates who emitted the event:
|
|
|
|
| Value | Description |
|
|
|-------|-------------|
|
|
| `agent` | Native event from the agent |
|
|
| `daemon` | Synthetic event generated by the daemon |
|
|
|
|
### Synthetic Events
|
|
|
|
The daemon emits synthetic events (`synthetic: true`, `source: "daemon"`) to provide a consistent event stream across all agents. Common synthetics:
|
|
|
|
| Synthetic | When |
|
|
|-----------|------|
|
|
| `session.started` | Agent doesn't emit explicit session start |
|
|
| `session.ended` | Agent doesn't emit explicit session end |
|
|
| `item.started` | Agent doesn't emit item start events |
|
|
| `item.delta` | Agent doesn't stream deltas natively |
|
|
| `question.*` | Claude Code plan mode (from ExitPlanMode tool) |
|
|
|
|
### Raw Payloads
|
|
|
|
Pass `include_raw=true` to event endpoints to receive the original agent payload in the `raw` field. Useful for debugging or accessing agent-specific data not in the universal schema.
|
|
|
|
```typescript
|
|
const events = await client.getEvents("my-session", { includeRaw: true });
|
|
// events[0].raw contains the original agent payload
|
|
```
|