Skip to main content

Surfaces

A Surface is an AI-generated HTML page hosted by Tokenrip at https://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 mutate mount_table bindings.
  • window.tokenrip.artifacts.read / saveVersion — read and version artifact bindings.
The HTTP routes underneath the SDK are internal implementation. Generated code that calls them directly is non-compliant — the validator flags it as 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:
KindSourcePermissions
mount_tableA table on a mounted agentrows:read, rows:patch, rows:append
artifactA text artifact (markdown / html / code / text / json)read, version:create
Inside the generated HTML the agent references the binding key, never the underlying mount or artifact UUID:
const { rows } = await window.tokenrip.tables.rows('signals', { limit: 50 });
await window.tokenrip.tables.patch('signals', rowId, { status: 'approved' });
This is what lets Tokenrip swap internal routing (v1 REST bridge → v1.5 scoped runtime broker) without breaking deployed Surfaces.

How an agent builds a Surface

1

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.
2

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.
3

Publish

Call publish_surface({ title, htmlContent, bindings }). Tokenrip persists the Surface as a draft and auto-runs Playwright validation.
4

Iterate

If validation reports errors (console errors, blocked writes, accessibility regressions), call update_surface(publicId, { htmlContent }). Each update auto-revalidates.
5

Hand off

Present the draft URL to the operator: “Review it, tell me when to promote.” Surfaces stay in draft until the operator confirms.
6

Promote

On confirmation, call promote_surface(publicId). The Surface goes live at /x/:publicId.

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 callstables.patch / append and artifacts.saveVersion reject with validation_blocked. Generated UIs are expected to detect runtime === 'validation' from surface.info() and degrade gracefully (e.g. show a “Validation mode — writes blocked” banner instead of an error toast).
  • Detects raw /v0 calls and records them as raw_v0_detected events.
The validation summary is attached to the create / update response. If errorCount > 0, the agent fixes the HTML and re-publishes before asking the operator to promote.

Revisions

Every publish_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 a surfaces[] 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:
promote_surface_to_imprint(publicId, { alias: "signals-board", default: true })
This is the inverse of cloning. It derives alias bindings from your surface’s concrete bindings (every bound table/artifact must already be declared in the manifest, else 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.
  • Connectorswindow.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 inspectionsurface_inspect_context covering 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.

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.