# `SuperPi.Gateway.AGUI`
[🔗](https://github.com/oleksandr/super-pi-beam/blob/v0.1.0/lib/super_pi/gateway/agui.ex#L1)

[AG-UI](https://docs.ag-ui.com) over Server-Sent Events, forwarded from `SuperPi.Gateway.Router`
at `/agui/v1`. The router's `authenticate`, `reject_when_draining` and `trace_request` plugs
already ran, so this module has no auth of its own.

| Route | Does |
|---|---|
| `POST /agui/v1/run` | Body is a `RunAgentInput` (`threadId`, `runId`, `messages`, `forwardedProps`). Opens the SSE response, submits the last user message and streams the run until it ends. This is the shape that `@ag-ui/client`'s `HttpAgent` expects. |
| `GET /agui/v1/sessions/:id/events` | Attaches to a live conversation. Sends `STATE_SNAPSHOT` and `MESSAGES_SNAPSHOT`, then live events. Keeps the stream open with a comment line every 15 s. |
| `POST /agui/v1/sessions/:id/input` | Sends input into a conversation: `{"type": "prompt", "text": ...}`, `{"type": "permission", "request_id": ..., "option_id": ...}`, `{"type": "answer", "request_id": ..., "value": ...}` or `{"type": "cancel"}`. |

`threadId` maps to a conversation through `SuperPi.Gateway.Sessions` (as `agui:<threadId>`, per
principal). `forwardedProps` may carry `harness` and `executionMode`. A remote mode never goes
above `Permissions.remote_mode/1`.

## Resuming

After a disconnect, `GET .../events` sends a fresh `STATE_SNAPSHOT` and `MESSAGES_SNAPSHOT`. The
snapshot covers whatever was lost in the gap. Exact replay would need a database write per
`text_delta` or an append-only event table, which the snapshot events exist to avoid.

## Backpressure

There is no ack window (the RPC server has one because the client can call `session.ack`). SSE is
one-way and TCP is the backpressure: a failed chunk write cancels the turn. Deltas that arrive within
16 ms are merged into one content event (`SuperPi.Event.Renderer.AGUI.coalesce/1`).

## Prompts

A `permission_request` and a `ui_request` arrive as `CUSTOM` events. The client answers with
`POST .../input` of type `permission` or `answer`. The stream registers as an interactive responder,
so `Permissions` asks instead of blocking. With `?interactive=false` on `/run` the stream does not
register, and `Permissions` blocks as for any other Gateway client.

# `call`

# `init`

---

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