This document explains what opencode-a2a is responsible for, what remains inside OpenCode, and how requests move through the adapter boundary.
opencode-a2a is an adapter layer between A2A clients and an OpenCode runtime.
It is responsible for:
- exposing A2A-facing HTTP+JSON and JSON-RPC endpoints
- normalizing transport, streaming, session, and interrupt contracts
- applying authentication, logging, persistence, and deployment-side guardrails
- hosting an outbound A2A client for peer calls triggered by CLI usage or
a2a_call
It is not responsible for:
- replacing OpenCode's own provider or model selection internals
- hard multi-tenant isolation inside one shared deployment by default
- acting as a general OpenCode process supervisor
flowchart LR
Client["A2A Client / Hub / Gateway"] --> Gateway["opencode-a2a"]
Gateway --> Contracts["A2A contracts\ntransport/session/interrupt"]
Gateway --> Ops["Auth / logging / persistence / deployment boundary"]
Contracts --> OpenCode["OpenCode runtime"]
Ops --> OpenCode
Gateway --> Peer["Embedded outbound A2A client"]
This view emphasizes service responsibility boundaries rather than internal module structure. The root README keeps the overview path for first-time readers, while maintainer-architecture.md covers module boundaries and request call chains for contributors.
- A client calls the REST or JSON-RPC endpoint.
- FastAPI middleware validates auth, request size, protocol version, and logging policy.
- The adapter maps transport payloads into the OpenCode-facing execution path.
- The execution layer calls the upstream OpenCode runtime and consumes its stream or unary response.
- The service maps the result back into shared A2A-facing task, message, and stream event contracts.
For streaming requests, the adapter does more than simple passthrough:
- classifies stream blocks into shared types such as
text,reasoning, andtool_call - preserves stable event and message identity where possible
- emits shared interrupt lifecycle state
- avoids duplicate final snapshots when streaming already produced the final text
Detailed streaming contract: Usage Guide
The service keeps a shared session continuation contract around metadata.shared.session.id and adapter-derived contextId, so clients can continue work without binding directly to raw OpenCode session IDs.
The same process can also act as an embedded A2A client:
- CLI calls route through the local client facade
- server-side
a2a_calltool execution uses the same outbound client settings - outbound auth, timeouts, and transport preferences are configured independently from inbound auth
The adapter improves the runtime boundary, but it is not a full trust-boundary replacement.
- stable A2A-facing contract shape
- auth enforcement on A2A entrypoints
- payload logging controls
- lightweight persistence for SDK task rows plus adapter-managed runtime state
- compatibility metadata for clients and operators
- provider credential consumption
- workspace side effects
- upstream model/provider behavior
- host-level process supervision and isolation
That is why deployments should still be treated as trusted or controlled unless stronger isolation is added outside this repository.
Use the docs by responsibility:
- README: project overview, install/start path, and entry navigation
- Compatibility Guide: compatibility-sensitive surface and stability expectations
- Usage Guide: runtime configuration, transport contracts, extensions, and examples
- Maintainer Architecture Guide: internal module boundaries, request call chains, and persistence touchpoints
- Extension Specifications: stable extension URI/spec index and disclosure policy
- Conformance Notes: external TCK experiment workflow
- Contributing Guide: contributor workflow and validation
- Security Policy: threat model and disclosure guidance