Skip to main content

A2A wrapper service for opencode

Project description

opencode-a2a-server

Turn OpenCode into a stateful A2A service with a clear runtime boundary.

opencode-a2a-server exposes OpenCode through standard A2A interfaces and adds the runtime pieces that raw agent runtimes usually do not provide by default: authentication, session continuity, streaming contracts, interrupt handling, 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
  • keeping the server/runtime contract explicit while leaving deployment supervision to the operator

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, and tool_call blocks
  • 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 a foreground runtime entrypoint

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:

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 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"]
    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_TOKEN protects 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.
  • Deployment supervision is intentionally BYO. If you wrap this runtime with systemd, Docker, Kubernetes, or another supervisor, you own the service user, secret storage, restart policy, and hardening choices.

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_WORKSPACE_ROOT=/abs/path/to/workspace \
opencode-a2a-server serve

OPENCODE_WORKSPACE_ROOT is the default workspace root that this runtime exposes to OpenCode.

Default address: http://127.0.0.1:8000

Common runtime variables:

Variable Required Default Purpose
A2A_BEARER_TOKEN Yes None Bearer token required for authenticated runtime requests.
OPENCODE_BASE_URL No http://127.0.0.1:4096 Upstream OpenCode HTTP endpoint.
OPENCODE_WORKSPACE_ROOT No None Default workspace root exposed to OpenCode.
OPENCODE_PROVIDER_ID No None Default provider for the upstream runtime.
OPENCODE_MODEL_ID No None Default model for the upstream runtime. Set together with OPENCODE_PROVIDER_ID.
A2A_HOST No 127.0.0.1 Bind host for the A2A server.
A2A_PORT No 8000 Bind port for the A2A server.
A2A_PUBLIC_URL No http://127.0.0.1:8000 Public base URL advertised by the Agent Card.
A2A_LOG_LEVEL No WARNING Server log level.
A2A_LOG_PAYLOADS No false Enable request/response payload logging.
A2A_LOG_BODY_LIMIT No 0 Payload preview size used when payload logging is enabled.
A2A_MAX_REQUEST_BODY_BYTES No 1048576 Maximum accepted request size.
A2A_ALLOW_DIRECTORY_OVERRIDE No true Allow request-level metadata.opencode.directory overrides.
A2A_ENABLE_SESSION_SHELL No false Enable high-risk opencode.sessions.shell.
OPENCODE_TIMEOUT No 120 Upstream OpenCode request timeout in seconds.
OPENCODE_TIMEOUT_STREAM No None Upstream OpenCode stream timeout override in seconds.

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:

This path is for users who already manage their own shell, workspace, and process lifecycle.

Use any supervisor you prefer for long-running operation:

  • systemd
  • Docker / container runtimes
  • Kubernetes
  • supervisord, pm2, or similar process managers

The project no longer ships built-in host bootstrap or process-manager wrappers. The official product surface is the runtime entrypoint itself.

Minimal systemd example:

  1. Create an env file such as /etc/opencode-a2a/alpha.env:
A2A_BEARER_TOKEN=replace-me
A2A_HOST=127.0.0.1
A2A_PORT=8000
A2A_PUBLIC_URL=https://a2a.example.com
OPENCODE_BASE_URL=http://127.0.0.1:4096
OPENCODE_WORKSPACE_ROOT=/srv/my-workspace
  1. Create a unit file such as /etc/systemd/system/opencode-a2a-server.service:
[Unit]
Description=OpenCode A2A Server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=/srv/my-workspace
EnvironmentFile=/etc/opencode-a2a/alpha.env
ExecStart=/home/dev/.local/bin/opencode-a2a-server serve
Restart=on-failure
RestartSec=2

[Install]
WantedBy=multi-user.target

Replace ExecStart with the absolute path returned by command -v opencode-a2a-server.

Migration notes:

  • OPENCODE_DIRECTORY has been removed. Use OPENCODE_WORKSPACE_ROOT.
  • Built-in init-release-system, deploy-release, and uninstall-instance have been removed.
  • Secret storage, service users, restart policy, and supervisor configuration are now operator-managed.

Contributor Paths

Use the repository checkout directly only for development, local debugging, or validation against unreleased changes.

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_WORKSPACE_ROOT=/abs/path/to/workspace \
uv run opencode-a2a-server serve

Baseline validation:

uv run pre-commit run --all-files
uv run pytest

Documentation Map

User Docs

  • docs/guide.md Product behavior, API contracts, and detailed streaming/session/interrupt consumption guidance.
  • SECURITY.md Threat model, deployment caveats, and vulnerability disclosure guidance.
  • CONTRIBUTING.md Contributor workflow, validation baseline, and documentation expectations.
  • scripts/README.md Contributor helper script index.

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

opencode_a2a_server-0.2.2.tar.gz (179.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

opencode_a2a_server-0.2.2-py3-none-any.whl (58.7 kB view details)

Uploaded Python 3

File details

Details for the file opencode_a2a_server-0.2.2.tar.gz.

File metadata

  • Download URL: opencode_a2a_server-0.2.2.tar.gz
  • Upload date:
  • Size: 179.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for opencode_a2a_server-0.2.2.tar.gz
Algorithm Hash digest
SHA256 949be44edffecc10980b39a6aabb6b4f95dfd6076734cbb2b98b3272a86c1bd4
MD5 d12ce58c31dea56de04c9eee5dd81682
BLAKE2b-256 a5c45350d8b1103d5fa51ca60f8db1c5c19a28c124fdd3fd1aefd971bbe5438a

See more details on using hashes here.

Provenance

The following attestation bundles were made for opencode_a2a_server-0.2.2.tar.gz:

Publisher: publish.yml on Intelligent-Internet/opencode-a2a-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file opencode_a2a_server-0.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for opencode_a2a_server-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b8ae267b3fb3ad101f68b79c0f188af99062b0cd23d106cb856a4de9a5be5919
MD5 af5d6f395f0a48d01b14a82d419eaae1
BLAKE2b-256 781af72bdacc54521629f39b32e754c052fe4a9d1b9508308589706970dac6c5

See more details on using hashes here.

Provenance

The following attestation bundles were made for opencode_a2a_server-0.2.2-py3-none-any.whl:

Publisher: publish.yml on Intelligent-Internet/opencode-a2a-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page