Live editor bridge
Reference for the live-editor agent bridge: useDocxAgentTools, useAgentBridge, createEditorBridge, the agentPanel prop, chat UI, and paraId anchors.
Reference for wiring model tool calls to a running <DocxEditor>. For a complete walkthrough, read the AI editing tutorial first; this page documents the APIs it uses.
useDocxAgentTools (React)
The main React hook from @eigenpal/docx-editor-agents/react. It creates the bridge to the editor and returns the tool schemas, executor, and context snapshot.
const { tools, executeToolCall, getContext } = useDocxAgentTools({
editorRef, // React.RefObject<EditorRefLike | null>; DocxEditorRef satisfies it
author: 'Assistant', // stamped on comments + tracked changes. Default: 'AI'
include: ['read_document', 'find_text', 'add_comment'], // optional allow-list
exclude: ['apply_formatting'], // optional block-list, applied after include
tools: { my_tool: myToolDefinition }, // optional custom tools, keyed by name
});Returns:
| Member | Type | Purpose |
|---|---|---|
tools | OpenAI function-calling schemas | Pass to your provider (streamText({ tools }), OpenAI tools, Anthropic tools) |
executeToolCall | (name, args) => AgentToolResult | The executor. Hand to AI SDK's onToolCall or call it from your own loop |
getContext | () => AgentContextSnapshot | Snapshot of { selection, currentPage, totalPages } for system-prompt injection |
Behavior worth knowing:
include/excludefilter built-in tools both in the returned schemas and at execution time. A filtered tool call returnsTool 'x' is not enabled.Custom tools are not filtered by these options.- A custom tool with a built-in's name replaces the built-in.
- Pass a stable (memoized or module-level)
toolsobject to avoid rebuilding schemas every render. - Tool calls before the editor mounts return
{ success: false, error: 'Editor not ready.' }.
useAgentChat (React)
The minimal variant: executor plus static schemas, no filtering, no context snapshot.
import { useAgentChat } from '@eigenpal/docx-editor-agents/react';
const { executeToolCall, toolSchemas } = useAgentChat({ editorRef, author: 'Assistant' });Use useDocxAgentTools unless you specifically want the smaller surface.
useAgentBridge (Vue)
The Vue twin, from @eigenpal/docx-editor-agents/vue:
import { ref } from 'vue';
import { useAgentBridge, type EditorRefLike } from '@eigenpal/docx-editor-agents/vue';
const editorRef = ref<EditorRefLike | null>(null);
const { executeToolCall, toolSchemas } = useAgentBridge({
editorRef,
author: 'Assistant', // accepts a string or a Ref<string>
});Same EditorRefLike contract, same tool catalog, same AgentToolResult shape. As of 1.4 it matches useAgentChat (executor + schemas); the include/exclude/custom-tools options live in the React hook only, so filter toolSchemas yourself and guard names in your dispatch if you need scoping in Vue.
createEditorBridge (any host)
For hosts that are neither React nor Vue, build the bridge directly from @eigenpal/docx-editor-agents/bridge:
import { createEditorBridge, type EditorRefLike } from '@eigenpal/docx-editor-agents/bridge';
import { executeToolCall, getToolSchemas } from '@eigenpal/docx-editor-agents';
const bridge = createEditorBridge(editorHandle satisfies EditorRefLike, 'Assistant');
const result = executeToolCall('find_text', { query: 'liability' }, bridge);EditorRefLike is the structural contract both adapters' DocxEditorRef satisfy: addComment, proposeChange, findInDocument, getSelectionInfo, applyFormatting, setParagraphStyle, scrollToParaId, getPageContent, and friends. Anything implementing it can host the toolkit. The resulting EditorBridge also satisfies the compile-time Word JS API parity contract.
The agentPanel prop (React)
<DocxEditor agentPanel={...}> mounts a right-hand panel with a header, close button, drag-resize handle, and toolbar toggle button. Three control patterns:
- Uncontrolled:
agentPanel={{ render }}. The toolbar and close buttons toggle it; width persists to localStorage. - Controlled:
agentPanel={{ render, open, onOpenChange }}. You own open state. - Headless: omit
agentPanelentirely and render the toolkit's output wherever you want.
<DocxEditor
agentPanel={{
render: ({ close }) => <MyChatUI onClose={close} />, // called only while open
open, // optional: controlled open state
onOpenChange: setOpen, // fires on toolbar / close button clicks
showToolbarButton: true, // default true
toolbarBadge: <Dot />, // optional badge on the toolbar button
title: 'Assistant', // panel header title
icon: <SparkIcon />, // header icon, default sparkle
defaultWidth: 360, // px, default 360
minWidth: 280, // drag limit, default 280
maxWidth: 600, // drag limit, default 600
}}
/>The panel shell is configurable through these options; render your own chat UI inside render. In Vue the agentPanel prop does not exist yet (React-only per the parity contract); mount the AgentPanel component from @eigenpal/docx-editor-agents/vue next to the editor instead.
Chat UI components
Optional components for the inside of the panel. React: @eigenpal/docx-editor-agents/react. Vue: @eigenpal/docx-editor-agents/vue.
| Component | Purpose |
|---|---|
AgentChatLog | Message list with streaming text and a collapsible tool-call timeline. Props: messages: AgentMessage[], loading, error, humanizeToolName (pass getToolDisplayName), emptyState |
AgentComposer | Input row. React props: value, onChange, onSubmit, disabled, placeholder, footnote. The Vue component uses modelValue (v-model) instead of value/onChange and has no footnote prop |
AgentTimeline | Standalone tool-call list (running spinner, done check), used internally by the chat log |
AgentSuggestionChip | Prompt-suggestion chip for empty states |
AgentPanel | The panel shell itself, for hosts not using the agentPanel prop |
If you drive the chat with the Vercel AI SDK, toAgentMessages(chat.messages, chat.status) from @eigenpal/docx-editor-agents/ai-sdk/react (or /ai-sdk/vue) converts useChat's UIMessage[] into the AgentMessage[] shape these components render. You can also render components from another chat UI library or your own design system.
paraId anchoring
Every locate tool returns paragraphs tagged with paraId; every mutate tool addresses by it. Details that make this reliable:
- The id is Word's own
w14:paraIdattribute, read from the file and preserved through save, so anchors stay valid across the whole edit session and across reloads. - A
ParaIdAllocatorExtensionruns in the editor and assigns fresh ids when paragraphs are created or split (Enter, paste). Concurrent typing while the agent loop runs does not desync anchors. - Paragraphs that arrive without a
paraId(Word does not always emit them) are addressed by their ordinal index as a string. Use the ids returned by locate tools when you call mutate tools. - Sub-paragraph anchoring uses
search: an exact phrase that must occur exactly once in the paragraph.find_textreturns the matched phrase precisely so it can be passed back assearch.
This is also why the tool surface serializes cleanly over JSON (and MCP): an anchor is a plain { paraId, search? } value, not a live object like Office.js' Range.
Next steps
- AI editing tutorial, the wiring in context
- Tools reference, every tool the bridge executes
- Word JS API parity, the contract behind
EditorBridge - agents API reference, full signatures
AI redlining
AI redlining for DOCX: every suggestion is a Word-native tracked change a human accepts or rejects, live in the editor or in batch with DocxReviewer.
Tool catalog
Reference for the DOCX agent tools: parameters, return shapes, and examples for reading, comments, tracked changes, formatting, and navigation.