Document tools and error handling
Each Office module publishes a catalog of structured document tools. getTools() returns their names, descriptions,
input schemas, and execution functions. Adapt the schemas and results to the model API or framework you use.
Get executable tools
const tools = await word.getTools({ include: ["insert_text"] }); // omit `include` to get every tool
Each item is an OfficeTool - name, description, inputSchema (JSON Schema), and execute(args). execute
delegates to the editor and, by default, returns the editor's result unchanged (an MCP CallToolResult:
{ content, isError? }).
Keep the tool set small and task-specific with include (an array of names or a predicate). A shorter tool set improves
model selection quality and limits the impact of a wrong decision.
Connect to your LLM framework
The code below maps schemas using the tools obtained above. The OpenAI example uses Chat Completions, which differs
from the Responses API. Use the Vercel example in a project with the ai package installed. Apply your application's
authorization, argument validation, and user approval in the execution function.
// OpenAI
const openaiTools = tools.map((t) => ({
type: "function",
function: { name: t.name, description: t.description, parameters: t.inputSchema },
}));
// Anthropic
const anthropicTools = tools.map((t) => ({ name: t.name, description: t.description, input_schema: t.inputSchema }));
// Vercel AI SDK
import { tool, jsonSchema } from "ai";
const aiTools = Object.fromEntries(tools.map((t) => [
t.name,
tool({ description: t.description, inputSchema: jsonSchema(t.inputSchema), execute: t.execute }),
]));
Tool-call responses and result messages differ between providers. With Anthropic Messages, preserve the assistant's
tool_use in the conversation and return a user tool_result with the same ID.
Follow the Editor AI SDK quickstart for an example with an allowlist, argument validation,
user approval, and execution limits. Explicitly configure the loop termination condition for your framework version.
Register with a registerTool callback
For frameworks that expose a registry callback instead of accepting a tool array, registerTools() registers the whole
catalog. It builds on getTools(); its default formatters wrap results in the MCP text shape.
const schemas = await word.registerTools(modelContext, {
formatResult: (result) => result, // pass the editor result through
formatError: (error) => ({ isError: true, content: [{ type: "text", text: error.message }] }),
});
modelContext is the registerTool callback object provided by your application's framework. This example assumes it
is already available. Do not return stack traces, internal URLs, storage paths, or credentials to the model.
Inspect schemas and the module prompt
const schemas = await word.getToolSchemas(); // name, description, inputSchema - no executors
const prompt = await word.getSystemPrompt(); // module-provided system prompt; "" when not provided
Confirm destructive operations
For broad or destructive changes, especially when Editor SDK is called through an AI agent:
- Read the current state.
- Build and display a change plan.
- Require user confirmation.
- Apply the smallest set of operations.
- Save explicitly.
- Read the affected state again and verify the result.
SDK errors
All SDK-owned failures reject with SDKError (code, message, optional data).
| Code | Constant | Meaning | Typical recovery |
|---|---|---|---|
| 1001 | INVALID_ARGUMENT | Invalid module, origin, iframe target, or an iframe already bound to another module | Correct configuration before retrying |
| 1002 | TIMEOUT | Editor did not answer before the timeout | Wait with whenReady(), check the origin, then retry intentionally |
| 1003 | DESTROYED | Handle used after disconnect() | Obtain a new handle with Office.word(iframe) |
| 1004 | INVALID_RESPONSE | Response envelope could not be parsed | Check editor/SDK compatibility |
| 1005 | NETWORK_ERROR | postMessage send failed | Check target window lifecycle |
| 2000 | FRAMEWORK_ERROR | Editor operation failed | Inspect error.data.error.code and user input |
When a document operation fails, error.data is the editor's structured response:
{ success: false, error: { code, message } }. Branch on error.data.error.code (for example SHEET_NOT_FOUND) rather
than parsing the message.
import { SDKError, SDK_ERROR_CODE } from "@thinkfree.dev/tfo-sdk";
try {
await word.getDocument().save();
} catch (error) {
if (error instanceof SDKError && error.code === SDK_ERROR_CODE.TIMEOUT) {
showRetryMessage();
} else if (error instanceof SDKError && error.data?.success === false) {
showDocumentOperationError(error.data.error.code);
} else {
throw error;
}
}
showRetryMessage and showDocumentOperationError are error-display functions your application implements.
An edit may have been applied even after a timeout, so check the document state first. Do not automatically retry a
write unless the operation is known to be idempotent.
Use this guide to choose recovery behavior. For supported methods, exact parameters, and return types, see the Word, Spreadsheet, Presentation API references.