> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agenticenv.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# A2A

> Expose agents as A2A HTTP servers or connect to remote A2A agents as tools

[A2A (Agent-to-Agent)](https://github.com/a2aproject/A2A) 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:

| Route                              | Purpose                                                                              |
| ---------------------------------- | ------------------------------------------------------------------------------------ |
| `GET /.well-known/agent-card.json` | Agent card — name, description, skills, streaming capability, supported auth schemes |
| `POST /`                           | JSON-RPC v2 only — `SendMessage`, `SendStreamingMessage`, `GetTask`, etc.            |

<Warning>
  The server accepts **JSON-RPC v2 only** (PascalCase methods: `SendMessage`, `SendStreamingMessage`, `GetTask`). Legacy slash-style method strings and HTTP REST paths are not supported.
</Warning>

```go theme={null}
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

```go theme={null}
agent.WithA2AServer(&agent.A2AServerConfig{
    Hostname:     "0.0.0.0",
    Port:         8080,
    BearerTokens: []string{os.Getenv("A2A_SERVER_TOKEN")},
    AgentCard:    &interfaces.A2AAgentCard{ /* optional overrides */ },
})
```

| Field          | Default         | Description                                                                                            |
| -------------- | --------------- | ------------------------------------------------------------------------------------------------------ |
| `Hostname`     | `localhost`     | Bind address — use `0.0.0.0` for external connections                                                  |
| `Port`         | `9999`          | TCP port                                                                                               |
| `BearerTokens` | empty (no auth) | Static pre-shared bearer tokens — enforced on every inbound call. The agent card endpoint stays public |
| `AgentCard`    | auto-generated  | Override card fields — merged with agent name, tools, and listen URL                                   |

<Note>
  Currently supported auth scheme: **static bearer token**. OAuth 2.0 / OIDC, API key, and mTLS are planned but not yet implemented.
</Note>

See [A2A Server example](/examples/a2a-server).

## 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

```go theme={null}
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

```go theme={null}
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),
)
```

<Note>
  `SkipTLSVerify` is available on client config for local HTTPS development only — avoid using it in production.
</Note>

## Runtime changes

Add or remove A2A agents after `NewAgent` via [`a.A2ARegistry()`](/advanced/dynamic-capabilities) — skills are re-discovered on each run.

## Examples

<CardGroup cols={2}>
  <Card title="A2A Server" icon="play" href="/examples/a2a-server">
    Inbound agent card and JSON-RPC
  </Card>

  <Card title="A2A Config" icon="play" href="/examples/a2a-config">
    Outbound WithA2AConfig
  </Card>

  <Card title="A2A Client" icon="play" href="/examples/a2a-client">
    Outbound WithA2AClients
  </Card>
</CardGroup>

## Related

<CardGroup cols={2}>
  <Card title="Sub-agents" icon="sitemap" href="/features/sub-agents">
    In-process specialist delegation
  </Card>

  <Card title="Approvals" icon="shield-check" href="/features/approvals">
    A2A skills follow the same approval policy
  </Card>

  <Card title="Streaming" icon="wave-pulse" href="/getting-started/streaming">
    A2A streaming via SendStreamingMessage
  </Card>

  <Card title="Configuration" icon="sliders" href="/getting-started/configuration">
    WithA2AConfig, WithA2AServer, WithA2AClients
  </Card>
</CardGroup>
