Skip to main content

The boundary

The SDK owns
  • Parsing DOCX, Markdown, text, and HTML
  • The document model and its Yjs session
  • Canvas layout, pagination, and rendering
  • Keyboard input, selection, and undo history
  • Tracked changes and comment threads
  • The agent tool runtime
You own
  • The file: where it comes from, where it goes
  • Document IDs and their meaning
  • The collaboration transport, if you want one
  • Accounts, permissions, and tenancy
  • Persistence and versioning
  • Your agent loop and its model
  • Any chrome you choose to render yourself
Nothing in the SDK calls a Revise server. The only network call it can make is to an agent backend you configure explicitly. Collaboration does not change that: the SDK builds the shared document and reads awareness, but the socket is yours to open — see collaboration. And your server can be more than the socket: @reviseio/sdk/backend lets the process that relays updates also create, read, and edit the document itself — see the backend reference.

Canvas, not contenteditable

Revise is not built on ProseMirror, Slate, or a contenteditable DOM. It is a word processor rendered to <canvas>, with its own layout engine, text measurement, and hit testing. That is why page geometry behaves like Word rather than like a web page: real pagination, per-section page sizes and margins, running headers and footers, footnote areas that flow with their references, and text measurement that matches what exports to .docx. The practical consequence for integrators: do not expect to reach into the document via the DOM. Every read and write goes through the handle or the tools. Selection geometry is intentionally not public — there are no canvas rectangles or hit-test APIs — so your UI stays decoupled from Revise’s internals.

Documents are independent sessions

ReviseEditor keeps every open document mounted. Editor-local state survives tab switches: caret and selection, scroll position, formatting context, search, review and comment state, zoom, and in-flight agent runs. Every document-local controller supports two forms of routing:
Collection state comes from editor.documents.getState() and editor.documents.subscribe(). You never need a state round trip before acting on the active document. Tool state is part of that per-document state, not per call: what a document has read, edited, and searched persists across tools.execute() calls, which is what lets a search_result_id from one call target the matches in the next. Reloading a document’s source starts a fresh tool session and retires those references.

Document fragments

Inside one document, content lives in separate streams — the same separation Word makes: This is why inserting a footnote does not shift body block indices, and why an agent reading “block 12” gets body block 12 regardless of how many notes exist.

Editing modes

Every document is in one of three modes, set per document and changed at runtime through view.setDocumentMode():

editing

Changes apply directly. The default.

suggesting

Changes land as tracked suggestions to accept or reject.

viewing

Read-only.
Agent mutations follow the same rule, which is what makes “let the AI draft it, then review every change” work without special-casing. See tracked changes. Mode is a starting point, not a permission: anything holding the handle can change it. When a participant must not be able to edit directly at all, set a role instead — it constrains which modes are reachable and refuses agent tool calls that would exceed it.