Skip to main content
The SDK exposes Revise’s canonical document-local tool subset. The tools are JSON-schema described, safe to call without React state or browser focus, and operate on semantic document structure rather than UI geometry.

The loop

That is the whole integration: schemas out, results back in. The definitions are generated from the same source as Revise’s production agent, so they carry the descriptions and constraints the tools were designed with.

Results

Both surfaces — this one and @reviseio/sdk/backend — return the same discriminated envelope, so result handling is shared verbatim between web and Node:
A rejected edit resolves — it does not throw. Always check ok, and feed error.message back to the model: it explains why a call failed in terms the model can act on, which is usually the difference between a retry that works and one that repeats the mistake. (tools.call() is the throwing variant for application code, raising a typed ReviseToolError.)
Read and search tools return context.html: HTML that preserves block IDs, inline formatting, tables, and notes rather than flattening the document to plain text. Those IDs are what mutation tools target, so the read/act cycle composes. Suggesting-posture mutations report the tracked records they created in suggestionIds — feed them straight to review.acceptSuggestions().

Working with blocks

The model reads a window of the document, then edits by block ID:
replace operates inside one block. Two edits in different blocks are two calls — a single call with finds spanning blocks fails rather than partially applying.

Editing every match at once

A search of the active document returns a search_result_id standing for the whole unpaginated match set. Pass it to replace, replace_block, style_blocks, or remove_blocks instead of an id, and the edit applies independently to every matched block — no paging through IDs, no call per occurrence:
The reference is scoped to the editor session that produced it, and is rejected once the matched blocks have changed underneath it — nothing is partially applied. Re-run search_document and use the new ID.

Routing to a document

Every tool schema carries an optional document_id. Omit it for the active document, or target any ready document in the same editor:

Suggestions or direct edits

Mutations land as tracked changes by default, whatever mode the editor’s own typing surface is in. Pass directMode to apply them outright:
See tracked changes for when that is appropriate.

What is not a tool

Review navigation, comment-panel state, focus, viewport, zoom, and direct canvas rendering are host concerns, not tools in this external catalogue. An agent should not be clicking “next suggestion” — it should be making semantic edits and letting your UI present them. A delegated Revise agent can inspect the mounted canvas with its internal render_document_pages tool. See architecture and delegation. The full catalogue is in the tool reference.

Node: semantic editing without an editor

@reviseio/sdk/backend binds the same deterministic definitions and executor to a host-owned Y.Doc; no model or React mount is involved. (Full surface — conversion, room lifecycle, and the session API — in the backend reference.) A session is document-scoped, retains search references across calls, and must be disposed. Disposal releases Revise observers but deliberately leaves your Y.Doc alive. Because the session is bound to one document, its schemas and descriptions carry no document_id. Literal tool names infer their exact schema input and structured output. Use call() in ordinary application code; it returns the successful response directly and throws ReviseToolError for an expected tool rejection. Use execute() when you want a discriminated result, or executeDynamic() for untrusted model-provided names and JSON. Every path is serialized in arrival order on one session. Switch with document.setSuggestingMode() and document.setEditingMode(); each call captures the mode when submitted, so toggling is deterministic even with queued work.
For a model-driven loop, keep expected failures as data:
Read/search response.context.html is constrained Revise semantic HTML: semantic document markup with stable block IDs for paragraphs, formatted runs, tables, comments, and notes where supported. Structured tool metadata is in the inferred response.data; the concise model-oriented summary is response.message. Structural insertion and whole-block replacement accept this dialect because it is safer than constructing DocRoot or OOXML. It is not arbitrary browser HTML/CSS and is not a lossless web representation of unsupported Word geometry. The Yjs-backed Revise model remains authoritative, DOCX remains the import/export format, and executing a tool does not reparse untouched content through HTML. Do not mutate DocRoot directly. Existing conversion calls may still return that type for compatibility, but the supported server mutation contract is (await createServerDocumentSession(ydoc, ...)).tools.