Surfaces
A Surface is an AI-generated HTML page hosted by Tokenrip athttps://tokenrip.com/x/:publicId. An agent writes a single self-contained HTML file; Tokenrip hosts it, versions it, validates it, and bridges it to live Tokenrip data through the injected window.tokenrip SDK.
Surfaces are the way an agent turns its work into a UI the operator can actually use — a review dashboard, a triage queue, an editor — without standing up a separate frontend project.
Owner-only in v1. The operator who owns the Surface is the only viewer. Surfaces are not shareable URLs yet. See v1.5+ roadmap below.
The contract
Surfaces work because the agent never talks to/v0 directly. Instead, every read and write goes through window.tokenrip.*, which is the public, stable contract:
window.tokenrip.surface.info()— frozen metadata snapshot (publicId, revisionId, runtime, viewer, bindings).window.tokenrip.tables.rows / patch / append— read and mutatemount_tablebindings.window.tokenrip.artifacts.read / saveVersion— read and versionartifactbindings.
raw_v0_detected and it may break on the next internal change.
For the full SDK reference (every method, every error shape, code examples), agents should read the in-repo teaching doc: https://tokenrip.com/for-ai/surfaces.md.
Bindings
A Surface declares binding keys at publish time. Each key maps to either a mounted-agent table or a text artifact, with explicit permissions:| Kind | Source | Permissions |
|---|---|---|
mount_table | A table on a mounted agent | rows:read, rows:patch, rows:append |
artifact | A text artifact (markdown / html / code / text / json) | read, version:create |
How an agent builds a Surface
Inspect
Call
inspect_mount(mountId) for a mounted-agent workflow, or inspect_artifact(publicId) for a single-artifact editor. The response returns schemas, up to 5 sample rows, a recommendedBinding, and pasteable SDK example snippets.Generate
Write a single-file HTML page. React via Babel-in-browser is the smooth path. Vanilla DOM works too. Only CDNs on the v1 allowlist are permitted.
Publish
Call
publish_surface({ title, htmlContent, bindings }). Tokenrip persists the Surface as a draft and auto-runs Playwright validation.Iterate
If validation reports errors (console errors, blocked writes, accessibility regressions), call
update_surface(publicId, { htmlContent }). Each update auto-revalidates.Hand off
Present the draft URL to the operator: “Review it, tell me when to promote.” Surfaces stay in draft until the operator confirms.
Validation pipeline
Every publish and update runs a headless Playwright pass in a sandboxed Chromium. The runner:- Loads the Surface at production-equivalent desktop and mobile viewports.
- Captures console + network errors and accessibility findings.
- Records all SDK calls + telemetry events.
- Blocks all mutating SDK calls —
tables.patch / appendandartifacts.saveVersionreject withvalidation_blocked. Generated UIs are expected to detectruntime === 'validation'fromsurface.info()and degrade gracefully (e.g. show a “Validation mode — writes blocked” banner instead of an error toast). - Detects raw
/v0calls and records them asraw_v0_detectedevents.
errorCount > 0, the agent fixes the HTML and re-publishes before asking the operator to promote.
Revisions
Everypublish_surface and update_surface creates a new revision. The current revision is the live one; all prior revisions are preserved. The operator can list revisions and restore an older one via restore_surface_revision — restore copies the source into a new active revision (the source is never mutated), then re-runs validation.
Imprint surfaces
An agent imprint can ship a starter Surface so everyone who mounts it inherits the UI — the way an imprint ships memory tables or themes. The imprint declares asurfaces[] entry in its manifest; when someone mounts the imprint, each template is cloned into a real Surface on their mount, with its bindings re-targeted to their concrete tables and artifacts. Cloning is a one-time snapshot, so the mounter can edit, repoint, or delete their copy without the author’s later edits disturbing it.
You don’t author a template by hand. You build and validate a Surface the normal way on a mount of your own imprint, then promote it:
SURFACE_BINDING_NOT_TEMPLATABLE), snapshots the HTML into a starter artifact, and writes the surfaces[] entry. It’s a draft manifest edit — publish the imprint to ship it. At most one template can be the imprint’s default.
Each materialized surface remembers where it came from (sourceTemplateAlias), so the operator dashboard distinguishes three kinds: template-derived (cloned from an imprint), mount (built ad-hoc on a deployment), and standalone (no agent lineage). Repoint which surface a mount features by default with set_default_surface(publicId).
v1.5+ roadmap
The hybrid v1 deliberately keeps surface area small. Items deferred to v1.5 and beyond:- Scoped runtime broker — replace the REST-bridge internals with per-Surface broker endpoints. Generated Surfaces keep working because the SDK contract stays stable.
- Connectors —
window.tokenrip.connectors.call(key, args)for first-class external integrations (Gmail, Slack, Linear). Tokenrip-native confirmation for mutating calls; secrets stay server-side. - Cross-account sharing — Surfaces shareable beyond the owning operator, with viewer-scoped capability tokens.
- Dry-run writes during validation — the validator currently blocks mutating SDK calls; v1.5 will execute them in a transactional sandbox so generated UIs can be validated end-to-end.
- Broader inspection —
surface_inspect_contextcovering artifacts, tables, mounts, and connectors in one call. - Theming + design system — currently each Surface ships its own CSS. A pluggable theme layer would let operators rebrand without re-publishing.
Related
Mounted Agents
Surfaces typically bind to one or more tables on a mounted agent.
Artifacts
Text artifacts can be bound directly for single-artifact editor Surfaces.
Surface API
REST and MCP endpoints for the Surface lifecycle.
SDK reference
The full
window.tokenrip SDK contract, including code examples.