Dynamic views: let your agent build the UI

Agents can push entire custom HTML interfaces into a Docs document — charts, trackers, dashboards — rendered in sandboxed iframes. Here's how it works and why it's safe.

Text is a wonderful interface and a terrible one. A project plan is text. The burndown chart that tells you whether the plan is on track is not. A decision log is text. The dashboard showing which decisions are still open is not.

Until now, the deal with documents was: if you want UI, leave the document. Today we’re shipping the alternative. In Docs, an AI agent can push its own interface into the document — a self-contained HTML/JS page, rendered live in a panel beside the text.

What it looks like

Your agent calls one endpoint:

POST /api/docs/<id>/views
{
  "kind": "custom",
  "payload": { "html": "<!doctype html><html>...</html>" }
}

The payload is a complete HTML document the agent authored — markup, styles, script, everything. Docs renders it in the views panel next to the editor. Every collaborator on the document sees it.

What agents build with this is up to them, which is precisely the point. In our own use we’ve seen: a Gantt-style timeline distilled from a planning doc; a glossary browser for a spec; a “review status” board summarizing every open annotation and suggestion; a checklist that re-derives itself from the document’s headings. None of these were product features. They were one agent’s idea of the right lens for one document, generated on demand.

How it can possibly be safe

“Arbitrary AI-generated code, executing in a multiplayer web app” should set off alarm bells. Here’s the boundary that makes it sane:

Every custom view renders inside an <iframe sandbox="allow-scripts">without allow-same-origin. The browser treats the view as a foreign, opaque origin. Concretely, the pushed code cannot:

  • read or write the parent page’s DOM,
  • touch cookies, local storage, or auth tokens,
  • reach the document’s live sync connection,
  • navigate the top-level page or open dialogs on its behalf.

It can run scripts and draw pixels inside its own rectangle. That’s it.

Communication happens over a deliberately tiny, versioned postMessage bridge. In v1 it has exactly two messages: getDocument, which returns the markdown, the review index, the actor list, and the current views; and requestRefresh, which signals the agent that a human asked for the view to be regenerated. The bridge only hands the view data that anyone looking at the document can already see — so even a malicious view learns nothing its viewer didn’t already have.

One honest caveat: a sandbox confines code, not pixels. A view can still draw misleading UI inside its own frame, the way any embedded content can. The sandbox guarantees it can’t act outside the frame, can’t exfiltrate your session, and can’t touch the document without going through the same public API as everyone else.

Components included

Raw HTML gives agents power; it doesn’t give them taste. So we publish our design system — the same component library and tokens our own products use — as a hosted ESM bundle with CSS tokens at a stable URL, documented in llm.txt. An agent can import it and produce views that look native to Docs: same surfaces, same hairline borders, same type scale. The difference between “a chart an AI made” and “a chart that belongs here” is a stylesheet, and we ship it.

Why this matters

We think of documents as the durable artifact and chat as the ephemeral one. But agents have mostly been limited to writing prose about their analysis. Dynamic views close the gap: the agent’s analysis can be an interactive artifact that lives with the document, updates when the document changes, and is visible to every collaborator — not a PNG pasted into a chat thread that’s stale on arrival.

The interface stops being something we predicted you’d need and becomes something your agent builds because this document, today, needs it.

Try it end to end: create a document, paste the agent prompt to your AI, drop in some project notes, and ask it to “build a view that tracks the open questions in this doc.” Then change the doc and ask it to refresh. That loop — document, lens, revision — is the product we wanted to exist.