Agents

Core action reference

The arguments, selectors, placements, and receipts behind superdoc_inspect and superdoc_perform_action.

The core preset advertises two tools. superdoc_inspect reads a deterministic snapshot. superdoc_perform_action runs one named action with flat arguments and returns a receipt. This page documents both from the action registry in @superdoc/sdk, and the same definitions are served over MCP under MCP_PRESET=core.

The registry changes across SDK releases without changing the preset id. Pin the SDK version when your integration depends on a specific action set, and read the advertised schema after upgrading:

import { getToolCatalog } from '@superdoc/sdk';

const catalog = await getToolCatalog('core');
const performAction = catalog.tools.find((tool) => tool.toolName === 'superdoc_perform_action');
console.log(performAction?.inputSchema);

superdoc_inspect

Every argument is optional. Prefer the narrowest call that answers the question, because the result lives in conversation history for the rest of the run.

ArgumentEffect
countsOnlyReturn counts only. The cheapest orientation call
includeDomainsLimit the snapshot to the listed domains
blockNodeTypesOnly blocks of these node types, for example ["heading"]
findText, findLimitScan the whole document server-side, report matching blocks, and center the block window on the first match
blockOffset, blockLimitA contiguous window of blocks. Ordinals are absolute, so windows line up across calls
omitEmptyBlocks, dropTextPreview, blockTextLimitTrim the payload of a reading pass
includeListItemRuns, listItemRunsLimitInline formatting runs on list items. On by default; pass false for a pure read
includeBlockRuns, blockRunsLimitInline formatting runs on body blocks. Off by default. Pair with a narrow block window
includeTableCellRuns, tableCellRunsLimitInline formatting runs on table cells. Off by default
listLimit, tableLimit, commentLimit, trackedChangeLimitCap the entries returned for each domain

Domains: blocks, lists, tables, comments, trackedChanges, sections, headerFooters, styles, contentControls, fields, hyperlinks, bookmarks, permissionRanges, images.

Every ordinal in a snapshot is 1-based, and selectors accept the same values. Use findText to locate a heading or phrase in a long document instead of paging through windows.

Selectors

Actions that operate on a block take a selector. Batch actions take selectors[].

SelectorShapeUse when
Node id{ kind: "nodeId", nodeId }You have a nodeId from an inspect. The most precise choice
Ordinal{ kind: "ordinal", ordinalKind, value }"The third paragraph" or "the second table"
Text search{ kind: "textSearch", terms: [...], match?, occurrence?, caseSensitive?, nodeTypes? }You know the wording but not the position
Table cell{ kind: "tableCell", tableOrdinal, rowIndex, columnIndex }Cell-scoped edits
Relative{ kind: "relative", position: "before" | "after", target: <selector> }"The paragraph after the heading called X"

ordinalKind is one of blockOrdinal, paragraphOrdinal, bodyParagraphOrdinal, headingOrdinal, listOrdinal, tableOrdinal, or sectionOrdinal. match on a text search is all or any, and nodeTypes narrows to paragraph, heading, or listItem.

Placement

Actions that insert content take a placement:

{ "at": "document_end" }
{ "at": "document_start" }
{ "at": "after", "selector": { "kind": "textSearch", "terms": ["Definitions"] } }
{ "at": "before", "selector": { "kind": "nodeId", "nodeId": "p42" } }

changeMode

Actions that accept changeMode record the edit as a tracked change when it is "tracked" and edit directly otherwise. The tool schema advertises the argument once for the whole tool, so the table below is the only place that says which actions honor it. Passing it to an action marked No looks compliant and produces a direct edit. move_range accepts the argument and then fails without mutating, because a block-range deletion cannot be tracked.

The safety guide explains why a loop that promises reviewable output must enforce this allowlist in code.

Actions

Arguments marked ? are optional. Styled text arguments (texts, cellTexts, entries) accept either a plain string or an object with runs and marks so new content can match its neighbors in the same call.

Text and structure

ActionArgumentsTrackedNotes
insert_paragraphstexts[] or text, placement?, headingLevel?YesThe way to add a paragraph or clause. The first item can become a heading
insert_headingtext, level, placement?Yes
replace_textedits[{ find, replace }], selector?, caseSensitive?YesRewrites the matched span as plain text. Keep spans minimal. Not for appending new sentences
delete_textfinds[], selector?, caseSensitive?YesDeletes text only and leaves the block. Scope with selector to delete stray whitespace safely
delete_blocksselectors[] or selectorYesRemoves whole paragraphs, headings, or list items, marker included
append_listitems[], kind?, headingText?, headingLevel?, placement?YesStarts a new list. Use add_list_items to extend an existing one
create_tablerows, columns, cellTexts?, placement?YesIn tracked mode the whole insertion is one tracked change
rewrite_blockselector, textYesReplaces a block's text and preserves the run pattern over the unchanged prefix and suffix
fill_placeholdersvalues[] and/or fields[{ label?, value }]Yes
move_rangefromText, toText?, afterText or beforeTextRefusedMoves a block range or a visual section identified by text. Ranges containing tables, lists, or images are refused

Lists and numbering

ActionArgumentsTrackedNotes
convert_listkind, then listOrdinal? or anchorText?, or fromMarker + toMarker, or fromText + toTextYesConverts lists, clause ranges, or plain paragraphs to a list in place
attach_numberinganchorText or nodeId, likeMarkerYesNumbers a block in the same scheme and level as the sibling rendering likeMarker
add_list_itemsanchorText or listOrdinal, entries[] or items[]YesAdds into an existing list and reuses its numbering. level is relative to the anchor
split_listanchorText, restartNumbering?NoSplits one list into two at an item

History

ActionArgumentsTrackedNotes
undo_changesuntilMarker?, steps?NoSteps history back until the rendered marker reappears, or a step count
redo_changessteps?NoOnly valid right after an undo, before any new edit

Moving text

ActionArgumentsTrackedNotes
move_texttext, afterText?YesDirect mode requires afterText. Tracked mode records a tracked delete at the source and insert at the destination

Comments

ActionArgumentsTrackedNotes
comment_paragraphscommentText, scope?, excludeBlockQuotes?NoOne identical comment per paragraph. For broadcast notes only
add_commentscommentText, selector or selectors[]NoBatch many targets into selectors[] in one call
resolve_commentsanchorText?, reopen?NoOmit anchorText to resolve every open comment
reply_to_commentcommentText, anchorText or commentIdNoAdds a threaded reply rather than a new top-level comment

Tracked-change review

ActionArgumentsTrackedNotes
accept_tracked_changesauthor?, changeType?NochangeType is insert, delete, replacement, or format
reject_tracked_changesauthor?, changeType?No

Exclude both when a person must make the final decision. Safety shows the exclusion.

Formatting

ActionArgumentsTrackedNotes
format_texttargetText, targetTexts[], or selector; bold?, italic?, underline?, strike?, highlight?, color?, fontSize?, caseSensitive?YesApplies to every occurrence of the target text
apply_styleselector, then one of styleId, headingLevel, or likeTextNolikeText copies another block's style and effective look
format_paragraphselector, alignmentYesTracked mode records the former alignment as a property change
set_paragraph_spacingselector, lineSpacing?, spaceBefore?, spaceAfter?No
normalize_body_font_sizefontSizeYesWhole-body font size
set_font_familyfontFamily, selector? or targetText/targetTexts[]?, caseSensitive?YesOmit every target to set the whole body typeface
apply_letter_spacingselector, letterSpacingYes
ActionArgumentsTrackedNotes
insert_page_breakselectorNoSets a page break before the block instead of inserting empty paragraphs
add_hyperlinktext, url, tooltip?NoTurns existing text into a link
insert_toctitle?, placement?Yes

Tables

ActionArgumentsTrackedNotes
style_tabletableOrdinal?, accentColor?NoAccent header, bold first column, banded rows
move_tabletableOrdinal?, placementNoMoves the whole table with its content in one call
delete_tabletableOrdinal?Yes
insert_table_rowtableOrdinal?, rowIndex?, position?, cellTexts?, dryRun?YesdryRun: true reports success without changing the document
insert_table_columntableOrdinal?, columnIndex?, position?, headerText? or cellTexts?Yes
delete_table_rowtableOrdinal?, rowIndexYes
delete_table_columntableOrdinal?, columnIndexYes
split_tabletableOrdinal?, rowIndex, separatorText?Yes

tableOrdinal is 1-based. Omit it only when the document contains exactly one table; with several tables the action cannot resolve a target and fails. rowIndex and columnIndex are 0-based, unlike every ordinal, so rowIndex: 0 is the first row. The tableCell selector uses the same 0-based row and column indices.

Receipts

Every dispatched action returns a receipt. Reads return a snapshot instead, and argument validation throws before a receipt exists. Build an agent explains how a loop should branch on the three cases.

FieldMeaning
statusok, partial, failed, or aborted. partial means some requested edits applied and some did not
intentThe action name
preSnapshot, postSnapshotrevision and counts before and after. Differing revisions are the evidence that the document changed
selectedTargetsThe selectors that resolved and what they matched
executedOperationsThe Document API operations the action ran
verification, verificationPassedPost-checks run against a fresh snapshot, and their roll-up
errors[]code, a message written for the model, and sometimes a structured recovery
nextStep, revertHint, noteProse guidance for the model, and a literal undo call when several history steps were dispatched

Actions add their own evidence, such as editsApplied and editsSkipped on replace_text, formattingMatched on inserts that copy neighboring formatting, and addedItems on add_list_items.

Verification checks include revision-changed, block-count-delta, comment-count-delta, tracked-change-count-delta, block-text-contains, table-shape, and list-item-count. The standard revision-changed check fails when a mutation turns out to be a no-op, so verificationPassed: false does not by itself say whether anything changed. Read the snapshots.

Add your own

createAgentToolkit accepts customActions, which extend this registry with named verbs of your own that dispatch through the same tool. Their receipts report succeeded rather than ok. See Custom actions.

Not advertised

The dispatcher also routes superdoc_execute_code, agent_apply, agent_verify, and agent_operation. They are for SDK callers, they are absent from the tool list and the system prompt, and a model-facing loop should refuse them. Build an agent shows the check.

On this page