Vercel AI SDK integration
This page covers the Vercel-specific adapter that connects Document Authoring AI to Vercel AI SDK(opens in a new tab). For the conceptual model, see agentic tools; for the Edit/Review/View policy, see review and approval.
Before you start
This guide assumes:
- A Document Authoring editor is already running in the browser.
- Your app uses Vercel AI SDK for the chat transport and the model loop.
- Your server can reach your model provider.
- The browser can grab the live
DocAuthEditorinstance when tool calls arrive.
The examples use OpenAI through Vercel AI SDK, but any Vercel-supported provider works the same way; the toolkit doesn’t care which model is on the other side.
Server route for agentic tools
The toolkit ships framework-neutral helpers in @nutrient-sdk/document-authoring-ai. The Vercel adapter in @nutrient-sdk/document-authoring-ai/vercel converts those definitions into an AI SDK tool set before you hand them to streamText(opens in a new tab).
import { openai } from "@ai-sdk/openai";import { convertToModelMessages, stepCountIs, streamText,} from "ai";import { getAiPromptGuide, getAiToolDefinitions,} from "@nutrient-sdk/document-authoring-ai";import { toVercelAiTools } from "@nutrient-sdk/document-authoring-ai/vercel";
const tools = toVercelAiTools( getAiToolDefinitions({ reviewComments: "create", }),);const system = `${getAiPromptGuide()}
Keep `reviewComment` values concise and reviewer-facing.`;
export async function POST(req: Request) { const body = await req.json();
const result = streamText({ model: openai("gpt-4o-mini"), system, messages: await convertToModelMessages(body.messages), stopWhen: stepCountIs(20), temperature: 0.1, tools, });
return result.toUIMessageStreamResponse();}The adapter returns tools with no execute handlers, so the route exposes the tools to the model but doesn’t run them. The browser does. getAiPromptGuide is the system prompt designed for these tools; using it as your base system prompt tells the model how the toolkit handles element IDs, read-before-write ordering, and the rest of the rules, including when to include reviewComment. The reviewComments: "create" option makes reviewComment required on write tool calls; use the same option in the browser execution policy.
Browser chat loop
The useChat(opens in a new tab) hook is where the model’s tool calls land in the browser. The toolkit work inside onToolCall is the same execution loop described in agentic tools. The Vercel-specific part is feeding the result back through addToolOutput(opens in a new tab).
import { useChat } from "@ai-sdk/react";import { DefaultChatTransport, lastAssistantMessageIsCompleteWithToolCalls,} from "ai";import { isAiWriteToolName,} from "@nutrient-sdk/document-authoring-ai";import { getAiToolkit } from "@nutrient-sdk/document-authoring-ai/editor";
const toolkit = getAiToolkit(editor);
const { addToolOutput } = useChat({ transport: new DefaultChatTransport({ api: "/api/chat" }), sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls, async onToolCall({ toolCall }) { // Skip Vercel dynamic tools; they aren't part of this route's tool set. if ("dynamic" in toolCall && toolCall.dynamic) { return; }
const editorMode = editor.getEditorMode(); const isWriteTool = isAiWriteToolName(toolCall.toolName);
if (isWriteTool && editorMode === "view") { addToolOutput({ tool: toolCall.toolName, toolCallId: toolCall.toolCallId, state: "output-error", errorText: "The document is in View mode. Switch to Edit or Review mode before editing.", }); return; }
const executed = await toolkit.executeTool( { id: toolCall.toolCallId, name: toolCall.toolName, args: toolCall.input, }, { writeMode: isWriteTool && editorMode === "review" ? "track_changes" : "apply", reviewComments: isWriteTool ? "create" : "disabled", }, );
addToolOutput({ tool: toolCall.toolName, toolCallId: toolCall.toolCallId, output: executed, }); },});lastAssistantMessageIsCompleteWithToolCalls(opens in a new tab) lets Vercel’s chat loop pick the conversation back up once you’ve submitted every tool output.
The reviewComments option is a host policy, not a model decision. The model must supply reviewComment on write tool calls because the server-side tool schema exposes it as required, but the browser still decides whether to create comment threads when it executes the call.
Server route for workflows
Workflows use Vercel’s structured-output API instead of tool calls. The route receives workflow input from the browser and returns one validated output object with generateText(opens in a new tab) and Output.object(opens in a new tab).
import { openai } from "@ai-sdk/openai";import { generateText, Output } from "ai";import { getBuiltInWorkflow } from "@nutrient-sdk/document-authoring-ai";import { toVercelAiWorkflowOutputSchema } from "@nutrient-sdk/document-authoring-ai/vercel";
export async function POST(req: Request) { const body = await req.json(); const workflow = getBuiltInWorkflow("proofreading");
const result = await generateText({ model: openai("gpt-4o-mini"), system: workflow.systemPrompt, prompt: JSON.stringify({ task: body.task ?? workflow.defaultTask, input: body.workflowInput, }), output: Output.object(toVercelAiWorkflowOutputSchema(workflow)), temperature: 0.1, });
return Response.json({ output: result.output });}On the browser side, call toolkit.readWorkflowInput to build the request body, hit this route, and apply the result with toolkit.applyWorkflowOutput. The full browser flow is in workflows.