A WordPress plugin where the website has no templates. A short markdown spec
(site-spec.md) is the entire source of truth. Every page is generated on the
fly by an AI agent that reacts to what the visitor does — page load, clicks,
form submits, typing — and renders the HTML for the next page state. Navigation,
a menu, a cart, a checkout form: all invented per-request by the model, with
continuity carried across the session.
It's a proof-of-concept of a "generative UI" / LLM-served site, built as a
consumer of Automattic/agents-api
— a worked example of how to plug a product onto that substrate.
⚠️ Proof of concept. The agent's HTML+JS output is injected into the page by design (this is the whole point), so it is XSS-by-construction. Don't run this on a production site without an output policy. See Security.
Browser shell (iframe) WordPress
───────────────────── ─────────
load / click / submit ──POST /chat──▶ agents-api ──▶ agent-served-site handler
agents/chat │ site-spec.md + session history + event
(canonical) │ │
│ ▼
rendered HTML ◀──── reply ─────────┘ wp-ai-client → AI provider (Claude, …)
(swapped into the iframe)
- The shell (
/?served=1) is a tiny HTML document hosting a sandboxed<iframe>and a small client script. - On every user event the client POSTs a JSON event
(
{"event":"click","action":"navigate","route":"/menu"}) to the canonicalagents-apiREST routePOST /wp-json/agents-api/v1/chat. agents-apidispatches the canonicalagents/chatability to this plugin's handler, which assembles a prompt (site spec + session history + the event), callswp-ai-client(WordPress 7.0 core), and returns the generated HTML as the canonicalreply.- The shell swaps the HTML into the iframe and re-wires its event listeners. The
loop continues, threaded by the
session_id.
| Layer | Owns |
|---|---|
agents-api (substrate) |
The canonical agents/chat contract, the REST route, the handler-dispatch filter, session/run plumbing, and the conversation store (transcript persistence). |
wp-ai-client (WP 7.0 core) |
Provider/model prompt execution. |
| This plugin (consumer) | The site spec, prompt assembly, the chat handler, and the browser shell. |
agents-api ships no AI provider and no chat runtime on purpose — the consumer
brings those. This plugin is that consumer.
Session history is not reinvented here: it's persisted through agents-api's
conversation store (resolved via the wp_agent_conversation_store filter — the
built-in CPT store, enabled by this plugin, or a host's own store), with a
transient fallback when no store is registered. See
includes/class-session-store.php.
- WordPress 7.0+ (ships
wp-ai-clientin core). Automattic/agents-apiactive.- An AI provider registered with
wp-ai-clientand authenticated — e.g. AI Provider for Anthropic. - PHP 8.1+.
- Copy
agent-served-site/intowp-content/plugins/. - Ensure
agents-apiand an AI provider are active and the provider has an API key. - Activate Agent-Served Site.
- Visit
/?served=1.
- The site itself lives in
site-spec.md. Edit it to change what the site is — brand, pages, rules. No code changes needed. You can also swap it at runtime via theagent_served_site_specfilter. - Model — define
AGENT_SERVED_SITE_MODELinwp-config.php(a bare model id orprovider:model). Default:anthropic:claude-haiku-4-5-20251001.
// wp-config.php — higher fidelity, slower:
define( 'AGENT_SERVED_SITE_MODEL', 'anthropic:claude-sonnet-4-6' );The latency of a render is almost entirely output-token generation — network and prompt-processing overhead is ~2s. A full styled page is ~1,200–3,000 output tokens. Two levers keep it snappy:
-
Compact-output instruction in the system prompt (concise CSS, terse markup).
-
A fast model. A full page takes roughly:
Model Full page claude-haiku-4-5-20251001(default)~3–13s claude-sonnet-4-6~25–37s
There is no token streaming in this version, so the whole page must finish before it paints; the shell shows a "Generando…" indicator meanwhile. Streaming (paint as it generates) is the natural next step.
The agent returns HTML — including <style> and <script> — which is rendered
directly. That is intentional for the PoC. The content runs inside a sandboxed
same-origin iframe, and the chat endpoint is opened to anonymous visitors only
for this plugin's agent slug. None of this is safe for production without a strict
output policy. Treat it as a demo.
GPL-2.0-or-later.