sandbox-agent/research/acp/spec.md
2026-02-11 14:47:41 +00:00

15 KiB

V2 Spec: ACP Over HTTP

0) Delete/Remove First

Before implementing v2, remove in-house protocol files and remove v1 API behavior as documented in:

  • research/acp/00-delete-first.md
  • research/acp/v1-schema-to-acp-mapping.md (endpoint/event-by-event conversion target)

This is mandatory to prevent dual-protocol drift.

1) Goals

  • v2 is intentionally breaking and ACP-native.
  • Internal runtime uses ACP end-to-end (no custom universal event schema).
  • Existing agent managers are replaced with ACP agent process runtimes.
  • v1 API is completely removed; all /v1/* requests return explicit removed errors.
  • OpenCode <-> ACP support is preserved as a product requirement, but implemented in a separate step after ACP core is stable.

2) Non-goals for first v2 cut

  • No guarantee of v1 endpoint compatibility.
  • No v1 compatibility layer in the initial v2 release.
  • No OpenCode compatibility during ACP core bring-up (/opencode/* is disabled until the dedicated bridge step).
  • No in-house universal event format.

3) Protocol baseline

Use ACP v1 schema from:

  • ~/misc/acp-docs/schema/schema.json
  • ~/misc/acp-docs/schema/meta.json
  • research/acp/v1-schema-to-acp-mapping.md (required for preserving v1 feature coverage during migration)

Supported agent methods (minimum):

  • initialize, authenticate (if needed), session/new, session/prompt, session/cancel

Supported client methods (minimum):

  • session/request_permission

Included unstable ACP methods for v2 profile:

  • session/list
  • session/fork
  • session/resume
  • session/set_model
  • $/cancel_request

Phase-1 optional methods (still optional per agent process capability):

  • fs/read_text_file, fs/write_text_file
  • terminal/*
  • session/load, session/set_mode, session/set_config_option

Sandbox Agent ACP extension methods currently implemented:

  • _sandboxagent/session/detach
  • _sandboxagent/session/list_models
  • _sandboxagent/session/set_metadata
  • _sandboxagent/session/request_question (agent -> client request pattern)
  • _sandboxagent/session/terminate
  • _sandboxagent/session/ended (runtime -> client notification)

4) Transport: ACP over HTTP (repo-specific draft)

ACP streamable HTTP is draft upstream, so this spec defines a concrete transport that stays close to current ACP transport guidance and JSON-RPC semantics.

4.1 Endpoints

  • POST /v2/rpc
  • GET /v2/rpc (SSE stream, Accept: text/event-stream)
  • DELETE /v2/rpc (explicit connection close)

4.2 Connection model

  • Each ACP HTTP connection maps to a logical client connection id (X-ACP-Connection-Id).
  • Agent processes are shared per AgentId (one backend process per agent type on a server), not per HTTP connection.
  • Session inventory is server-global in memory across connections; session/list returns this aggregated inventory.
  • Connection identity is X-ACP-Connection-Id header.
  • First initialize request may omit X-ACP-Connection-Id and must include params._meta["sandboxagent.dev"].agent.
  • Server ensures backend exists for that agent, creates connection, returns X-ACP-Connection-Id in response headers.
  • All subsequent POST /v2/rpc and GET /v2/rpc requests must include X-ACP-Connection-Id.
  • DELETE /v2/rpc with X-ACP-Connection-Id detaches/closes only the transport connection and releases connection-scoped resources.
  • DELETE /v2/rpc does not terminate the session or agent process. Session termination is explicit via _sandboxagent/session/terminate.

4.3 Message routing

  • Client -> agent requests/notifications: sent as JSON-RPC payloads to POST /v2/rpc.
  • Agent -> client notifications/requests: delivered on GET /v2/rpc SSE stream as JSON-RPC envelopes.
  • Client replies to agent-initiated requests by POSTing JSON-RPC responses to POST /v2/rpc.

4.4 SSE framing

  • event: message
  • id: <monotonic-sequence>
  • data: <single JSON-RPC object>

Keepalive:

  • SSE comment heartbeat every 15s.

Resume:

  • Last-Event-ID accepted for best-effort replay from in-memory ring buffer.

4.5 HTTP status and errors

  • JSON-RPC request success: HTTP 200 with JSON-RPC response object.
  • JSON-RPC notification accepted: HTTP 202, empty body.
  • Invalid envelope: HTTP 400 with application/problem+json.
  • Unknown connection: HTTP 404 with application/problem+json.
  • Server timeout waiting on agent process response: HTTP 504 with application/problem+json.
  • Successful DELETE /v2/rpc: HTTP 204.
  • Repeated DELETE /v2/rpc on an already-closed connection: HTTP 204 (idempotent close).
  • All /v1/* endpoints: HTTP 410 with application/problem+json and message v1 API removed; use /v2.

Note: ACP method-level failures still return JSON-RPC error objects inside 200 responses.

4.6 Ordering and concurrency

  • Per-connection outbound SSE order is preserved.
  • JSON-RPC id is opaque and passed through unchanged.
  • Multiple in-flight requests are allowed.

4.7 Security

  • Reuse existing bearer token auth middleware.
  • Validate bearer auth at request time for /v2/* routes when configured.
  • ACP runtime connection ids are in-memory server ids and are not additionally principal-scoped inside runtime.
  • Do not expose agent process stderr on stdout channel.

4.8 Field research alignment (2026-02-10)

Based on current ACP community implementations/discussion:

  • Streamable HTTP and WebSocket are both being piloted.
  • Streamable HTTP implementations are converging on MCP-like request patterns while keeping ACP JSON-RPC payloads.
  • WebSocket implementations report simpler handling for bidirectional/server-initiated ACP traffic.

Decision for this repo:

  • v2 public transport remains Streamable HTTP (POST/GET SSE over /v2/rpc) as the canonical contract.
  • WebSocket transport is not part of initial v2 surface; consider later only if HTTP profile proves insufficient operationally.

Reference:

  • research/acp/acp-over-http-findings.md

5) Agent process runtime and install model

5.1 Runtime

Replace custom per-agent protocol parsers with one ACP agent process process contract:

  • Spawn ACP agent process binary (stdio JSON-RPC).
  • Bridge stdio <-> internal ACP client dispatcher.
  • No agent-specific JSON parsing in server core.

5.2 Installers

Current auto-installer installs native CLIs. v2 installer must install:

  • native agent binary (if needed by agent process)
  • ACP agent process binary required for that agent

Add a manifest-driven mapping (new file to create in implementation phase):

  • claude: agent process claude-code-acp
  • codex: agent process codex-acp
  • opencode: native ACP mode (agent process optional)
  • amp: pending decision (official agent process required or unsupported in v2 initial release)

5.3 ACP Registry install instructions

Yes, this must be handled.

V2 installer/docs must include install instructions sourced from ACP registry metadata where available, with explicit fallback for non-registry agent processes.

Requirements:

  • Maintain a local agent process manifest with:
    • registry slug (if present)
    • agent process package/repo source
    • native agent dependency
    • supported platform matrix
    • install verification command
  • Prefer ACP registry source of truth when agent process is published there.
  • If agent process is not in registry, use pinned fallback source and mark as non_registry.
  • Support SANDBOX_AGENT_ACP_REGISTRY_URL override for controlled/test environments.
  • Generate user-facing install instructions from this manifest (do not hand-maintain per-agent docs).
  • Expose install provenance in API/CLI (registry vs fallback).

Output surfaces:

  • GET /v2/agents: include agent process install source + verification status.
  • POST /v2/agents/{agent}/install: return concrete installed artifacts and source provenance.

5.4 Install commands and lazy agent process install

This must match current ergonomics where installs can be explicit or automatic.

Explicit install interfaces:

  • API: POST /v2/agents/{agent}/install
  • CLI (v2 surface): sandbox-agent api v2 agents install <agent> [--reinstall] [--agent-version <v>] [--agent process-version <v>]

Lazy install behavior (default on):

  • Trigger point: first ACP bootstrap request (initialize) on /v2/rpc with params._meta["sandboxagent.dev"].agent.
  • If required binaries are missing, server installs:
    • ACP agent process
    • native agent binary if agent process requires it
  • Then server starts the agent process process and continues normal ACP handshake.

Operational requirements:

  • Per-agent install lock to prevent duplicate concurrent downloads.
  • Idempotent install response when artifacts already exist.
  • Clear provenance in result (registry vs fallback) plus concrete artifact versions.
  • Config switch to disable lazy install (require_preinstall=true) for controlled environments.

6) Public v2 API shape

Expose ACP directly, not custom session endpoints.

  • POST /v2/rpc: transport write path
  • GET /v2/rpc: transport read path (SSE)

Non-ACP endpoints retained in v2:

  • GET /v2/health
  • GET /v2/agents (capabilities + install status)
  • POST /v2/agents/{agent}/install
  • GET /v2/sessions
  • GET /v2/sessions/{id}
  • GET /v2/fs/file
  • PUT /v2/fs/file
  • POST /v2/fs/upload-batch
  • GET /ui/ (Inspector UI shell)

Agent discovery note:

  • Do not add standalone /v2/agents/{agent}/models or /v2/agents/{agent}/modes endpoints.
  • Expose optional models/modes properties on agent response payloads when the agent is installed.

Legacy endpoints retained only as removals:

  • ALL /v1/* return HTTP 410 with a stable "v1 removed" error body.
  • /opencode/* is commented out/disabled until Phase 7 and is expected to be broken during ACP core bring-up.

Everything related to prompting/sessions/permissions/tools happens through ACP JSON-RPC messages.

6.3 Filesystem Boundary (Intentional)

Sandbox Agent keeps a separate host-owned filesystem API from ACP native filesystem methods.

Rationale:

  • ACP fs/* methods are agent-protocol capabilities and can vary by agent implementation.
  • Sandbox Agent filesystem HTTP endpoints are host/runtime capabilities and should behave consistently across all agents.
  • Large binary transfers (raw file read/write and tar upload) need streaming-friendly HTTP behavior; ACP JSON-RPC envelopes are not suitable for super-large binary payload transport.
  • GET /v2/fs/file specifically benefits from HTTP response streaming for large reads.

For this reason, GET /v2/fs/file, PUT /v2/fs/file, and POST /v2/fs/upload-batch remain dedicated HTTP endpoints even as other static control APIs migrate to ACP extensions.

Parallel ACP compatibility is still supported:

  • Keep ACP extension variants in parallel for these operations.
  • ACP and HTTP variants should call into the same underlying filesystem service logic so behavior remains consistent.
  • ACP variants are not intended for very large file transfer; SDK defaults should prefer HTTP for these methods.

6.1 TypeScript SDK integration (mandatory)

Use the existing ACP TypeScript SDK (@agentclientprotocol/sdk) inside our SDK implementation.

Rules:

  • Do not build a second in-house ACP protocol implementation in sdks/typescript.
  • Wrap and embed ACP SDK primitives (ClientSideConnection/transport handling) in our SDK surface.
  • Implement our own ACP-over-HTTP transport agent process for the SDK because the official ACP client SDK does not currently provide our required Streamable HTTP client behavior out of the box.
  • Keep our SDK focused on:
    • auth/token handling
    • endpoint/bootstrap convenience
    • spawn/embedded server ergonomics
    • product-specific helper APIs
  • ACP message framing, JSON-RPC lifecycle, and protocol object modeling should come from upstream ACP SDK.

6.2 Inspector (mandatory)

The inspector must be ACP-native in v2.

  • Replace v1 session/event calls in inspector with ACP-over-HTTP connection flow (initialize, session/new, session/prompt, streamed session/update).
  • Add inspector support for rendering raw ACP envelopes and decoded session updates.
  • Keep inspector route at /ui/; remove dependency on v1 REST session endpoints.
  • Inspector end-to-end verification is mandatory via agent-browser automation (not only unit/integration tests).

7) Data model changes (breaking)

Removed from public contract:

  • UniversalEvent
  • UniversalItem
  • custom permission.reply and question.reply REST endpoints
  • v1 sessions/* REST resources

Added:

  • raw ACP JSON-RPC envelopes over HTTP
  • explicit connection identity (X-ACP-Connection-Id)

8) Test contract for v2

Consolidated must-have suites (duplicates collapsed):

  • ACP protocol conformance (JSON-RPC + ACP schema/semantics)
  • Transport contract (/v2/rpc POST/SSE routing, ordering, replay, errors)
  • End-to-end agent process matrix (includes core turn flow, cancel, HITL, streaming)
  • Installer suite (explicit + lazy install, registry/fallback provenance)
  • Security/auth isolation
  • TypeScript SDK end-to-end (embedded + server mode, embedding @agentclientprotocol/sdk)
  • v1 removal contract suite (/v1/* => HTTP 410 + stable error payload)
  • Inspector ACP suite executed with agent-browser (ACP session flow + streaming render correctness)
  • OpenCode <-> ACP bridge suite (dedicated later phase)

No synthetic protocol fixtures. Use real agent processes in integration tests.

Minimum required agent-browser inspector coverage:

  1. Open /ui/, spawn an agent/session, send one message, and verify a response is rendered.

Current automation entrypoint:

  • frontend/packages/inspector/tests/agent-browser.e2e.sh
  • server/packages/sandbox-agent/tests/v2_agent_process_matrix.rs (deterministic agent process matrix smoke + JSON-RPC conformance checks)

9) Open questions to resolve before implementation lock

  • Amp agent process availability and support level for v2 launch.
  • Whether additional non-binary filesystem endpoints remain HTTP or migrate to ACP extensions after initial cut.

10) Deferred Dedicated Step: OpenCode <-> ACP

  • During ACP core implementation, /opencode/* is commented out/disabled.
  • After ACP core is stable, complete the dedicated OpenCode <-> ACP bridge step and re-enable /opencode/*.
  • Mark the step complete only after dedicated integration tests pass.

11) Companion Docs

  • research/acp/v1-schema-to-acp-mapping.md (normative 1:1 endpoint/event mapping)
  • research/acp/migration-steps.md (execution order and rollout steps)
  • research/acp/todo.md (phase checklist and validation tracker)
  • research/acp/acp-over-http-findings.md (community transport findings and decision context)
  • research/acp/friction.md (ongoing issue/decision log)
  • docs/quickstart.mdx, docs/cli.mdx, docs/sdks/typescript.mdx (external migration and rollout guidance)

12) Documentation Updates (mandatory)

When implementing this spec, update docs in the same change set:

  • API reference/openapi docs for v2 and /v1/* removal semantics
  • docs/cli.mdx for v2 ACP and removed v1 commands
  • docs/inspector.mdx for ACP-based inspector behavior
  • SDK docs (docs/sdks/typescript.mdx) for ACP-over-HTTP transport usage
  • Any OpenCode compatibility docs that reference /opencode/*