Documentation
¶
Overview ¶
Package a2aclient provides a transport-agnostic A2A client implementation. Under the hood it handles transport protocol negotiation and connection establishment.
A Client can be configured with CallInterceptor middleware and custom transports. If a client is created in multiple places, a Factory can be used to share the common configuration options:
factory := NewFactory(
WithConfig(&a2aclient.Config{...}),
WithInterceptors(loggingInterceptor),
WithGRPCTransport(customGRPCOptions)
)
A client can be created from an a2a.AgentCard or a list of known a2a.AgentInterface descriptions using either package-level functions or Factory methods.
client, err := factory.CreateFromEndpoints(ctx, []a2a.AgentInterface{{URL: url, Transport: a2a.TransportProtocolGRPC}})
// or
card, err := agentcard.DefaultResolved.Resolve(ctx, url)
if err != nil {
log.Fatalf("Failed to resolve an AgentCard: %v", err)
}
client, err := a2aclient.NewFromCard(ctx, card, WithInterceptors(&customInterceptor{}))
An AuthInterceptor provides a basic support for attaching credentials listed as security requirements in agent card to requests. Credentials retrieval logic is application specific and is not handled by the package.
// client setup
store := a2aclient.InMemoryCredentialsStore()
interceptors := WithInterceptors(&a2aclient.AuthInterceptor{Service: store})
client, err := a2aclient.NewFromCard(ctx, card, interceptors)
// session setup
sessionID := newSessionID()
store.Set(sessionID, a2a.SecuritySchemeName("..."), credential)
sessionCtx := a2aclient.WithSessionID(ctx, sessionID)
// credentials will be automatically attached to requests if listed as security requirements
resp, err := client.SendMessage(sessionCtx, params)
Index ¶
- Variables
- func WithSessionID(ctx context.Context, sid SessionID) context.Context
- type AuthCredential
- type AuthInterceptor
- type CallInterceptor
- type CallMeta
- type Client
- func (c *Client) AddCallInterceptor(ci CallInterceptor)
- func (c *Client) CancelTask(ctx context.Context, id *a2a.TaskIDParams) (*a2a.Task, error)
- func (c *Client) DeleteTaskPushConfig(ctx context.Context, params *a2a.DeleteTaskPushConfigParams) error
- func (c *Client) Destroy() error
- func (c *Client) GetAgentCard(ctx context.Context) (*a2a.AgentCard, error)
- func (c *Client) GetTask(ctx context.Context, query *a2a.TaskQueryParams) (*a2a.Task, error)
- func (c *Client) GetTaskPushConfig(ctx context.Context, params *a2a.GetTaskPushConfigParams) (*a2a.TaskPushConfig, error)
- func (c *Client) ListTaskPushConfig(ctx context.Context, params *a2a.ListTaskPushConfigParams) ([]*a2a.TaskPushConfig, error)
- func (c *Client) ResubscribeToTask(ctx context.Context, id *a2a.TaskIDParams) iter.Seq2[a2a.Event, error]
- func (c *Client) SendMessage(ctx context.Context, message *a2a.MessageSendParams) (a2a.SendMessageResult, error)
- func (c *Client) SendStreamingMessage(ctx context.Context, message *a2a.MessageSendParams) iter.Seq2[a2a.Event, error]
- func (c *Client) SetTaskPushConfig(ctx context.Context, params *a2a.TaskPushConfig) (*a2a.TaskPushConfig, error)
- type Config
- type CredentialsService
- type Factory
- type FactoryOption
- func WithConfig(c Config) FactoryOption
- func WithDefaultsDisabled() FactoryOption
- func WithGRPCTransport(opts ...grpc.DialOption) FactoryOption
- func WithInterceptors(interceptors ...CallInterceptor) FactoryOption
- func WithJSONRPCTransport(client *http.Client) FactoryOption
- func WithTransport(protocol a2a.TransportProtocol, factory TransportFactory) FactoryOption
- type InMemoryCredentialsStore
- type JSONRPCOption
- type PassthroughInterceptor
- type Request
- type Response
- type SessionCredentials
- type SessionID
- type Transport
- type TransportFactory
- type TransportFactoryFn
Constants ¶
This section is empty.
Variables ¶
var ErrCredentialNotFound = errors.New("credential not found")
ErrCredentialNotFound is returned by CredentialsService if a credential for the provided (sessionId, scheme) pair was not found.
Functions ¶
func WithSessionID ¶
WithSessionID allows callers to attach a session identifier to the request. CallInterceptor can access this identifier using SessionIDFrom.
Types ¶
type AuthCredential ¶
type AuthCredential string
AuthCredential represents a security-scheme specific credential (eg. a JWT token).
type AuthInterceptor ¶
type AuthInterceptor struct {
PassthroughInterceptor
Service CredentialsService
}
AuthInterceptor implements CallInterceptor. It uses SessionID provided using WithSessionID to lookup credentials and attach them according to the security scheme specified in the agent card. Credentials fetching is delegated to CredentialsService.
type CallInterceptor ¶
type CallInterceptor interface {
// Before allows to observe, modify or reject a Request.
// A new context.Context can be returned to pass information to After.
Before(ctx context.Context, req *Request) (context.Context, error)
// After allows to observe, modify or reject a Response.
After(ctx context.Context, resp *Response) error
}
CallInterceptor can be attached to an Client. If multiple interceptors are added:
- Before will be executed in the order of attachment sequentially.
- After will be executed in the reverse order sequentially.
type CallMeta ¶
CallMeta holds things like auth headers and signatures. In jsonrpc it is passed as HTTP headers, in gRPC it becomes a part of context.Context. Custom protocol implementations can use CallMetaFrom to access this data and perform the operations necessary for attaching it to the request.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client represents a transport-agnostic implementation of A2A client. The actual call is delegated to a specific Transport implementation. CallInterceptor-s are applied before and after every protocol call.
func NewFromCard ¶
NewFromCard is a client Client constructor method which takes an a2a.AgentCard as input. It is equivalent to Factory.CreateFromCard method.
func NewFromEndpoints ¶
func NewFromEndpoints(ctx context.Context, endpoints []a2a.AgentInterface, opts ...FactoryOption) (*Client, error)
NewFromEndpoints is a Client constructor method which takes known a2a.AgentInterface descriptions as input. It is equivalent to Factory.CreateFromEndpoints method.
func (*Client) AddCallInterceptor ¶
func (c *Client) AddCallInterceptor(ci CallInterceptor)
AddCallInterceptor allows to attach a CallInterceptor to the client after creation.
func (*Client) CancelTask ¶
func (*Client) DeleteTaskPushConfig ¶
func (*Client) GetAgentCard ¶
func (*Client) GetTaskPushConfig ¶
func (c *Client) GetTaskPushConfig(ctx context.Context, params *a2a.GetTaskPushConfigParams) (*a2a.TaskPushConfig, error)
func (*Client) ListTaskPushConfig ¶
func (c *Client) ListTaskPushConfig(ctx context.Context, params *a2a.ListTaskPushConfigParams) ([]*a2a.TaskPushConfig, error)
func (*Client) ResubscribeToTask ¶
func (*Client) SendMessage ¶
func (c *Client) SendMessage(ctx context.Context, message *a2a.MessageSendParams) (a2a.SendMessageResult, error)
func (*Client) SendStreamingMessage ¶
func (*Client) SetTaskPushConfig ¶
func (c *Client) SetTaskPushConfig(ctx context.Context, params *a2a.TaskPushConfig) (*a2a.TaskPushConfig, error)
type Config ¶
type Config struct {
// PushConfig specifies the default push notification configuration to apply for every Task.
PushConfig *a2a.PushConfig
// AcceptedOutputModes are MIME types passed with every Client message and might be used by an agent
// to decide on the result format.
// For example, an Agent might declare a skill with OutputModes: ["application/json", "image/png"]
// and a Client that doesn't support images will pass AcceptedOutputModes: ["application/json"]
// to get a result in the desired format.
AcceptedOutputModes []string
// PreferredTransports is used for selecting the most appropriate communication protocol.
// The first transport from the list which is also supported by the server is going to be used
// to establish a connection. If no preference is provided the server ordering will be used.
// If there's no overlap in supported Transport Factory will return an error on Client
// creation attempt.
PreferredTransports []a2a.TransportProtocol
// Whether client prefers to poll for task updates instead of blocking until a terminal state is reached.
// If set to true, non-streaming send message result might be a Message or a Task in any (including non-terminal) state.
// Callers are responsible for running the polling loop. This configuration does not apply to streaming requests.
Polling bool
}
Config exposes options for customizing Client behavior.
type CredentialsService ¶
type CredentialsService interface {
Get(ctx context.Context, sid SessionID, scheme a2a.SecuritySchemeName) (AuthCredential, error)
}
CredentialsService is used by AuthInterceptor for resolving credentials.
type Factory ¶
type Factory struct {
// contains filtered or unexported fields
}
Factory provides an API for creating a Client compatible with requested transports. Factory is immutable, but the configuration can be extended using WithAdditionalOptions call.
func NewFactory ¶
func NewFactory(options ...FactoryOption) *Factory
NewFactory creates a new Factory applying the provided configurations.
func WithAdditionalOptions ¶
func WithAdditionalOptions(f *Factory, opts ...FactoryOption) *Factory
WithAdditionalOptions creates a new Factory with the additionally provided options.
func (*Factory) CreateFromCard ¶
CreateFromCard returns a Client configured to communicate with the agent described by the provided a2a.AgentCard or fails if we couldn't establish a compatible transport. Config.PreferredTransports field is used to determine the order of connection attempts.
If PreferredTransports were not provided, we start from the PreferredTransport specified in the AgentCard and proceed in the order specified by the AdditionalInterfaces.
The method fails if we couldn't establish a compatible transport.
func (*Factory) CreateFromEndpoints ¶
func (f *Factory) CreateFromEndpoints(ctx context.Context, endpoints []a2a.AgentInterface) (*Client, error)
CreateFromEndpoints returns a Client configured to communicate with one of the provided endpoints. Config.PreferredTransports field is used to determine the order of connection attempts.
If PreferredTransports were not provided, we attempt to establish a connection using the provided endpoint order.
The method fails if we couldn't establish a compatible transport.
type FactoryOption ¶
type FactoryOption interface {
// contains filtered or unexported methods
}
FactoryOption represents a configuration for creating a Client.
func WithConfig ¶
func WithConfig(c Config) FactoryOption
func WithDefaultsDisabled ¶
func WithDefaultsDisabled() FactoryOption
WithDefaultsDisabled attaches call interceptors to clients created by the factory.
func WithGRPCTransport ¶
func WithGRPCTransport(opts ...grpc.DialOption) FactoryOption
WithGRPCTransport create a gRPC transport implementation which will use the provided [grpc.DialOption]s during connection establishment.
func WithInterceptors ¶
func WithInterceptors(interceptors ...CallInterceptor) FactoryOption
WithInterceptors attaches call interceptors to created [Client]s.
func WithJSONRPCTransport ¶
func WithJSONRPCTransport(client *http.Client) FactoryOption
WithJSONRPCTransport returns a Client factory option that enables JSON-RPC transport support. When applied, the client will use JSON-RPC 2.0 over HTTP for all A2A protocol communication as defined in the A2A specification §7.
func WithTransport ¶
func WithTransport(protocol a2a.TransportProtocol, factory TransportFactory) FactoryOption
WithTransport uses the provided factory during connection establishment for the specified protocol.
type InMemoryCredentialsStore ¶
type InMemoryCredentialsStore struct {
// contains filtered or unexported fields
}
InMemoryCredentialsStore implements CredentialsService.
func NewInMemoryCredentialsStore ¶
func NewInMemoryCredentialsStore() *InMemoryCredentialsStore
NewInMemoryCredentialsStore initializes an in-memory implementation of CredentialsService.
func (*InMemoryCredentialsStore) Get ¶
func (s *InMemoryCredentialsStore) Get(ctx context.Context, sid SessionID, scheme a2a.SecuritySchemeName) (AuthCredential, error)
func (*InMemoryCredentialsStore) Set ¶
func (s *InMemoryCredentialsStore) Set(sid SessionID, scheme a2a.SecuritySchemeName, credential AuthCredential)
type JSONRPCOption ¶
type JSONRPCOption func(*jsonrpcTransport)
JSONRPCOption configures optional parameters for the JSONRPC transport. Options are applied during NewJSONRPCTransport initialization.
type PassthroughInterceptor ¶
type PassthroughInterceptor struct{}
PassthroughInterceptor can be used by CallInterceptor implementers who don't need all methods. The struct can be embedded for providing a no-op implementation.
type Request ¶
type Request struct {
// Method is the name of the method invoked on the A2A-server.
Method string
// BaseURL is the URL of the agent interface to which the Client is connected.
BaseURL string
// CallMeta holds request metadata like auth headers and signatures.
Meta CallMeta
// Card is the AgentCard of the agent the client is connected to. Might be nil if Client was
// created directly from server URL and extended AgentCard was never fetched.
Card *a2a.AgentCard
// Payload is the request payload. It is nil if the method does not take any parameters. Otherwise, it is one of a2a package core types otherwise.
Payload any
}
Request represents a transport-agnostic request to be sent to A2A server.
type Response ¶
type Response struct {
// Method is the name of the method invoked on the A2A-server.
Method string
// BaseURL is the URL of the agent interface to which the Client is connected.
BaseURL string
// Err is the error response. It is nil for successful invocations.
Err error
// CallMeta holds request metadata like auth headers and signatures.
Meta CallMeta
// Card is the AgentCard of the agent the client is connected to. Might be nil if Client was
// created directly from server URL and extended AgentCard was never fetched.
Card *a2a.AgentCard
// Payload is the response. It is nil if method doesn't return anything or Err was returned. Otherwise, it is one of a2a package core types otherwise.
Payload any
}
Response represents a transport-agnostic result received from A2A server.
type SessionCredentials ¶
type SessionCredentials map[a2a.SecuritySchemeName]AuthCredential
SessionCredentials is a map of scheme names to auth credentials.
type SessionID ¶
type SessionID string
SessionID is a client-generated identifier used for scoping auth credentials.
type Transport ¶
type Transport interface {
// GetTask calls the 'tasks/get' protocol method.
GetTask(ctx context.Context, query *a2a.TaskQueryParams) (*a2a.Task, error)
// CancelTask calls the 'tasks/cancel' protocol method.
CancelTask(ctx context.Context, id *a2a.TaskIDParams) (*a2a.Task, error)
// SendMessage calls the 'message/send' protocol method (non-streaming).
SendMessage(ctx context.Context, message *a2a.MessageSendParams) (a2a.SendMessageResult, error)
// ResubscribeToTask calls the `tasks/resubscribe` protocol method.
ResubscribeToTask(ctx context.Context, id *a2a.TaskIDParams) iter.Seq2[a2a.Event, error]
// SendStreamingMessage calls the 'message/stream' protocol method (streaming).
SendStreamingMessage(ctx context.Context, message *a2a.MessageSendParams) iter.Seq2[a2a.Event, error]
// GetTaskPushNotificationConfig calls the `tasks/pushNotificationConfig/get` protocol method.
GetTaskPushConfig(ctx context.Context, params *a2a.GetTaskPushConfigParams) (*a2a.TaskPushConfig, error)
// ListTaskPushNotificationConfig calls the `tasks/pushNotificationConfig/list` protocol method.
ListTaskPushConfig(ctx context.Context, params *a2a.ListTaskPushConfigParams) ([]*a2a.TaskPushConfig, error)
// SetTaskPushConfig calls the `tasks/pushNotificationConfig/set` protocol method.
SetTaskPushConfig(ctx context.Context, params *a2a.TaskPushConfig) (*a2a.TaskPushConfig, error)
// DeleteTaskPushNotificationConfig calls the `tasks/pushNotificationConfig/delete` protocol method.
DeleteTaskPushConfig(ctx context.Context, params *a2a.DeleteTaskPushConfigParams) error
// GetAgentCard resolves the AgentCard.
// If extended card is supported calls the 'agent/getAuthenticatedExtendedCard' protocol method.
GetAgentCard(ctx context.Context) (*a2a.AgentCard, error)
// Clean up resources associated with the transport (eg. close a gRPC channel).
Destroy() error
}
A2AClient defines a transport-agnostic interface for making A2A requests. Transport implementations are a translation layer between a2a core types and wire formats.
func NewGRPCTransport ¶
func NewGRPCTransport(conn *grpc.ClientConn) Transport
NewGRPCTransport exposes a method for direct A2A gRPC protocol handler.
func NewGRPCTransportFromClient ¶ added in v0.3.3
func NewGRPCTransportFromClient(client a2apb.A2AServiceClient) Transport
NewGRPCTransportFromClient creates a gRPC transport where the connection is managed externally and encapsulated in the service client. The transport's Destroy method is a no-op.
func NewJSONRPCTransport ¶
NewJSONRPCTransport creates a new JSON-RPC transport for A2A protocol communication. By default, an HTTP client will use a 3-minute timeout. For production deployments, provide a client with appropriate timeout, retry policy, and connection pooling configured for your requirements.
To create an A2A client with custom HTTP client use WithJSONRPCTransport option:
httpClient := &http.Client{Timeout: 5 * time.Minute}
client := NewFromCard(ctx, card, WithJSONRPCTransport(httpClient))
type TransportFactory ¶
type TransportFactory interface {
Create(ctx context.Context, url string, card *a2a.AgentCard) (Transport, error)
}
TransportFactory creates an A2A protocol connection to the provided URL.