[PR #10452] feat: add A2A (Agent-to-Agent) remote agent support #13447

Open
opened 2026-02-16 18:18:18 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/10452

State: open
Merged: No


Fixes https://github.com/anomalyco/opencode/issues/3023.

Summary

This PR adds support for the A2A (Agent-to-Agent) protocol, enabling OpenCode to communicate with remote AI agents. Users can now invoke remote agents using the @domain.com syntax directly in their prompts.

What is A2A?

A2A is an open protocol that allows AI agents to communicate with each other over HTTP. It defines:

  • Agent Cards: JSON manifests describing an agent's capabilities, skills, and endpoints
  • Message/Task lifecycle: Standardized request/response patterns for agent interactions
  • Streaming: Server-sent events for real-time responses

Features Added

  • @domain.com syntax: Reference remote agents directly in prompts (e.g., @localhost:3000 summarize this code)
  • Agent card discovery: Automatic fetching from /.well-known/a2a/agent-card or custom paths
  • Streaming responses: Real-time output from remote agents via SSE
  • Session context: Maintains conversation context across multiple interactions with the same agent
  • Trust management: Session-based and config-based trust for remote agent domains
  • Autocomplete: Tab completion for @ references in the TUI

Design Choices

Using the Official SDK

We use @a2a-js/sdk for:

  • Type definitions: AgentCard, Message, Task, Artifact, etc.
  • Client implementation: ClientFactory and Client handle HTTP/JSON-RPC and SSE streaming

This ensures protocol compliance and reduces maintenance burden as the spec evolves.

Module Structure (src/a2a/)

File Purpose
agent-card.ts URL parsing (@domain.com/path), agent card fetching with 5-min cache
client.ts Wraps SDK client, transforms events to internal StreamEvent type
context.ts Stores contextId per session+domain for conversation continuity
trust.ts Domain trust: session-scoped (temporary) and config-based (persistent)
index.ts Re-exports SDK types and module functions

Integration with Task Tool

Remote agents are invoked through the existing Task tool. When a @domain.com reference is detected:

  1. Trust is verified (prompts user if untrusted)
  2. Agent card is fetched and cached
  3. SDK client streams the response
  4. Events are transformed and displayed in the TUI

How It Works

User: @localhost:3000 hello world
         │
         ▼
   parseAgentRef("@localhost:3000")
         │
         ▼
   fetchAgentCard() → GET http://localhost:3000/.well-known/a2a/agent-card
         │
         ▼
   SDK Client.sendMessageStream()
         │
         ▼
   Transform A2AStreamEventData → StreamEvent
         │
         ▼
   Display in TUI (streaming text, tool calls, artifacts)

Configuration

Trust remote agent domains in ~/.config/opencode/config.json:

{
  "remoteAgents": {
    "domains": ["trusted-agent.example.com"]
  }
}
**Original Pull Request:** https://github.com/anomalyco/opencode/pull/10452 **State:** open **Merged:** No --- Fixes https://github.com/anomalyco/opencode/issues/3023. ## Summary This PR adds support for the [A2A (Agent-to-Agent) protocol](https://google.github.io/A2A/), enabling OpenCode to communicate with remote AI agents. Users can now invoke remote agents using the `@domain.com` syntax directly in their prompts. ## What is A2A? A2A is an open protocol that allows AI agents to communicate with each other over HTTP. It defines: - **Agent Cards**: JSON manifests describing an agent's capabilities, skills, and endpoints - **Message/Task lifecycle**: Standardized request/response patterns for agent interactions - **Streaming**: Server-sent events for real-time responses ## Features Added - **`@domain.com` syntax**: Reference remote agents directly in prompts (e.g., `@localhost:3000 summarize this code`) - **Agent card discovery**: Automatic fetching from `/.well-known/a2a/agent-card` or custom paths - **Streaming responses**: Real-time output from remote agents via SSE - **Session context**: Maintains conversation context across multiple interactions with the same agent - **Trust management**: Session-based and config-based trust for remote agent domains - **Autocomplete**: Tab completion for `@` references in the TUI ## Design Choices ### Using the Official SDK We use `@a2a-js/sdk` for: - **Type definitions**: `AgentCard`, `Message`, `Task`, `Artifact`, etc. - **Client implementation**: `ClientFactory` and `Client` handle HTTP/JSON-RPC and SSE streaming This ensures protocol compliance and reduces maintenance burden as the spec evolves. ### Module Structure (`src/a2a/`) | File | Purpose | |------|---------| | `agent-card.ts` | URL parsing (`@domain.com/path`), agent card fetching with 5-min cache | | `client.ts` | Wraps SDK client, transforms events to internal `StreamEvent` type | | `context.ts` | Stores `contextId` per session+domain for conversation continuity | | `trust.ts` | Domain trust: session-scoped (temporary) and config-based (persistent) | | `index.ts` | Re-exports SDK types and module functions | ### Integration with Task Tool Remote agents are invoked through the existing Task tool. When a `@domain.com` reference is detected: 1. Trust is verified (prompts user if untrusted) 2. Agent card is fetched and cached 3. SDK client streams the response 4. Events are transformed and displayed in the TUI ## How It Works ``` User: @localhost:3000 hello world │ ▼ parseAgentRef("@localhost:3000") │ ▼ fetchAgentCard() → GET http://localhost:3000/.well-known/a2a/agent-card │ ▼ SDK Client.sendMessageStream() │ ▼ Transform A2AStreamEventData → StreamEvent │ ▼ Display in TUI (streaming text, tool calls, artifacts) ``` ## Configuration Trust remote agent domains in `~/.config/opencode/config.json`: ```json { "remoteAgents": { "domains": ["trusted-agent.example.com"] } } ```
yindo added the pull-request label 2026-02-16 18:18:18 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#13447