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

# Agent-to-Agent (A2A)

> Cross-system agent communication with authentication and delivery guarantees.

The A2A protocol enables agent communication **across system boundaries** — between services, organizations, or deployment environments. It builds on [internal messaging](/library/messaging) by adding authentication, authorization, and external transport.

## Architecture

```mermaid theme={null}
flowchart LR
    subgraph System_A["System A"]
        Agent_A["Agent A"]
        A2A_Client["A2A Client"]
    end

    subgraph System_B["System B"]
        A2A_Server["A2A Server"]
        Auth["Auth Provider"]
        Agent_B["Agent B"]
    end

    Agent_A --> A2A_Client
    A2A_Client -->|"HTTP/gRPC"| A2A_Server
    A2A_Server --> Auth
    Auth --> A2A_Server
    A2A_Server --> Agent_B
```

## Three integration layers

| Layer                 | What it does                      | When you need it                      |
| --------------------- | --------------------------------- | ------------------------------------- |
| **Internal Protocol** | Typed envelopes with idempotency  | Always (agents in the same system)    |
| **Auth Provider**     | Token validation, caller identity | When agents are in different services |
| **External Adapter**  | HTTP/gRPC transport, discovery    | When agents are in different systems  |

## Request flow

<Steps>
  <Step title="Client builds invocation request">
    ```python theme={null}
    from afk.messaging import AgentInvocationRequest

    request = AgentInvocationRequest(
        run_id="run-42",
        thread_id="thread-42",
        conversation_id="conversation-42",
        correlation_id="analysis-42",
        source_agent="system-a",
        target_agent="analyzer",
        payload={"user_message": "Analyze this dataset"},
        metadata={"source": "system-a"},
        idempotency_key="analysis-42",
    )
    ```
  </Step>

  <Step title="Auth provider validates">
    The server validates the auth token, extracts the caller identity, and checks authorization rules.
  </Step>

  <Step title="Server runs the agent">
    The target agent executes locally with a Runner, using the invocation request as input.
  </Step>

  <Step title="Response returned">
    ```python theme={null}
    response = await client.invoke(request)
    print(response.output)       # Agent output payload
    print(response.success)      # True when handled successfully
    print(response.run_id)       # For tracing
    ```
  </Step>
</Steps>

## Invocation contracts

<Tabs>
  <Tab title="Request">
    ```python theme={null}
    class AgentInvocationRequest(BaseModel):
        run_id: str
        thread_id: str
        conversation_id: str
        correlation_id: str
        idempotency_key: str
        source_agent: str
        target_agent: str
        payload: dict = {}
        metadata: dict = {}
        timeout_s: float | None = None
    ```
  </Tab>

  <Tab title="Response">
    ```python theme={null}
    class AgentInvocationResponse(BaseModel):
        run_id: str
        thread_id: str
        conversation_id: str
        correlation_id: str
        idempotency_key: str
        source_agent: str
        target_agent: str
        success: bool
        output: dict | str | None = None
        error: str | None = None
    ```
  </Tab>
</Tabs>

## Hosting an A2A service

Expose your agents as an A2A-accessible service:

```python theme={null}
from afk.agents import Agent, A2AServiceHost, APIKeyA2AAuthProvider
from afk.core import Runner

# Define the agent
analyzer = Agent(name="analyzer", model="gpt-5.5", instructions="Analyze data.")

# Create auth provider
auth = APIKeyA2AAuthProvider(
    keys={"system-a": "token-abc", "system-c": "token-xyz"},
    server_secret="hmac-secret-for-key-hashing",
)

# Start the server
server = A2AServiceHost(
    agents={"analyzer": analyzer},
    runner_factory=lambda: Runner(),
    auth_provider=auth,
    host="0.0.0.0",
    port=8080,
)
await server.start()
```

## Authentication providers

AFK ships with three auth providers:

<Tabs>
  <Tab title="AllowAll (dev only)">
    Permits all requests without authentication. **Never use in production.**

    ```python theme={null}
    from afk.agents import AllowAllA2AAuthProvider

    auth = AllowAllA2AAuthProvider()
    ```
  </Tab>

  <Tab title="API Key">
    Validates requests against pre-shared API keys with HMAC-SHA256 hashing.

    ```python theme={null}
    from afk.agents import APIKeyA2AAuthProvider

    auth = APIKeyA2AAuthProvider(
        keys={"caller-id": "secret-key"},
        server_secret="hmac-server-secret",
    )
    ```
  </Tab>

  <Tab title="JWT">
    Validates JWT tokens with configurable issuer and audience claims.

    ```python theme={null}
    from afk.agents import JWTA2AAuthProvider

    auth = JWTA2AAuthProvider(
        secret="jwt-signing-secret",
        algorithm="HS256",
        issuer="https://auth.example.com",
        audience="agent-service",
    )
    ```
  </Tab>
</Tabs>

### Google A2A adapter

For interoperability with Google's A2A protocol, use the Google adapter:

```python theme={null}
from afk.agents import GoogleA2AProtocolAdapter

adapter = GoogleA2AProtocolAdapter(client=google_a2a_client)
```

The adapter wraps a configured Google A2A SDK client behind AFK's `AgentCommunicationProtocol`.

## Security considerations

| Concern              | Mechanism                                                        |
| -------------------- | ---------------------------------------------------------------- |
| **Authentication**   | Token-based (API keys, JWT, OAuth)                               |
| **Authorization**    | Per-agent access control (which callers can invoke which agents) |
| **Idempotency**      | `idempotency_key` prevents duplicate processing on retries       |
| **Rate limiting**    | Configure per-caller request limits                              |
| **Input validation** | All requests validated against `AgentInvocationRequest` schema   |
| **Cost isolation**   | Each invocation has its own `FailSafeConfig` budget              |

<Warning>
  **Always authenticate A2A endpoints.** An unauthenticated A2A server allows
  anyone to invoke your agents, consuming your LLM API credits.
</Warning>

## Next steps

<CardGroup cols={2}>
  <Card title="Task Queues" icon="list-check" href="/library/task-queues">
    Async job processing for long-running work.
  </Card>

  <Card title="MCP Server" icon="plug" href="/library/mcp-server">
    Expose tools via the Model Context Protocol.
  </Card>
</CardGroup>
