This guide explains how to use ADK Elixir as a drop-in backend replacement for the adk-web React frontend.
Overview
The ADK.Phoenix.WebRouter module provides HTTP endpoints that match the Python ADK's adk web FastAPI server exactly, enabling the adk-web frontend to work with an Elixir backend without modification.
Quick Start
1. Add Dependencies
Ensure your mix.exs includes:
{:adk, path: "../adk-elixir"}, # or from hex
{:plug, "~> 1.14"},
{:jason, "~> 1.4"},
{:bandit, "~> 1.0"}, # or {:plug_cowboy, "~> 2.5"}2. Define Your Agents
Create an agent loader — either a map or a module:
# Simple map-based loader
agents = %{
"my_agent" => ADK.Agent.LlmAgent.new(
name: "assistant",
model: "gemini-flash-latest",
instruction: "You are a helpful assistant."
)
}
# Or a module-based loader
defmodule MyApp.AgentLoader do
def list_agents, do: ["my_agent"]
def list_agents_detailed do
[%{
name: "my_agent",
root_agent_name: "assistant",
description: "A helpful assistant",
language: "elixir",
is_computer_use: false
}]
end
def load_agent("my_agent") do
ADK.Agent.LlmAgent.new(
name: "assistant",
model: "gemini-flash-latest",
instruction: "You are a helpful assistant."
)
end
def load_agent(_), do: nil
end3. Start the Server
# Standalone with Bandit
opts = [
agent_loader: agents, # or MyApp.AgentLoader
session_store: {ADK.Session.Store.InMemory, []}
]
Bandit.start_link(
plug: {ADK.Phoenix.WebRouter, opts},
port: 8000
)Or in a Phoenix router:
# In your router.ex
forward "/api", ADK.Phoenix.WebRouter,
agent_loader: MyApp.AgentLoader,
session_store: {ADK.Session.Store.InMemory, []}4. Connect adk-web Frontend
Point the adk-web frontend at your Elixir server:
# Clone adk-web
git clone https://github.com/google/adk-web
cd adk-web
# Set the backend URL
echo "VITE_API_URL=http://localhost:8000" > .env.local
# Start the frontend
npm install && npm run dev
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /health | Health check |
GET | /version | Version info |
GET | /list-apps | List available agents |
GET | /apps/:app/users/:user/sessions | List sessions |
POST | /apps/:app/users/:user/sessions | Create session |
GET | /apps/:app/users/:user/sessions/:id | Get session |
DELETE | /apps/:app/users/:user/sessions/:id | Delete session |
POST | /run | Run agent (JSON response) |
POST | /run_sse | Run agent (SSE streaming) |
Request/Response Shapes
All shapes match the Python ADK exactly. See the test file at test/adk/phoenix/web_router_test.exs for examples.
POST /run_sse
Request body:
{
"app_name": "my_agent",
"user_id": "user123",
"session_id": "sess456",
"new_message": {
"parts": [{"text": "Hello!"}]
},
"streaming": false
}Response: SSE stream with data: {event_json}\n\n lines.
POST /apps/:app/users/:user/sessions
Request body:
{
"session_id": "optional-custom-id",
"state": {"key": "value"}
}CORS
CORS headers (Access-Control-Allow-Origin: *) are included on all responses by default. The OPTIONS preflight is handled automatically.
Session Persistence
By default, sessions use ADK.Session.Store.InMemory (ETS-backed). For production, use ADK.Session.Store.Ecto with a database backend.