# `A2A`
[🔗](https://github.com/actioncard/a2a-elixir/blob/main/lib/a2a.ex#L1)

Elixir implementation of the Agent-to-Agent (A2A) protocol.

A2A provides a behaviour-based agent framework where agents are local
GenServer processes. Use `A2A.call/3` and `A2A.stream/3` to interact
with agents.

## Quick Start

    # Define an agent
    defmodule MyAgent do
      use A2A.Agent,
        name: "my-agent",
        description: "Does things"

      @impl A2A.Agent
      def handle_message(message, _context) do
        {:reply, [A2A.Part.Text.new("Got: #{A2A.Message.text(message)}")]}
      end
    end

    # Start and call it
    {:ok, _pid} = MyAgent.start_link()
    {:ok, task} = A2A.call(MyAgent, "hello")

# `call`

```elixir
@spec call(GenServer.server(), String.t() | A2A.Message.t(), keyword()) ::
  {:ok, A2A.Task.t() | A2A.Message.t()} | {:error, term()}
```

Sends a message to a local agent and returns the resulting task.

The `agent` can be a module name (registered GenServer) or a PID.
The `message` can be a string, an `A2A.Message.t()`, or a list of parts.

Returns `{:ok, task}`, or `{:ok, message}` when the agent replies
`{:message, parts}` — a bare `A2A.Message.t()` with no task behind it.

## Options

- `:context_id` — associate the message with a conversation context
- `:task_id` — continue an existing task (must be in a non-terminal state)
- `:timeout` — GenServer call timeout in ms (default: `60_000`)

## Examples

    A2A.call(MyAgent, "hello")
    A2A.call(MyAgent, message, context_id: "ctx-123")

    # Multi-turn: continue an input_required task
    {:ok, task} = A2A.call(MyAgent, "order pizza")
    {:ok, task} = A2A.call(MyAgent, "large", task_id: task.id)

# `get_agent_card`

```elixir
@spec get_agent_card(GenServer.server(), keyword()) :: map()
```

Returns the encoded agent card for a local agent.

Fetches the card via GenServer and encodes it using
`A2A.JSON.encode_agent_card/2`. This is useful for serving agent
cards from custom endpoints (e.g., a Phoenix controller) when you
set `agent_card_path: false` on `A2A.Plug`.

## Options

- `:base_url` — the public URL of the agent endpoint (required)
- All other options are forwarded to `A2A.JSON.encode_agent_card/2`

## Examples

    A2A.get_agent_card(MyAgent, base_url: "https://example.com/a2a")
    # => %{"name" => ..., "url" => "https://example.com/a2a", ...}

# `stream`

```elixir
@spec stream(GenServer.server(), String.t() | A2A.Message.t(), keyword()) ::
  {:ok, A2A.Task.t(), Enumerable.t()}
  | {:ok, A2A.Message.t()}
  | {:error, term()}
```

Sends a message to a streaming agent and returns the stream.

The agent's `handle_message/2` must return `{:stream, enumerable}`.
The returned stream is lazy — the caller must consume it.

An agent that replies `{:message, parts}` answers out-of-band instead:
the call returns `{:ok, message}` with no task and no stream.

## Options

- `:context_id` — associate the message with a conversation context
- `:timeout` — GenServer call timeout in ms (default: `60_000`)

## Examples

    A2A.stream(MyAgent, "research topic")
    |> Stream.each(&process/1)
    |> Stream.run()

---

*Consult [api-reference.md](api-reference.md) for complete listing*
