A2A wrapper service for opencode
Project description
opencode-a2a-server
Turn OpenCode into a stateful A2A service with a clear runtime boundary and production-friendly deployment workflow.
opencode-a2a-server exposes OpenCode through standard A2A interfaces and adds
the operational pieces that raw agent runtimes usually do not provide by
default: authentication, session continuity, streaming contracts, interrupt
handling, deployment tooling, and explicit security guidance.
Why This Project Exists
OpenCode is useful as an interactive runtime, but applications and gateways need a stable service layer around it. This repository provides that layer by:
- bridging A2A transport contracts to OpenCode session/message/event APIs
- making session and interrupt behavior explicit and auditable
- packaging release-first deployment scripts and operational guidance for long-running use
What It Already Provides
- A2A HTTP+JSON endpoints (
/v1/message:send,/v1/message:stream,GET /v1/tasks/{task_id}:subscribe) - A2A JSON-RPC endpoint (
POST /) for standard methods and OpenCode-oriented extensions - SSE streaming with normalized
text,reasoning, andtool_callblocks - session continuation via
metadata.shared.session.id - request-scoped model selection via
metadata.shared.model - OpenCode session query/control extensions and provider/model discovery
- released CLI install/upgrade flow and release-based systemd deployment
Extension Capability Overview
The Agent Card declares six extension URIs. Shared contracts are intended for any compatible consumer; OpenCode-specific contracts stay provider-scoped even though they are exposed through A2A JSON-RPC.
| Extension URI | Scope | Primary use |
|---|---|---|
urn:a2a:session-binding/v1 |
Shared | Bind a main chat request to an existing upstream session via metadata.shared.session.id |
urn:a2a:model-selection/v1 |
Shared | Override the default upstream model for one main chat request |
urn:a2a:stream-hints/v1 |
Shared | Advertise canonical stream metadata for blocks, usage, interrupts, and session hints |
urn:opencode-a2a:session-query/v1 |
OpenCode-specific | Query external sessions and invoke OpenCode session control methods |
urn:opencode-a2a:provider-discovery/v1 |
OpenCode-specific | Discover normalized OpenCode provider/model summaries |
urn:a2a:interactive-interrupt/v1 |
Shared | Reply to interrupt callbacks observed from stream metadata |
Detailed consumption guidance:
- Shared session binding:
docs/guide.md#shared-session-binding-contract - Shared model selection:
docs/guide.md#shared-model-selection-contract - Shared stream hints:
docs/guide.md#shared-stream-hints-contract - OpenCode session query and provider discovery:
docs/guide.md#opencode-session-query--provider-discovery-a2a-extensions - Shared interrupt callback:
docs/guide.md#shared-interrupt-callback-a2a-extension
Design Principle
One OpenCode + opencode-a2a-server instance pair is treated as a
single-tenant trust boundary.
This repository's intended scaling model is parameterized self-deployment: consumers should launch their own isolated instance pairs through the provided deployment scripts instead of sharing one runtime across mutually untrusted tenants.
- OpenCode may manage multiple projects/directories, but one deployed instance is not a secure multi-tenant runtime.
- Shared-instance identity/session checks are best-effort coordination, not hard tenant isolation.
- For mutually untrusted tenants, deploy separate instance pairs with isolated Linux users or containers, isolated workspace roots, isolated credentials, and distinct runtime ports.
Logical Components
flowchart TD
Hub["A2A client / a2a-client-hub / app"] --> Api["opencode-a2a-server transport"]
Api --> Mapping["Task / session / interrupt mapping"]
Mapping --> Runtime["OpenCode HTTP runtime"]
Api --> Auth["Bearer auth + request logging controls"]
Api --> Deploy["release-based deployment tooling"]
Runtime --> Workspace["Shared workspace / environment boundary"]
This repository wraps OpenCode in a service layer. It does not change OpenCode into a hard multi-tenant isolation platform.
Recommended Client Side
If you need a client-side integration layer to consume this service, prefer a2a-client-hub.
It is a better place for client concerns such as A2A consumption, upstream
adapter normalization, and application-facing integration, while
opencode-a2a-server stays focused on the server/runtime boundary around
OpenCode.
Security Model
This project improves the service boundary around OpenCode, but it is not a hard multi-tenant isolation layer.
A2A_BEARER_TOKENprotects the A2A surface, but it is not a tenant isolation boundary inside one deployed instance.- LLM provider keys are consumed by the OpenCode process. Prompt injection or indirect exfiltration attempts may still expose sensitive values.
- systemd deploy defaults use operator-provisioned root-only secret files
unless
ENABLE_SECRET_PERSISTENCE=trueis explicitly enabled.
Read before deployment:
User Paths
Released versions are published to PyPI and mapped to Git tags / GitHub Releases. This is the recommended entry point for users.
Path 1: Run a Released CLI in an Existing User Environment
Install the latest release:
uv tool install opencode-a2a-server
Upgrade an existing installation:
uv tool upgrade opencode-a2a-server
Install an exact release:
uv tool install "opencode-a2a-server==<version>"
Run it against an existing project/workspace:
GOOGLE_GENERATIVE_AI_API_KEY=<your-key> \
OPENCODE_PROVIDER_ID=google \
OPENCODE_MODEL_ID=gemini-3.1-pro-preview \
opencode serve
A2A_BEARER_TOKEN=prod-token \
A2A_PUBLIC_URL=http://127.0.0.1:8000 \
OPENCODE_DIRECTORY=/abs/path/to/workspace \
opencode-a2a-server
Default address: http://127.0.0.1:8000
If you omit OPENCODE_PROVIDER_ID / OPENCODE_MODEL_ID, opencode serve
uses your local OpenCode defaults (for example ~/.config/opencode/opencode.json).
For provider-specific auth, model IDs, and config details, use the OpenCode official docs and CLI:
- Providers: https://opencode.ai/docs/providers/
- Models: https://opencode.ai/docs/models/
- Local checks:
opencode auth list,opencode models,opencode models <provider>
This path is for users who already manage their own shell, workspace, and process lifecycle. No host bootstrap script is required.
Path 2: Formal systemd Deploy From a Released Version
For long-running systemd deployments, use the release-based scripts:
./scripts/init_release_system.sh
./scripts/deploy_release.sh project=alpha a2a_port=8010 a2a_host=127.0.0.1
This path is for users who want:
- isolated Linux users and per-project directories
- systemd-managed restart behavior
- root-only secret files
- published package versions as the deployment boundary
Primary operator docs:
- scripts/init_release_system.sh
- scripts/deploy_release.sh
- scripts/deploy_release_readme.md
- docs/release_deploy_smoke_test.md
Contributor Paths
Use the repository checkout directly only for development, local debugging, or validation against unreleased changes. Source-based deploy/bootstrap docs are kept for contributors and internal debugging, not as the recommended user path.
Quick source run:
uv sync --all-extras
GOOGLE_GENERATIVE_AI_API_KEY=<your-key> \
OPENCODE_PROVIDER_ID=google \
OPENCODE_MODEL_ID=gemini-3.1-pro-preview \
opencode serve
A2A_BEARER_TOKEN=dev-token \
OPENCODE_DIRECTORY=/abs/path/to/workspace \
uv run opencode-a2a-server
Baseline validation:
uv run pre-commit run --all-files
uv run pytest
Documentation Map
User / Operator Docs
- docs/guide.md Product behavior, API contracts, and detailed streaming/session/interrupt consumption guidance.
- docs/agent_deploy_sop.md Operator-facing SOP for release-based deployment, verification, and uninstall.
- docs/release_deploy_smoke_test.md Real-host smoke test checklist for release-based systemd deployment.
- scripts/deploy_release_readme.md Release-based systemd deployment guide for published package versions.
- scripts/init_release_system_readme.md Release-based host bootstrap guide that avoids source checkout.
- scripts/uninstall_readme.md Preview-first uninstall flow for deployed instances.
- scripts/README.md Full script index, including contributor/internal paths.
Contributor / Internal Docs
- scripts/deploy_readme.md Source-based systemd deployment for development/debugging only.
- scripts/init_system_readme.md Source-based host bootstrap for contributor/internal workflows.
- SECURITY.md threat model, deployment caveats, and vulnerability disclosure guidance.
License
Apache-2.0. See LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file opencode_a2a_server-0.2.0.tar.gz.
File metadata
- Download URL: opencode_a2a_server-0.2.0.tar.gz
- Upload date:
- Size: 203.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa21f3d0d89b7ae4bf0651de877973354053604f2e79354f2f4262b6ba9c8351
|
|
| MD5 |
f5245718f00e2f7e181fcebda8f84a04
|
|
| BLAKE2b-256 |
1253f831bbadc93e9ef8936cf5065b207681a3e050ecb7e59ce3c4a0f127e844
|
Provenance
The following attestation bundles were made for opencode_a2a_server-0.2.0.tar.gz:
Publisher:
publish.yml on Intelligent-Internet/opencode-a2a-server
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
opencode_a2a_server-0.2.0.tar.gz -
Subject digest:
aa21f3d0d89b7ae4bf0651de877973354053604f2e79354f2f4262b6ba9c8351 - Sigstore transparency entry: 1122742053
- Sigstore integration time:
-
Permalink:
Intelligent-Internet/opencode-a2a-server@e591a141a6d7c0f0a29a7195ad3cff6f1bab85f5 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Intelligent-Internet
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e591a141a6d7c0f0a29a7195ad3cff6f1bab85f5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file opencode_a2a_server-0.2.0-py3-none-any.whl.
File metadata
- Download URL: opencode_a2a_server-0.2.0-py3-none-any.whl
- Upload date:
- Size: 54.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4979318e8f0edfaa84035b1239073d1720ffa3ef5132443610e99e53dac19ceb
|
|
| MD5 |
56da1ba26779c07fa3824b543e4a9132
|
|
| BLAKE2b-256 |
b8f017cfd6bbac457ead46fee302326121470473111841e80935271cf13e5c72
|
Provenance
The following attestation bundles were made for opencode_a2a_server-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on Intelligent-Internet/opencode-a2a-server
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
opencode_a2a_server-0.2.0-py3-none-any.whl -
Subject digest:
4979318e8f0edfaa84035b1239073d1720ffa3ef5132443610e99e53dac19ceb - Sigstore transparency entry: 1122742059
- Sigstore integration time:
-
Permalink:
Intelligent-Internet/opencode-a2a-server@e591a141a6d7c0f0a29a7195ad3cff6f1bab85f5 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Intelligent-Internet
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e591a141a6d7c0f0a29a7195ad3cff6f1bab85f5 -
Trigger Event:
push
-
Statement type: