Current section
Files
Jump to
Current section
Files
examples/demo.exs
# Run with: mix run examples/demo.exs
# ─── 1. Define Agents ────────────────────────────────────────────────
defmodule Demo.EchoAgent do
use A2A.Agent,
name: "echo",
description: "Echoes messages back",
skills: [
%{id: "echo", name: "Echo", description: "Repeats your input", tags: ["demo"]}
]
@impl A2A.Agent
def handle_message(message, _context) do
text = A2A.Message.text(message) || ""
{:reply, [A2A.Part.Text.new("You said: #{text}")]}
end
end
defmodule Demo.PizzaAgent do
use A2A.Agent,
name: "pizza-bot",
description: "Takes pizza orders (multi-turn)",
skills: [
%{id: "order", name: "Order Pizza", description: "Place a pizza order", tags: ["food"]}
]
@impl A2A.Agent
def handle_message(message, context) do
text = A2A.Message.text(message) || ""
cond do
# First message — ask for size
length(context.history) == 1 ->
{:input_required, [A2A.Part.Text.new("What size? (small/medium/large)")]}
# Second message — ask for toppings
length(context.history) == 3 ->
{:input_required, [A2A.Part.Text.new("What toppings? (e.g., pepperoni, mushroom)")]}
# Third message — confirm order
true ->
first_msg = A2A.Message.text(Enum.at(context.history, 0))
size = A2A.Message.text(Enum.at(context.history, 2))
toppings = text
{:reply,
[
A2A.Part.Text.new("Order confirmed!"),
A2A.Part.Data.new(%{
pizza: first_msg,
size: size,
toppings: toppings,
status: "preparing"
})
]}
end
end
end
defmodule Demo.CountdownAgent do
use A2A.Agent,
name: "countdown",
description: "Streams a countdown",
skills: [
%{id: "count", name: "Countdown", description: "Counts down from N", tags: ["demo"]}
]
@impl A2A.Agent
def handle_message(message, _context) do
n =
case Integer.parse(A2A.Message.text(message) || "5") do
{num, _} -> num
:error -> 5
end
stream =
Stream.map(n..1//-1, fn i ->
A2A.Part.Text.new("#{i}...")
end)
{:stream, stream}
end
end
# ─── 2. Start Agents ─────────────────────────────────────────────────
IO.puts("=== A2A Agent Demo ===\n")
{:ok, _} = Demo.EchoAgent.start_link()
{:ok, _} = Demo.PizzaAgent.start_link()
{:ok, _} = Demo.CountdownAgent.start_link()
# ─── 3. Simple Call ───────────────────────────────────────────────────
IO.puts("--- Echo Agent ---")
{:ok, task} = A2A.call(Demo.EchoAgent, "Hello, agent!")
IO.puts("Status: #{task.status.state}")
IO.puts("Reply: #{A2A.Message.text(List.last(task.history))}")
IO.puts("")
# ─── 4. Multi-Turn Conversation ──────────────────────────────────────
IO.puts("--- Pizza Agent (multi-turn) ---")
{:ok, task} = A2A.call(Demo.PizzaAgent, "Margherita please")
IO.puts("[1] Status: #{task.status.state}")
IO.puts(" Agent: #{A2A.Message.text(task.status.message)}")
{:ok, task} = A2A.call(Demo.PizzaAgent, "large", task_id: task.id)
IO.puts("[2] Status: #{task.status.state}")
IO.puts(" Agent: #{A2A.Message.text(task.status.message)}")
{:ok, task} = A2A.call(Demo.PizzaAgent, "pepperoni, olives", task_id: task.id)
IO.puts("[3] Status: #{task.status.state}")
# Show the final artifact
[artifact | _] = task.artifacts
IO.puts(" Reply: #{inspect(Enum.map(artifact.parts, fn
%A2A.Part.Text{text: t} -> t
%A2A.Part.Data{data: d} -> d
end))}")
IO.puts(" History: #{length(task.history)} messages")
IO.puts("")
# ─── 5. Streaming ────────────────────────────────────────────────────
IO.puts("--- Countdown Agent (streaming) ---")
{:ok, task, stream} = A2A.stream(Demo.CountdownAgent, "5")
IO.puts("Status before consuming: #{task.status.state}")
IO.write("Stream: ")
stream
|> Stream.each(fn %A2A.Part.Text{text: text} -> IO.write(text <> " ") end)
|> Stream.run()
IO.puts("🎉")
# Give the cast a moment to process
Process.sleep(10)
{:ok, completed} = Demo.CountdownAgent.get_task(task.id)
IO.puts("Status after consuming: #{completed.status.state}")
IO.puts("Artifacts: #{length(completed.artifacts)}")
IO.puts("")
# ─── 6. Agent Card ───────────────────────────────────────────────────
IO.puts("--- Agent Cards ---")
for mod <- [Demo.EchoAgent, Demo.PizzaAgent, Demo.CountdownAgent] do
card = mod.agent_card()
skills = Enum.map(card.skills, & &1.name) |> Enum.join(", ")
IO.puts(" #{card.name} v#{card.version} — #{card.description} [#{skills}]")
end
IO.puts("\nDone!")