Skip to main content

Modes

A document in suggesting mode records every change as a tracked suggestion instead of applying it. This applies to typing, toolbar commands, and agent tool calls equally — which is what makes “let the model draft it, then review every change” work without any special casing.
Set the starting mode per document, or editor-wide:
defaultDocumentMode seeds the mode; it does not control it. Changing the prop later will not move a document that has already opened — use view.setDocumentMode() for that.
A mode is a stance the user can leave. When a participant must not be able to leave it — a reviewer who may only propose — use a role instead: role="suggester" pins the mode, refuses direct edits, and withholds accept and reject on every surface.

Reviewing

The review controller is the host-facing surface for tracked changes. It is deliberately not an agent tool: it exposes interactive state and moves the caret and viewport.
Subscribe to render your own review UI:

Targeted operations

When you know which suggestions you care about — for instance, everything a particular agent run produced — operate on the IDs directly:
previewCurrent() and previewAll() do the same for the current stop and the whole document. Pass null to clear a preview.

Display

"final" shows the document as it would read with everything accepted; "original" as it read before. Useful for a read-only “clean copy” toggle without mutating anything.

Direct mode

Sometimes an agent edit should just apply — a formatting sweep, a find-and-replace the user explicitly asked for. Pass directMode per call:
For a delegated agent run, the mode is inherited by every tool call in the loop, so one flag governs the whole task.
Direct mode bypasses the tracked-change trail. Reserve it for changes the user has already approved in your own UI; anything speculative should stay a suggestion.

Attribution

Suggestions carry their author, and agent-authored ones are distinguishable from human edits. review.getState().visibleAgentSuggestionIds narrows to the agent’s own work, and nextAgentSuggestion() steps through only those — enough to build a “review what the AI changed” flow that skips the user’s own typing.

Export

Tracked changes survive exportDocx() as Word revision marks, so a reviewer who opens the file in Word sees the same suggestions, and accepting them there produces the same result as accepting them in Revise.
Suggestions are authored under the identity you pass as currentUser. Without it, every human suggestion exports as reviewer “Anonymous” and agent suggestions as “Revise Agent”. Pass currentUser before anyone edits — the name is stamped at edit time, not at export.

Word round trip: what survives

The DOCX path is the high-fidelity one, and revision marks are part of what it preserves. Concretely, from a Word file, through the editor, and back: One behaviour is worth knowing before you build a test corpus: Tables are covered too: tracked row insertions and deletions (w:trPrw:ins / w:del), cell revisions (w:cellIns, w:cellDel, w:cellMerge), and tracked table property changes (w:tblPrChange) all import as resolvable suggestions and export as the same markup, authors intact. Linked moves round-trip natively: w:moveFrom / w:moveTo pairs import as one atomic move suggestion — accepting either half keeps the text at its destination, rejecting either half restores the original location — and export re-emits the paired move markup. An orphaned or mismatched half falls back to an ordinary insertion or deletion, so unrelated content is never resolved together.

Building your own review panel

listChanges() returns every pending change with the metadata a panel needs, so you can render the list yourself instead of driving the built-in ribbon:
kind is Word’s three — "insert", "delete", "format" — plus "move" for a linked move pair. A replacement is a deletion and an insertion sharing a location, and appears as both — the same way Word counts it. A move is the opposite: ONE change for both halves, with moveSourceBlockIds and moveDestinationBlockIds locating where the text left and where it landed (deletedText and insertedText carry the text at each end), and a single accept or reject settles both locations. author is a person’s name, "Revise Agent", an external agent’s name, or "Anonymous" when no identity was supplied, and imported Word redlines keep their original reviewer. blockIds gives the blocks a change touches, which is what navigateToSuggestion() scrolls to. Wire a row to the controller with the ID:
It is a pull, not a subscription: the list is derived from the document, and recomputing it on every keystroke would be wasteful for a panel that re-renders far less often. Call it when you render — after review.subscribe() tells you the counts moved, for instance. One call walks the document once no matter how many changes are open.