Plug for serving A2UI agents over HTTP.
Provides SSE streaming (server→client) and JSON-RPC 2.0 (client→server)
endpoints. Works standalone with Bandit or mounted inside Phoenix via
forward.
Usage
# In a Phoenix router:
forward "/a2ui", A2UI.Plug, agent: MyAgent
# Standalone with Bandit:
Bandit.start_link(plug: {A2UI.Plug, agent: MyAgent})Options
:agent— GenServer name or pid of the agent (required):sse_path— path segments for the SSE endpoint (default:["sse"]):rpc_path— path segments for the JSON-RPC endpoint (default:["rpc"])
Endpoints
GET /sse— opens an SSE stream. The first event contains aconnectionIdthe client must include in subsequent JSON-RPC calls.POST /rpc— accepts JSON-RPC 2.0 requests. Methods:a2ui.action,a2ui.error.
CORS
This plug does not set CORS headers. If your SSE/RPC endpoints are
accessed from a different origin, add a CORS plug (e.g. cors_plug)
upstream in your pipeline.
Security
The connectionId returned by the SSE endpoint acts as a bearer
token — any client that knows the ID can send JSON-RPC requests for
that session. The ID is a 128-bit cryptographically random value, so
brute-force guessing is infeasible. To protect against leakage:
- Serve SSE and RPC endpoints over HTTPS only
- Do not log
connectionIdvalues at non-debug levels - Add application-layer authentication upstream if stricter session isolation is required