a2a

package
v0.1.0-pre Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 26, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package a2a implements the v0.1 synchronous A2A client from docs/a2a-design.md ("Mast as A2A client", client-only phasing row): agent-card discovery and caching, JSON-RPC 2.0 message/send on the single A2A v0.3 endpoint (A2A-Version header, bearer auth from an env-var reference), direct-message and task-opened reply handling with bounded tasks/get polling to a terminal state, and tasks/cancel on caller cancellation. Static agent configs load from .agents/a2a/*.yaml (see AgentConfig / LoadDir; wired into pkg/config root scanning).

Build-vs-reuse note (docs/a2a-design.md v0.1 phasing row asks that ADK v2.1.0's agentregistry package be evaluated before hand-building client machinery): evaluated 2026-07-26 and declined for v0.1. That package is a Google Cloud Agent Registry client — ADC-authenticated discovery plus RemoteAgent factories over github.com/a2aproject/ a2a-go/v2, aimed at the registry-discovery story that is explicitly v0.2 here. Using its factories for the static-config path would add a2a-go/v2 as a direct dependency and an ADK RemoteAgent abstraction on top, to obtain three JSON-RPC methods and a card GET that fit in this file against stdlib net/http. Revisit at v0.2, where streaming (message/stream over SSE) and registry discovery make the SDK earn its place.

Layering note: Send returns *federation.Result and wraps the federation sentinel errors directly rather than defining a parallel error/result vocabulary — pkg/federation is protocol-neutral and does not import this package, so the dependency is one-way.

Index

Constants

View Source
const AuthTypeBearer = "bearer"

AuthTypeBearer is the only auth type the v0.1 client supports. google-iam (docs/a2a-design.md static-registration example) joins in v0.2 alongside the pluggable token-resolver surface.

View Source
const DefaultTimeout = 120 * time.Second

DefaultTimeout bounds a Send when neither the per-agent config nor the caller supplies one. v0.1 calls block to a bounded timeout — long-running remote tasks need programmatic pause, which is v0.2 per docs/durable-execution-design.md phasing.

View Source
const ProtocolVersion = "0.3"

ProtocolVersion is the A2A spec line this client implements and advertises in the A2A-Version request header (docs/a2a-design.md resolved open question 1: pin to the v0.3 line, send the header, document tested-against versions per release).

View Source
const Scheme = "a2a"

Scheme is the federation reference scheme this adapter serves: a2a://<name>/<skill> (docs/federation-design.md reference grammar).

View Source
const TransportJSONRPC = "JSONRPC"

TransportJSONRPC is the card transport identifier for JSON-RPC 2.0 over HTTP — the only transport this client speaks (docs/a2a-design.md endpoint layout: "JSON-RPC only at first"). An absent preferredTransport defaults to JSON-RPC per spec.

View Source
const VersionHeader = "A2A-Version"

VersionHeader is the HTTP request header carrying ProtocolVersion.

View Source
const WellKnownCardPath = "/.well-known/agent-card.json"

WellKnownCardPath is the spec-defined agent-card discovery path.

Variables

This section is empty.

Functions

This section is empty.

Types

type Adapter

type Adapter struct {
	// contains filtered or unexported fields
}

Adapter is the A2A protocol adapter for the federation registry — the v0.1 slice of docs/federation-design.md's "A2A adapter": static references only; registry-discovered references (a2a://<registry>/ <agent-id>) are v0.2.

func NewAdapter

func NewAdapter(cfgs []AgentConfig, opts ...ClientOption) (*Adapter, error)

NewAdapter builds the adapter from static agent configs (normally pkg/config's .agents/a2a/*.yaml scan). opts apply to every client.

func (*Adapter) Invoke

Invoke implements federation.Adapter. Per the frozen contract it returns an error only for dispatch-time failures (unknown agent); the synchronous remote call runs inside Invoke — v0.1 blocks to a bounded timeout — and its outcome, success or failure, surfaces from the returned Handle's Wait.

func (*Adapter) Scheme

func (a *Adapter) Scheme() string

Scheme implements federation.Adapter.

type AgentCard

type AgentCard struct {
	Name                 string           `json:"name"`
	Description          string           `json:"description,omitempty"`
	URL                  string           `json:"url"`
	Version              string           `json:"version,omitempty"`
	ProtocolVersion      string           `json:"protocolVersion,omitempty"`
	PreferredTransport   string           `json:"preferredTransport,omitempty"`
	AdditionalInterfaces []AgentInterface `json:"additionalInterfaces,omitempty"`
	Capabilities         Capabilities     `json:"capabilities,omitempty"`
	DefaultInputModes    []string         `json:"defaultInputModes,omitempty"`
	DefaultOutputModes   []string         `json:"defaultOutputModes,omitempty"`
	Skills               []AgentSkill     `json:"skills,omitempty"`
}

AgentCard is the discovery-time contract served at /.well-known/agent-card.json. Note: spec AgentSkill has NO I/O schemas — only inputModes/outputModes media types. Structured I/O contracts are conveyed in skill descriptions or out of band (docs/a2a-design.md, protocol overview).

type AgentConfig

type AgentConfig struct {
	// Name is the reference name: a2a://<name>/<skill>. Must be
	// lowercase because the name travels in the URI host position of a
	// federation reference, where RFC 3986 case-insensitivity means
	// parsers normalize to lowercase (see federation.ParseReference).
	Name string `yaml:"name"`

	// AgentCardURL locates the agent card. A base URL (empty or "/"
	// path) gets WellKnownCardPath appended. The JSON-RPC endpoint is
	// then resolved from the card.
	AgentCardURL string `yaml:"agent_card_url,omitempty"`

	// Endpoint is the JSON-RPC endpoint, bypassing card discovery.
	// When both Endpoint and AgentCardURL are set, Endpoint wins for
	// transport and the card is still fetched for skill validation.
	Endpoint string `yaml:"endpoint,omitempty"`

	// Skills is the subset of the agent's skills mast may invoke;
	// empty = all (docs/a2a-design.md).
	Skills []string `yaml:"skills,omitempty"`

	// Auth is optional; absent means unauthenticated calls.
	Auth *AuthConfig `yaml:"auth,omitempty"`

	// TimeoutSeconds bounds each invocation; 0 = DefaultTimeout.
	TimeoutSeconds int `yaml:"timeout_seconds,omitempty"`

	// Filename records provenance for error messages.
	Filename string `yaml:"-"`
}

AgentConfig is one static A2A agent registration from .agents/a2a/<name>.yaml (docs/a2a-design.md, "Static registration").

func LoadDir

func LoadDir(dir string) ([]AgentConfig, error)

LoadDir loads every *.yaml / *.yml in dir (flat, non-recursive, per the pkg/config scan rules). A missing dir yields zero entries. Any invalid file is a fatal load error. Name-collision checking across files is the caller's job (pkg/config does it alongside its other same-directory collision checks).

func (AgentConfig) Timeout

func (c AgentConfig) Timeout() time.Duration

Timeout returns the effective invocation bound.

func (AgentConfig) Validate

func (c AgentConfig) Validate() error

Validate checks an AgentConfig for load-time errors. All errors are fatal per the config-layout v0.1 rule (fail fast on invalid config).

type AgentInterface

type AgentInterface struct {
	Transport string `json:"transport"`
	URL       string `json:"url"`
}

AgentInterface is one (transport, url) alternative from the card.

type AgentSkill

type AgentSkill struct {
	ID          string   `json:"id"`
	Name        string   `json:"name,omitempty"`
	Description string   `json:"description,omitempty"`
	Tags        []string `json:"tags,omitempty"`
	InputModes  []string `json:"inputModes,omitempty"`
	OutputModes []string `json:"outputModes,omitempty"`
}

AgentSkill is one named capability. Per the v0.3 spec it carries media types, not JSON Schemas.

type Artifact

type Artifact struct {
	ArtifactID  string `json:"artifactId,omitempty"`
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
	Parts       []Part `json:"parts,omitempty"`
}

Artifact is a task output artifact.

type AuthConfig

type AuthConfig struct {
	// Type is the auth mechanism; v0.1: "bearer" only.
	Type string `yaml:"type"`

	// TokenEnv names the environment variable holding the bearer
	// token. Resolved at request time, not load time, so rotation
	// does not require a config reload.
	TokenEnv string `yaml:"token_env"`
}

AuthConfig is the static-registration auth block. Tokens are env-var references, never file-embedded (docs/a2a-design.md).

type Capabilities

type Capabilities struct {
	Streaming         bool `json:"streaming,omitempty"`
	PushNotifications bool `json:"pushNotifications,omitempty"`
}

Capabilities is the card's capability declaration.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a synchronous A2A v0.3 client for one configured agent. Safe for concurrent use.

func NewClient

func NewClient(cfg AgentConfig, opts ...ClientOption) (*Client, error)

NewClient validates cfg and returns a Client. No network I/O happens until the first call (card fetch is lazy).

func (*Client) Card

func (c *Client) Card(ctx context.Context) (*AgentCard, error)

Card returns the agent card, fetching and caching it on first use. Endpoint-only configs (no agent_card_url) return (nil, nil): the card is optional when the operator pinned the endpoint directly.

func (*Client) Name

func (c *Client) Name() string

Name returns the configured agent name.

func (*Client) Send

func (c *Client) Send(ctx context.Context, skill string, inputs map[string]any, timeout time.Duration) (*federation.Result, error)

Send invokes skill on the remote agent with inputs and blocks until a terminal state or the bounded timeout (opts precedence: timeout argument > config timeout_seconds > DefaultTimeout). The reply may be a direct message (returned as a completed Result) or an opened task, which Send polls via tasks/get. If the caller's ctx is canceled or the bound expires mid-task, Send issues tasks/cancel (best effort, on a detached context) before returning.

Skill selection: A2A v0.3 message/send has no first-class skill selector — AgentSkill is card-level metadata and MessageSendParams carries only the message. Mast conveys the chosen skill as message metadata under "skillId" (and validates it against the fetched card and the config's skills allowlist). Servers that route by content ignore the hint harmlessly.

type ClientOption

type ClientOption func(*Client)

ClientOption customizes a Client.

func WithHTTPClient

func WithHTTPClient(h *http.Client) ClientOption

WithHTTPClient substitutes the transport (tests, custom TLS/proxies).

func WithPollInterval

func WithPollInterval(d time.Duration) ClientOption

WithPollInterval overrides the tasks/get polling cadence.

type Message

type Message struct {
	Kind      string         `json:"kind"`
	MessageID string         `json:"messageId"`
	Role      string         `json:"role"`
	Parts     []Part         `json:"parts"`
	TaskID    string         `json:"taskId,omitempty"`
	ContextID string         `json:"contextId,omitempty"`
	Metadata  map[string]any `json:"metadata,omitempty"`
}

Message is an A2A message (kind: "message").

type Part

type Part struct {
	Kind     string         `json:"kind"`
	Text     string         `json:"text,omitempty"`
	Data     map[string]any `json:"data,omitempty"`
	Metadata map[string]any `json:"metadata,omitempty"`
}

Part is a message/artifact content part. Exactly one of Text / Data is populated for the kinds this client produces and consumes ("text", "data"); other kinds ("file") pass through with only Kind set.

type RPCError

type RPCError struct {
	Code    int             `json:"code"`
	Message string          `json:"message"`
	Data    json.RawMessage `json:"data,omitempty"`
}

RPCError is a JSON-RPC 2.0 error object (A2A-specific codes included, e.g. -32001 TaskNotFound).

func (*RPCError) Error

func (e *RPCError) Error() string

type Task

type Task struct {
	Kind      string     `json:"kind"`
	ID        string     `json:"id"`
	ContextID string     `json:"contextId,omitempty"`
	Status    TaskStatus `json:"status"`
	Artifacts []Artifact `json:"artifacts,omitempty"`
}

Task is an A2A task (kind: "task").

type TaskState

type TaskState string

TaskState is the A2A v0.3 task lifecycle vocabulary.

const (
	TaskStateSubmitted     TaskState = "submitted"
	TaskStateWorking       TaskState = "working"
	TaskStateInputRequired TaskState = "input-required"
	TaskStateAuthRequired  TaskState = "auth-required"
	TaskStateCompleted     TaskState = "completed"
	TaskStateFailed        TaskState = "failed"
	TaskStateCanceled      TaskState = "canceled"
	TaskStateRejected      TaskState = "rejected"
)

func (TaskState) Terminal

func (s TaskState) Terminal() bool

Terminal reports whether the state ends the task lifecycle.

type TaskStatus

type TaskStatus struct {
	State   TaskState `json:"state"`
	Message *Message  `json:"message,omitempty"`
}

TaskStatus is the task's current lifecycle position.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL