Skip to main content
A2A (Agent-to-Agent) lets you expose an agent as a standards-compliant HTTP server or connect remote A2A agents as tool providers for your LLM.

A2A server

Any agent can be exposed as an A2A HTTP server. Call RunA2A(ctx) after NewAgent — the server blocks until the context is cancelled, then shuts down gracefully. Endpoints:
RoutePurpose
GET /.well-known/agent-card.jsonAgent card — name, description, skills, streaming capability, supported auth schemes
POST /JSON-RPC v2 only — SendMessage, SendStreamingMessage, GetTask, etc.
The server accepts JSON-RPC v2 only (PascalCase methods: SendMessage, SendStreamingMessage, GetTask). Legacy slash-style method strings and HTTP REST paths are not supported.
a, err := agent.NewAgent(
    agent.WithName("my-agent"),
    agent.WithDescription("Helpful assistant exposed as an A2A server."),
    agent.WithLLMClient(llmClient),
    agent.WithStream(true),           // advertises streaming capability in agent card
    agent.WithA2ADefaultServer(),     // binds to localhost:9999, no auth
)
if err != nil {
    return err
}
defer a.Close()

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()

if err := a.RunA2A(ctx); err != nil {
    log.Fatal(err)
}

Custom server config

agent.WithA2AServer(&agent.A2AServerConfig{
    Hostname:     "0.0.0.0",
    Port:         8080,
    BearerTokens: []string{os.Getenv("A2A_SERVER_TOKEN")},
    AgentCard:    &interfaces.A2AAgentCard{ /* optional overrides */ },
})
FieldDefaultDescription
HostnamelocalhostBind address — use 0.0.0.0 for external connections
Port9999TCP port
BearerTokensempty (no auth)Static pre-shared bearer tokens — enforced on every inbound call. The agent card endpoint stays public
AgentCardauto-generatedOverride card fields — merged with agent name, tools, and listen URL
Currently supported auth scheme: static bearer token. OAuth 2.0 / OIDC, API key, and mTLS are planned but not yet implemented.
See A2A Server example.

A2A client

Remote A2A agents connect as tool providers. The SDK resolves the agent card, discovers skills, and registers each skill as a tool (a2a_<server>_<skillId>). Failing fast if a server is unreachable at NewAgent.

WithA2AConfig

import a2apkg "github.com/agenticenv/agent-sdk-go/pkg/a2a"

a, err := agent.NewAgent(
    agent.WithLLMClient(llmClient),
    agent.WithA2AConfig(agent.A2AServers{
        "assistant": {
            URL:     "https://assistant.example.com",
            Timeout: 30 * time.Second,
        },
        "researcher": {
            URL:         "https://researcher.example.com",
            Token:       os.Getenv("A2A_TOKEN"),
            SkillFilter: a2apkg.A2ASkillFilter{AllowSkills: []string{"search", "summarize"}},
            Timeout:     60 * time.Second,
        },
    }),
)

WithA2AClients

import a2aclient "github.com/agenticenv/agent-sdk-go/pkg/a2a/client"

cl, err := a2aclient.NewClient("assistant", "https://assistant.example.com",
    a2aclient.WithTimeout(30*time.Second),
    a2aclient.WithToken(os.Getenv("A2A_TOKEN")),
)
if err != nil {
    return err
}

a, err := agent.NewAgent(
    agent.WithLLMClient(llmClient),
    agent.WithA2AClients(cl),
)
SkipTLSVerify is available on client config for local HTTPS development only — avoid using it in production.

Runtime changes

Add or remove A2A agents after NewAgent via a.A2ARegistry() — skills are re-discovered on each run.

Examples

A2A Server

Inbound agent card and JSON-RPC

A2A Config

Outbound WithA2AConfig

A2A Client

Outbound WithA2AClients

Sub-agents

In-process specialist delegation

Approvals

A2A skills follow the same approval policy

Streaming

A2A streaming via SendStreamingMessage

Configuration

WithA2AConfig, WithA2AServer, WithA2AClients