Signal drop!
Relay (operand.online) is unreachable.
Usually, a dropped signal means an upgrade is happening. Hold on!
Sorry, no connección.
Hang in there while we get back on track
gram: docs
> ./docs/site/content/agents/tools.mdx
---
title: 'Tool catalog'
description: 'Reference for the 14 DOCX agent tools: parameters, return shapes, and examples for reading, comments, tracked changes, formatting, and navigation.'
category: 'Agents'
seoTitle: 'Agent tools reference'
---
All 14 built-in tools, with exact parameters and return shapes. The schemas come from `getToolSchemas()` (OpenAI function-calling format) or `getAiSdkTools()` (Vercel AI SDK shape); execution goes through `executeToolCall(name, args, bridge)` or the framework hooks.
Every tool returns the same envelope:
```ts
interface AgentToolResult {
success: boolean;
data?: unknown; // present on success; string for most tools
error?: string; // present on failure; written so the model can self-correct
}
The pattern is locate-then-mutate. Locate tools return paragraphs tagged with a stable paraId (Word's w14:paraId); mutate tools take that paraId as input. Paragraphs without a paraId in the source file are addressed by their ordinal index as a string, so the ids the agent reads always resolve.
Locate
read_document
Read the document as [paraId] text lines. Returns the vanilla view: pending tracked insertions are hidden, pending deletions still show as plain text (they are part of the document until accepted), and comment markers are stripped. Use read_changes / read_comments to inspect what is pending.
| Parameter | Type | Required | Description |
|---|---|---|---|
fromIndex |
number | no | Start ordinal index (inclusive) |
toIndex |
number | no | End ordinal index (inclusive) |
// call
{ "name": "read_document", "arguments": {} }
// data
"[2A1F3B] Quarterly report\n[2A1F3C] Revenue grew 14% over the prior period..."
read_selection
Read the user's current cursor or selection. No parameters. Returns a SelectionInfo object: { paraId, selectedText, paragraphText, before, after }. Fails with No selection (editor not focused). when there is no live cursor, which is always the case in headless mode.
// data
{
"paraId": "2A1F3C",
"selectedText": "grew 14%",
"paragraphText": "Revenue grew 14% over the prior period.",
"before": "Revenue ",
"after": " over the prior period.",
}
read_page
Read one rendered page. Live editor only: the headless reviewer has no layout, so it reports zero pages.
| Parameter | Type | Required | Description |
|---|---|---|---|
pageNumber |
number | yes | 1-indexed page number |
Returns the page text as [paraId] text lines. Out-of-range pages fail with Page 9 does not exist (document has 4 pages).; headless mode fails with No pages rendered (headless mode or empty document).
read_pages
Read a contiguous range of rendered pages in a single round-trip. Live editor only, same headless caveat as read_page.
| Parameter | Type | Required | Description |
|---|---|---|---|
from |
number | yes | 1-indexed start page (inclusive) |
to |
number | yes | 1-indexed end page (inclusive) |
// data
"--- Page 2 ---\n[3B1C44] ...\n\n--- Page 3 ---\n[3B1C59] ..."
find_text
Locate paragraphs containing a phrase. Returns handles the agent passes straight to the mutate tools: paraId plus the matched substring (use it as search).
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | yes | Text to find (substring match) |
caseSensitive |
boolean | no | Default false |
limit |
number | no | Max paragraphs to return. Default 20 |
Returns FoundMatch[], or the string No matches.:
// data
[
{
"paraId": "5D0A21",
"match": "best efforts",
"before": "The Supplier shall use ",
"after": " to deliver the goods by the agreed date.",
},
]
read_comments
List all comments with authors, anchored text, and threaded replies. No parameters.
// data
"[Comment #3] Legal AI: \"Define 'material breach'.\" (anchored to: \"material breach\")\n Reply by Dana: \"Agreed, drafting a definition.\""
read_changes
List tracked changes (insertions and deletions) currently pending in the document. No parameters.
// data
"[Change #12] insertion by Legal AI: \"commercially reasonable efforts\"\n[Change #13] deletion by Legal AI: \"best efforts\""
Mutate
add_comment
Attach a comment to a paragraph, optionally anchored to a phrase within it. In the live editor it appears in the comments sidebar immediately.
| Parameter | Type | Required | Description |
|---|---|---|---|
paraId |
string | yes | Paragraph id from read_document / find_text |
text |
string | yes | Comment body |
search |
string | no | Anchor to this exact phrase within the paragraph; must be unique |
// call
{ "paraId": "5D0A21", "text": "Replace with a defined-efforts standard.", "search": "best efforts" }
// data
"Comment 7 added on 5D0A21."
Fails when the paraId does not exist or search is missing from / ambiguous within the paragraph.
reply_comment
Reply to an existing comment; the reply threads under the original.
| Parameter | Type | Required | Description |
|---|---|---|---|
commentId |
number | yes | Comment id from read_comments |
text |
string | yes | Reply body |
Returns Reply 9 added to comment 7. Fails with Comment #7 not found. for unknown ids.
resolve_comment
Mark a comment as resolved (done).
| Parameter | Type | Required | Description |
|---|---|---|---|
commentId |
number | yes | Comment id from read_comments |
Returns Comment 7 resolved.
suggest_change
Suggest a tracked change the user accepts or rejects. Never edits text directly. Three modes selected by empty strings:
| Mode | search |
replaceWith |
|---|---|---|
| Replacement | non-empty | non-empty |
| Deletion | non-empty | "" |
| Insertion at paragraph end | "" |
non-empty |
| Parameter | Type | Required | Description |
|---|---|---|---|
paraId |
string | yes | Paragraph id from read_document / find_text |
search |
string | yes | Phrase to find; must be unique within the paragraph. "" = insert at paragraph end |
replaceWith |
string | yes | Replacement text. "" = delete the matched phrase |
// call
{ "paraId": "5D0A21", "search": "best efforts", "replaceWith": "commercially reasonable efforts" }
// data
"Replacement proposed: \"best efforts\" → \"commercially reasonable efforts\" on 5D0A21."
Fails when the paraId is unknown, search is missing or ambiguous, or the target overlaps an existing tracked change.
apply_formatting
Apply character formatting to a whole paragraph or a unique phrase within it. This is a direct edit, not a tracked change; exclude it in strict redlining workflows.
| Parameter | Type | Required | Description |
|---|---|---|---|
paraId |
string | yes | Paragraph id from read_document / find_text |
search |
string | no | Format only this exact phrase (must be unique). Omit to format the whole paragraph |
marks |
object | yes | Marks to set or clear. Omit a key to leave it untouched; pass false to clear |
marks keys:
| Key | Type | Notes |
|---|---|---|
bold, italic, strike |
boolean | false clears |
underline |
boolean or { style } |
true = single. Styles are the closed ECMA-376 ST_Underline set (single, double, thick, dotted, dash, wave, words, none, ...); other values are rejected |
color |
object | { rgb: "FF0000" } (no hash) or { themeColor: "accent1" } |
highlight |
string | Closed Word set only (yellow, green, cyan, magenta, red, darkBlue, ...). "none" clears. Hex is rejected: Word does not accept hex for <w:highlight> |
fontSize |
number | Points (e.g. 12, 14, 24) |
fontFamily |
object | { ascii, hAnsi } |
// call
{ "paraId": "2A1F3B", "marks": { "bold": true, "color": { "rgb": "1A73E8" } } }
// data
"Formatting applied to 2A1F3B."
Out-of-spec values fail early with the allowed list in the error message, so the model can self-correct instead of writing OOXML Word would discard.
set_paragraph_style
Apply a paragraph style by id. The styleId must exist in the document's styles.xml; unknown ids are rejected. Direct edit, not a tracked change.
| Parameter | Type | Required | Description |
|---|---|---|---|
paraId |
string | yes | Paragraph id from read_document / find_text |
styleId |
string | yes | Style id, e.g. "Heading1", "Heading2", "Title", "Quote", "Normal" |
// call
{ "paraId": "2A1F3B", "styleId": "Heading1" }
// data
"Style \"Heading1\" applied to 2A1F3B."
Navigate
scroll
Scroll the editor viewport to a paragraph. Does not move the user's cursor. In headless mode it validates the paraId and reports success without doing anything (there is no viewport).
| Parameter | Type | Required | Description |
|---|---|---|---|
paraId |
string | yes | Paragraph id from read_document / find_text |
Returns Scrolled to 2A1F3B. or fails with paraId 2A1F3B not found.
Next steps
- AI editing tutorial, wire these tools to a live editor
- AI redlining, tool subsets for tracked-change-only review
- Word JS API parity, how each tool maps to Office.js
- API reference