This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /guides/document-authoring/ai/agentic-tools.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. Agentic document tools

Agentic tools let the model decide how to handle a user’s request. The model might read the document, search for a paragraph, change wording, format a heading, insert a table, and keep going until the task is done.

That’s the path you want for prompts like “find the launch summary and make it shorter,” “add a table with the next three milestones,” “make the risk level bold,” or “read this contract and update the indemnity clause.”

If you already know what the task is — say, proofreading or translation — agentic tools can be overkill, so use workflows instead. They’re simpler when your app drives the task and needs a structured set of edits back.

How a tool call flows

Your server registers the toolkit’s document tools with your AI framework. When the model decides it wants to edit, it returns a tool call instead of a regular message.

That tool call comes back to the browser. Your code validates it with the toolkit, applies your editor mode policy, and either runs the operation or rejects it. The result goes back to the model so the conversation can continue.

The model never gets to mutate the document. It can ask, and the browser decides.

Choosing tools

getAiToolDefinitions returns every document tool with its schema and metadata:

const definitions = getAiToolDefinitions({
tools: ["read_document", "search_elements", "replace_paragraph"],
});

Pass tools to narrow the list. Smaller tool lists keep the model focused and the prompt cheaper.

Each definition tells you whether the tool reads or writes the document. The read tools are read_document, search_elements, and read_element. The write tools are add_paragraphs, add_section_break, replace_paragraph, replace_text, add_table, replace_table, delete_block, format_text, and format_list.

A rewrite-only assistant probably only needs the read tools plus replace_text and replace_paragraph. A formatting helper might add format_text and format_list.

If your backend isn’t TypeScript, export the tool and prompt definitions as JSON. See non-TypeScript backends.

Use isAiReadToolName and isAiWriteToolName to gate by editor mode in your tool-call handler. Both helpers are exported alongside getAiToolDefinitions. The same capability also lives on each definition as metadata.capability if you’re iterating over definitions.tools directly.

Read tools always run. Write tools should be blocked in View mode and routed through tracked changes in Review mode. See review and approval for the full mode rules and the author-name policy for tracked changes.

Every write tool also accepts an optional reviewComment string. Use it when the user asks for a reviewer-facing motivation, or when your host prompt tells the model to justify its edits as comments. Read tools don’t accept reviewComment.

Executing in the browser

Create a toolkit bound to the live DocAuthEditor and pass the raw tool call to executeTool. This call is the same, regardless of which framework is on the server.

import {
isAiWriteToolName,
} from "@nutrient-sdk/document-authoring-ai";
import { getAiToolkit } from "@nutrient-sdk/document-authoring-ai/editor";
const toolkit = getAiToolkit(editor);
async function runToolCall(rawCall) {
const editorMode = editor.getEditorMode();
const isWriteTool = isAiWriteToolName(rawCall.name);
if (isWriteTool && editorMode === "view") {
return {
ok: false,
error:
"The document is in View mode. Switch to Edit or Review mode before editing.",
};
}
const executed = await toolkit.executeTool(rawCall, {
writeMode: isWriteTool && editorMode === "review"
? "track_changes"
: "apply",
reviewComments: "create",
});
return { ok: true, result: executed };
}

executeTool validates the call before it touches the document. Calls whose name isn’t a real tool are rejected, and so are calls whose arguments don’t match the tool’s schema. If validation fails, executeTool throws. Catch the error, send it back through your chat transport as a tool result, and let the model retry on the next turn.

The result returned by a successful call is what you ship back to the model. For reads, it carries document context the model needs for its next step. For writes, it tells the model what changed and whether it was applied immediately or as a tracked change.

How the result lands back in the conversation depends on your framework. With Vercel AI SDK, you’ll send it through addToolOutput(opens in a new tab) from inside the chat transport. The chat loop setup is in Vercel AI SDK integration. With LangChain, you’ll attach the result to the agent’s tool-call message. The adapter details are in LangChain integration.

Review comments

reviewComment lets the model attach a short reason to a write tool call. The host still decides whether that text becomes a document comment thread.

Enable creation with reviewComments: "create" when you call toolkit.executeTool. The default is reviewComments: "disabled".

type AiToolExecutionOptions = {
writeMode?: "apply" | "track_changes";
reviewComments?: "disabled" | "create";
};
const executed = await toolkit.executeTool(rawCall, {
writeMode: editor.getEditorMode() === "review"
? "track_changes"
: "apply",
reviewComments: "create",
});

reviewComments is independent of writeMode. In Edit mode, the edit applies directly and the comment explains the applied change. In Review mode, the edit is written as a tracked change, and the comment explains the proposed change.

The toolkit reports what happened in the write result:

type AiReviewCommentResult =
| {
created: true;
threadId: string;
}
| {
created: false;
reason: "empty" | "unsupported-anchor" | "no-op";
};

empty means no comment thread was created because the reviewComment value was absent, empty, or contained only whitespace after trimming. The document write still succeeded. This reason is only about the comment text, not the edit. unsupported-anchor means the write succeeded but the package couldn’t create a comment thread because the write didn’t leave a usable text anchor for the review comment. This happens with writes that remove content or produce empty content where there’s no text in the document to anchor the comment to. no-op means the write produced no document change, so there’s no anchor to attach to.

When a comment is created, the comment body is the trimmed reviewComment text. The toolkit doesn’t add a prefix or rewrite the model’s note.

To steer the model, use getAiPromptGuide as your base system prompt and add a host instruction when your product wants comments:

const system = `${getAiPromptGuide()}
When the user asks for motivation or justification, include a concise reviewComment on each write tool call.`;

Working with element IDs

Element IDs come from read tools and are scoped to the current toolkit session. Pass them to the model exactly as the toolkit returned them. Don’t store them, derive them, or treat them as stable across sessions or document edits.

After a structural edit, older IDs become stale, and write tools that target them throw. Let the model call a read tool again before the next targeted write. The prompt guide returned by getAiPromptGuide already tells the model to do this, so using it as your system prompt is the simplest way to get the correct behavior.