a2a

package
v0.1.13 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: Apache-2.0 Imports: 23 Imported by: 1

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AuthMiddleware

func AuthMiddleware(authCfg *agentmodel.A2AAuth, jwtSvc *svcauth.JWTService, tokenProvider ...token.Provider) func(http.Handler) http.Handler

AuthMiddleware returns HTTP middleware that enforces A2A authentication based on the agent's A2AAuth configuration. It validates Bearer tokens, checks required scopes, and — when a TokenProvider is supplied — registers the inbound token so mid-turn refresh works via EnsureTokens.

func EffectiveA2A

func EffectiveA2A(ag *agentmodel.Agent) *agentmodel.ServeA2A

EffectiveA2A returns the A2A configuration for an agent, checking both modern Serve.A2A and legacy ExposeA2A. Exported for use by the server launcher.

Types

type A2AAuthConfig

type A2AAuthConfig struct {
	Enabled       bool
	Resource      string
	Scopes        []string
	UseIDToken    bool
	ExcludePrefix string
}

A2AAuthConfig is a runtime-agnostic auth configuration for exposing an A2A endpoint.

type A2AConfig

type A2AConfig struct {
	Enabled     bool
	Port        int
	Streaming   bool
	UserCredURL string
}

A2AConfig is a runtime-agnostic serving configuration for one exposed agent.

type AgentCapabilities

type AgentCapabilities struct {
	Streaming              bool `json:"streaming,omitempty"`
	PushNotifications      bool `json:"pushNotifications,omitempty"`
	StateTransitionHistory bool `json:"stateTransitionHistory,omitempty"`
}

AgentCapabilities describes what an A2A agent supports.

type AgentCard

type AgentCard struct {
	Name           string                 `json:"name"`
	Title          string                 `json:"title,omitempty"`
	Version        string                 `json:"version,omitempty"`
	Description    string                 `json:"description,omitempty"`
	Endpoints      map[string]string      `json:"endpoints,omitempty"`
	Authentication map[string]interface{} `json:"authentication,omitempty"`
	Capabilities   *AgentCapabilities     `json:"capabilities,omitempty"`
}

AgentCard describes an A2A agent's identity, capabilities, and endpoints.

type Artifact

type Artifact struct {
	ID        string    `json:"id"`
	CreatedAt time.Time `json:"createdAt"`
	Parts     []Part    `json:"parts"`
}

Artifact is an output generated by a task.

type Client

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

Client calls an external A2A agent over JSON-RPC HTTP.

func NewClient

func NewClient(url string, opts ...ClientOption) *Client

NewClient creates an A2A client for the given JSON-RPC endpoint URL. By default it uses message/stream (SSE) to keep long-running connections alive through load-balancer idle timeouts. Set WithStream(false) to disable and fall back to message/send.

func (*Client) CancelTask

func (c *Client) CancelTask(ctx context.Context, taskID string) (*Task, error)

CancelTask cancels a task on the remote agent.

func (*Client) GetAgentCard

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

GetAgentCard fetches the agent card from the well-known endpoint.

func (*Client) GetTask

func (c *Client) GetTask(ctx context.Context, taskID string) (*Task, error)

GetTask retrieves a task by ID from the remote agent.

func (*Client) SendMessage

func (c *Client) SendMessage(ctx context.Context, messages []Message, contextID *string) (*Task, error)

SendMessage sends messages to an external A2A agent and returns the task. When streaming is enabled (default), it uses the SSE message/stream endpoint so the connection stays alive through load-balancer idle timeouts. contextID is optional — if provided, the remote agent reuses the conversation.

type ClientOption

type ClientOption func(*Client)

ClientOption configures an A2A client.

func WithHTTPClient

func WithHTTPClient(hc *http.Client) ClientOption

WithHTTPClient sets a custom HTTP client.

func WithHeaders

func WithHeaders(h map[string]string) ClientOption

WithHeaders sets custom HTTP headers on all requests.

func WithStream added in v0.1.7

func WithStream(enabled bool) ClientOption

WithStream controls whether the client uses the SSE message/stream endpoint (default: true) to keep the connection alive through load-balancer timeouts.

func WithStreamURL added in v0.1.7

func WithStreamURL(url string) ClientOption

WithStreamURL sets an explicit SSE streaming endpoint URL.

func WithTimeout

func WithTimeout(d time.Duration) ClientOption

WithTimeout sets the HTTP client timeout.

type ExposedAgent

type ExposedAgent struct {
	ID          string
	Name        string
	Description string
	A2A         *A2AConfig
	Auth        *A2AAuthConfig
}

ExposedAgent describes one agent endpoint to expose over A2A.

type ExternalDirectory

type ExternalDirectory struct {
	Name        string   `yaml:"name,omitempty" json:"name,omitempty"`
	Description string   `yaml:"description,omitempty" json:"description,omitempty"`
	Tags        []string `yaml:"tags,omitempty" json:"tags,omitempty"`
	Priority    int      `yaml:"priority,omitempty" json:"priority,omitempty"`
}

ExternalDirectory holds display metadata for an external A2A agent.

type ExternalSpec

type ExternalSpec struct {
	ID         string            `yaml:"id" json:"id"`
	Enabled    *bool             `yaml:"enabled,omitempty" json:"enabled,omitempty"`
	JSONRPCURL string            `yaml:"jsonrpcURL" json:"jsonrpcURL"`
	StreamURL  string            `yaml:"streamURL,omitempty" json:"streamURL,omitempty"`
	Headers    map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"`
	Directory  ExternalDirectory `yaml:"directory,omitempty" json:"directory,omitempty"`
}

ExternalSpec describes an external A2A agent for client-side calls.

func (*ExternalSpec) IsEnabled

func (s *ExternalSpec) IsEnabled() bool

IsEnabled returns true if the spec is enabled (default true if nil).

type GenericServerConfig

type GenericServerConfig struct {
	AgentIDs      []string
	ResolveAgent  func(ctx context.Context, agentID string) (*ExposedAgent, error)
	Query         func(ctx context.Context, agentID, query, conversationID string) (*QueryResult, error)
	ApplyUserCred func(ctx context.Context, credURL string) (context.Context, error)
	JWTService    *svcauth.JWTService
	// TokenProvider, when set, allows the A2A auth middleware to register
	// inbound tokens so mid-turn refresh works via EnsureTokens.
	TokenProvider tokenpkg.Provider
}

GenericServerConfig allows non-core runtimes to reuse the core A2A launcher.

type Group added in v0.1.8

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

Group owns a set of per-agent A2A HTTP servers and coordinates their lifecycle. Returned by StartServers / StartServersGeneric.

A Group shuts its servers down automatically when the ctx passed to StartServers is cancelled. Callers can also call Shutdown explicitly to force a bounded graceful stop; both paths are idempotent.

func StartServers

func StartServers(ctx context.Context, cfg *ServerConfig) *Group

StartServers iterates agents with A2A enabled and launches a dedicated HTTP server per agent on its configured port. Each server exposes:

  • GET /.well-known/agent-card.json — agent card discovery
  • GET /.well-known/oauth-protected-resource — OAuth metadata (if auth enabled)
  • POST /v1/message:send — send message (JSON-RPC envelope or plain JSON)
  • All routes wrapped with auth middleware when configured

The returned *Group owns the spawned servers; it shuts them down automatically when ctx is cancelled, or explicitly via Group.Shutdown. Returns nil when no servers were started (nil cfg, no eligible agents).

func StartServersGeneric

func StartServersGeneric(ctx context.Context, cfg *GenericServerConfig) *Group

StartServersGeneric starts A2A servers using runtime-agnostic lookup/query callbacks.

func (*Group) Shutdown added in v0.1.8

func (g *Group) Shutdown(ctx context.Context)

Shutdown gracefully stops all servers in the group. It blocks until every server's Shutdown returns or ctx expires. Subsequent calls are no-ops.

func (*Group) Wait added in v0.1.8

func (g *Group) Wait()

Wait blocks until every server goroutine has exited. Useful in tests.

type Handler

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

Handler serves A2A protocol endpoints on the SDK's shared mux. This is for the "embedded" A2A access (via the SDK handler), as opposed to the per-agent servers launched by StartServers.

func NewHandler

func NewHandler(svc *Service) *Handler

NewHandler creates an A2A HTTP handler.

func (*Handler) Register

func (h *Handler) Register(mux *http.ServeMux)

Register mounts A2A routes on the given mux.

type JSONRPCError

type JSONRPCError struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data,omitempty"`
}

JSONRPCError is a JSON-RPC 2.0 error object.

type JSONRPCRequest

type JSONRPCRequest struct {
	JSONRPC string          `json:"jsonrpc"`
	Method  string          `json:"method"`
	Params  json.RawMessage `json:"params,omitempty"`
	ID      interface{}     `json:"id,omitempty"`
}

JSONRPCRequest is a JSON-RPC 2.0 request for A2A.

type JSONRPCResponse

type JSONRPCResponse struct {
	JSONRPC string          `json:"jsonrpc"`
	Result  json.RawMessage `json:"result,omitempty"`
	Error   *JSONRPCError   `json:"error,omitempty"`
	ID      interface{}     `json:"id,omitempty"`
}

JSONRPCResponse is a JSON-RPC 2.0 response for A2A.

type Message

type Message struct {
	Role  Role            `json:"role"`
	Parts []Part          `json:"parts"`
	Raw   json.RawMessage `json:"-"`
}

Message represents a communication turn in A2A.

type Part

type Part struct {
	Type     string                 `json:"type"`
	Text     string                 `json:"text,omitempty"`
	URI      string                 `json:"uri,omitempty"`
	MimeType string                 `json:"mimeType,omitempty"`
	Data     map[string]interface{} `json:"data,omitempty"`
}

Part represents a content part in a message.

type QueryResult

type QueryResult struct {
	MessageID      string
	ConversationID string
	Content        string
}

QueryResult is the minimal result needed to translate an agent query into an A2A task.

type Role

type Role string

Role represents the sender role in a message.

const (
	RoleUser  Role = "user"
	RoleAgent Role = "agent"
)

type SendMessageRequest

type SendMessageRequest struct {
	Messages  []Message `json:"messages,omitempty"`
	Message   *Message  `json:"message,omitempty"`
	TaskID    string    `json:"taskId,omitempty"`
	ContextID string    `json:"contextId,omitempty"`
}

SendMessageRequest is the input for the message/send operation. Supports both single Message (legacy) and Messages (batch) fields.

func (*SendMessageRequest) EffectiveMessages

func (r *SendMessageRequest) EffectiveMessages() []Message

EffectiveMessages returns Messages if set, otherwise wraps Message into a slice.

type SendMessageResponse

type SendMessageResponse struct {
	Task Task `json:"task"`
}

SendMessageResponse is the output for the message/send operation.

type ServerConfig

type ServerConfig struct {
	// AgentService is the agent query service.
	AgentService *agentsvc.Service
	// AgentFinder resolves agents by ID.
	AgentFinder agentmodel.Finder
	// AgentIDs is the list of agent IDs to check for A2A serving.
	AgentIDs []string
	// ApplyUserCred is an optional callback to inject user credentials
	// into the context for agents with UserCredURL configured.
	// Signature: func(ctx context.Context, credURL string) (context.Context, error)
	ApplyUserCred func(ctx context.Context, credURL string) (context.Context, error)
	// JWTService verifies inbound bearer tokens for protected A2A endpoints.
	JWTService *svcauth.JWTService
	// TokenProvider, when set, allows the A2A auth middleware to register
	// inbound tokens so mid-turn refresh works via EnsureTokens.
	TokenProvider tokenpkg.Provider
}

ServerConfig holds configuration for the A2A server launcher.

type Service

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

Service manages A2A protocol operations. It is stateless — for server-side (exposing agents as A2A), it bridges to agent.Query() and the conversation system holds all state. For client-side (consuming external A2A agents), see Client.

func New

func New(agent *agentsvc.Service, finder agentmodel.Finder) *Service

New creates an A2A service.

func (*Service) GetAgentCard

func (s *Service) GetAgentCard(ctx context.Context, agentID string) (*AgentCard, error)

GetAgentCard returns the A2A agent card for the given agent ID.

func (*Service) ListA2AAgents

func (s *Service) ListA2AAgents(ctx context.Context, agentIDs []string) ([]string, error)

ListA2AAgents returns agent IDs that have A2A serving enabled.

func (*Service) SendMessage

func (s *Service) SendMessage(ctx context.Context, agentID string, req *SendMessageRequest) (*SendMessageResponse, error)

SendMessage sends a message to an A2A agent via agent.Query() and returns the result as an A2A task envelope. The conversation system tracks all state.

type Task

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

Task is the A2A protocol response envelope. It is not persisted — for the server side the conversation is the state, for the client side the task is ephemeral (result of a tool call).

func (*Task) Touch

func (t *Task) Touch(state TaskState)

Touch sets the task state and updates the timestamp.

type TaskArtifactUpdateEvent

type TaskArtifactUpdateEvent struct {
	TaskID    string                 `json:"taskId"`
	ContextID string                 `json:"contextId,omitempty"`
	Kind      string                 `json:"kind"` // "artifact-update"
	Artifact  Artifact               `json:"artifact"`
	Append    bool                   `json:"append,omitempty"`
	LastChunk bool                   `json:"lastChunk,omitempty"`
	Metadata  map[string]interface{} `json:"metadata,omitempty"`
}

TaskArtifactUpdateEvent is a streaming event for task artifact delivery.

func NewArtifactEvent

func NewArtifactEvent(task *Task, art Artifact, appendFlag, lastChunk bool) *TaskArtifactUpdateEvent

NewArtifactEvent creates a TaskArtifactUpdateEvent from a task and artifact.

type TaskState

type TaskState string

TaskState represents the state of a task.

const (
	TaskStatePending      TaskState = "pending"
	TaskStateRunning      TaskState = "running"
	TaskStateCompleted    TaskState = "completed"
	TaskStateFailed       TaskState = "failed"
	TaskStateCanceled     TaskState = "canceled"
	TaskStateBlocked      TaskState = "blocked"
	TaskStateAuthRequired TaskState = "auth-required"
)

func (TaskState) IsTerminal

func (s TaskState) IsTerminal() bool

IsTerminal returns true if the state is a final state.

type TaskStatus

type TaskStatus struct {
	State     TaskState `json:"state"`
	Message   *Part     `json:"message,omitempty"`
	Error     *string   `json:"error,omitempty"`
	UpdatedAt time.Time `json:"updatedAt"`
}

TaskStatus tracks task progress.

type TaskStatusUpdateEvent

type TaskStatusUpdateEvent struct {
	TaskID    string                 `json:"taskId"`
	ContextID string                 `json:"contextId,omitempty"`
	Kind      string                 `json:"kind"` // "status-update"
	Status    TaskStatus             `json:"status"`
	Final     bool                   `json:"final"`
	Metadata  map[string]interface{} `json:"metadata,omitempty"`
}

TaskStatusUpdateEvent is a streaming event for task status changes.

func NewStatusEvent

func NewStatusEvent(task *Task, final bool) *TaskStatusUpdateEvent

NewStatusEvent creates a TaskStatusUpdateEvent from a task.

Jump to

Keyboard shortcuts

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