Documentation
¶
Overview ¶
Package a2a integrates the Agent-to-Agent (A2A) protocol into the Scope agent framework, wrapping the official SDK github.com/a2aproject/a2a-go/v2 (sdka2a/a2asrv/a2aclient).
It has two sides:
CLIENT — OpenToolSet resolves remote AgentCards and returns a ToolSet that owns both the tool view and opened protocol clients.
SERVER — expose a capability AS an A2A endpoint. Implement the narrow Agent interface (text in, streamed text out); NewHTTPHandler adapts it to the SDK and mounts the JSON-RPC method endpoint plus the well-known AgentCard.
The transport default is JSON-RPC over HTTP, matching the rest of the stack; the SDK's REST/gRPC bindings are not precluded but are not wired here.
Naming convention: the SDK's core types package is imported as `sdka2a` to avoid colliding with this package's own name; the server and client SDK packages keep their names `a2asrv` / `a2aclient`.
Index ¶
Examples ¶
Constants ¶
const DefaultRPCPattern = "/invoke"
DefaultRPCPattern is where NewHTTPHandler mounts the JSON-RPC method endpoint. The AgentCard's JSON-RPC interface URL must point at this path.
Variables ¶
var ( ErrNilCard = errors.New("a2a: agent card must not be nil") ErrInvalidCard = errors.New("a2a: invalid agent card") ErrNilAgent = errors.New("a2a: agent must not be nil") ErrEmptyCardURL = errors.New("a2a: card URL must not be empty") ErrInvalidCardURL = errors.New("a2a: invalid card URL") ErrInvalidCardTimeout = errors.New("a2a: card timeout must not be negative") ErrInvalidRPCOrigin = errors.New("a2a: invalid allowed RPC origin") ErrOriginNotAllowed = errors.New("a2a: origin not allowed") ErrInvalidRPCPattern = errors.New("a2a: invalid RPC pattern") ErrInvalidResult = errors.New("a2a: invalid send-message result") )
Functions ¶
func NewHTTPHandler ¶
func NewHTTPHandler(config ServerConfig) (http.Handler, error)
func NewJSONRPCInterface ¶
func NewJSONRPCInterface(url string) *sdka2a.AgentInterface
Example ¶
package main
import (
"fmt"
"github.com/Tangerg/scope/a2a"
)
func main() {
transport := a2a.NewJSONRPCInterface("https://agent.example/invoke")
fmt.Println(transport.URL, transport.ProtocolBinding)
}
Output: https://agent.example/invoke JSONRPC
Types ¶
type Agent ¶
type Agent interface {
// Run handles one inbound A2A message, already flattened to text, and
// yields the reply as a sequence of text chunks. A single-shot agent
// yields once; a streaming agent yields deltas. A yielded error ends the
// task as failed and stops iteration.
Run(ctx context.Context, input string) iter.Seq2[string, error]
}
Agent is the scope-side capability exposed over A2A. It is intentionally narrow — text in, streamed text out — so the consumer (an agent runtime) implements it without this package depending on those layers. The interface lives here, in the consumer, per the convention: the a2a server is what "runs an agent", so it declares the shape it needs.
type Endpoint ¶
type Endpoint struct {
// Name overrides the model-visible tool name. Empty derives it from the
// resolved AgentCard.
Name string
// CardURL is the absolute HTTP(S) URL used to resolve the AgentCard.
CardURL string
// HTTPClient is the client used for both card resolution and RPC calls.
// Nil uses http.DefaultClient. The caller retains ownership; a restricted
// shallow copy is used internally.
HTTPClient *http.Client
// CardTimeout bounds AgentCard resolution only. Zero selects 30 seconds; it
// does not impose a timeout on long-running agent RPC calls.
CardTimeout time.Duration
// AllowedRPCOrigins adds trusted RPC origins beyond CardURL's own origin.
// Entries use the exact "scheme://host[:port]" form. Empty prevents an
// AgentCard from redirecting calls to another origin.
AllowedRPCOrigins []string
}
Endpoint describes one remote A2A agent to expose as a chat tool. Its zero policy keeps discovery and RPC traffic on CardURL's origin.
type RemoteAgentError ¶
type RemoteAgentError struct {
// State is the task state the remote reported.
State sdka2a.TaskState
// Detail is any human-readable message the remote attached, or "".
Detail string
}
RemoteAgentError reports that a remote A2A task did not complete successfully. It lets a caller use errors.AsType to distinguish it from transport or protocol failures: the remote was reached and answered, but the work failed, was canceled or rejected, or requires unsupported continuation.
func (*RemoteAgentError) Error ¶
func (r *RemoteAgentError) Error() string
type ServerConfig ¶
type ServerConfig struct {
// Agent is the capability served over A2A. Required.
Agent Agent
// Card is the AgentCard served at the well-known path. Required and
// snapshotted during construction — its SupportedInterfaces should advertise
// a JSON-RPC interface whose URL ends in RPCPattern. Build it with
// [NewJSONRPCInterface] for the transport entry.
Card *sdka2a.AgentCard
// RPCPattern overrides where the JSON-RPC endpoint is mounted. Empty
// uses [DefaultRPCPattern].
RPCPattern string
}
ServerConfig wires a Agent into an HTTP A2A endpoint.
type ToolSet ¶
type ToolSet struct {
// contains filtered or unexported fields
}
ToolSet owns the clients behind an immutable view of remote-agent tools. Tools remain usable until Close; the value must not be copied after first use.
func OpenToolSet ¶
OpenToolSet closes every client opened before a later endpoint fails, so a failed construction never transfers partial lifecycle ownership to callers.
func (*ToolSet) Close ¶
Close releases every remote-agent client in reverse acquisition order. It is nil-safe and idempotent so multiple shutdown paths can share the owner.
func (*ToolSet) Tools ¶
func (t *ToolSet) Tools() []toolcontract.Tool
Tools returns a snapshot so callers cannot mutate the set's ordered view.