# WebUI Preview — webui.pydantic.work Internal maintainer preview environment for `pydantic/ai-chat-ui` and `pydantic-ai`. The public `/` Agent Lab runs Python in Pyodide. The protected `/previews` console runs full ai-chat-ui frontend bundles in Cloudflare containers. The private Preview Console models a session as: 1. an immutable ai-chat-ui frontend build, cached in R2 by commit SHA; 2. a pydantic-ai runtime ref, either PyPI release or resolved commit SHA; 3. a saved Python agent definition that must define `agent`. Session specs and agent definitions live in D1 (`pydantic-webui-db`) with immutable version rows. Browser API keys stay in localStorage and are sent only when a session launches or relaunches. ## Browser UI - `/` — public browser Agent Lab. - `/previews` — protected private build/session console. - `/webui/:sessionId` — full-page iframe to the running AgentContainer. - legacy `/webui/:branchKey/:versionSlug` URLs redirect to `/previews`. ## API endpoints All private routes require a cookie session. `/api/versions`, `/api/proxy/*`, and `/api/wheels/mirror/*` remain public for the Agent Lab. | Method | Path | Notes | | --- | --- | --- | | GET | `/health` | Liveness. | | GET | `/api/versions` | PyPI pydantic-ai releases via sandbox-worker. | | POST | `/api/frontend-builds` | Body `{ input, force? }`; input can be PR number/URL, branch/tag/SHA, commit URL, tree URL, or repo URL. | | GET | `/api/frontend-builds` | List cached frontend builds. | | GET | `/api/frontend-builds/:sha/status` | Poll build state; uploads R2 archive when ready. | | DELETE | `/api/frontend-builds/:sha` | Delete frontend build metadata/archive. | | GET | `/api/runtime/resolve?input=X` | Resolve pydantic-ai PR/URL/branch/SHA through sandbox-worker. | | POST | `/api/agent-definitions` | Create saved Python agent definition. | | GET | `/api/agent-definitions` | List saved definitions. | | GET/PUT/DELETE | `/api/agent-definitions/:id` | Read/update/soft-delete definition. Code edits append versions. | | POST | `/api/sessions` | Create session, snapshot agent definition version, launch container. | | GET | `/api/sessions` | List sessions. | | GET/PUT/DELETE | `/api/sessions/:id` | Read/update/soft-delete session. Updates append versions and relaunch. | | POST | `/api/sessions/:id/launch` | Relaunch latest spec with current browser-sent env values. | | GET | `/api/sessions/:id/status` | Container state, normalized to `starting` / `ready` / `stopped`. | | GET | `/api/sessions/:id/app/*` | Proxy to the AgentContainer app. | | GET | `/internal/frontend-builds/:sha/archive` | R2 archive endpoint consumed by AgentContainer. | ## Notes for Agents - Do not persist API key values server-side. Persist only env var names. - `server.py` executes the saved Python code and requires it to define `agent = Agent(...)`; it still serves a Starlette app from `agent.to_web()`. - Status polling must not wake stopped containers. Relaunch through `POST /api/sessions/:id/launch`. - Iframe API routing uses the `webui-session={sessionId}` cookie, never referer-based routing. Legacy tuple cookies are still accepted server-side.