Skip to main content

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:

  1. Read the current state.
  2. Build and display a change plan.
  3. Require user confirmation.
  4. Apply the smallest set of operations.
  5. Save explicitly.
  6. Read the affected state again and verify the result.

SDK errors

All SDK-owned failures reject with SDKError (code, message, optional data).

CodeConstantMeaningTypical recovery
1001INVALID_ARGUMENTInvalid module, origin, iframe target, or an iframe already bound to another moduleCorrect configuration before retrying
1002TIMEOUTEditor did not answer before the timeoutWait with whenReady(), check the origin, then retry intentionally
1003DESTROYEDHandle used after disconnect()Obtain a new handle with Office.word(iframe)
1004INVALID_RESPONSEResponse envelope could not be parsedCheck editor/SDK compatibility
1005NETWORK_ERRORpostMessage send failedCheck target window lifecycle
2000FRAMEWORK_ERROREditor operation failedInspect 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.