Tiptap Editor 3.0 Beta is out. Start here

Server-side tools (Vercel AI SDK)

This guide explains how to call tools in the server-side using the Vercel AI SDK. It presents an example of a tool that returns the weather in a given location.

First, define the tool in the Vercel AI SDK tool format:

const weatherTool = {
  description: 'Returns the weather in a given location',
  parameters: {
    type: 'object',
    properties: {
      location: {
        type: 'string',
        description: 'The location to get the weather for',
      },
    },
    required: ['location'],
  },
}

Then, when you call the Vercel AI SDK, include the tool in the tools object:

import { AiAgentToolkit } from '@tiptap-pro/extension-ai-agent-server'
import { vercelAiSdkAdapter } from '@tiptap-pro/extension-ai-agent'
import { generateObject } from 'ai'
import { openai } from '@ai-sdk/openai'

const toolkit = new AiAgentToolkit()

// Call the Vercel AI SDK
const response = await generateObject({
  model: openai('gpt-4.1'),
  messages: [
    {
      role: 'system',
      content: `
<Your system prompt>
${toolkit.getSystemPrompt()}
`,
    },
    ...llmMessages,
  ],
  // Include the weather tool in the tools object, beside
  // the other tools provided by AiAgentToolkit
  tools: {
    ...toolkit.getTools(vercelAiSdkAdapter),
    get_weather: weatherTool,
  },
})

Then, check if the response contains the weather tool. If so, call the tool and add the result to the llmMessages array.

for (const toolCall of response.toolCalls) {
  const name = toolCall.toolName

  if (name !== 'get_weather') {
    continue
  }

  const args = toolCall.args

  const result = getWeather(args)
  llmMessages.push({
    role: 'tool',
    content: [
      {
        type: 'tool-result',
        toolCallId: toolCall.toolCallId,
        result: result.toString(),
      },
    ],
  })
}

Finally, when there are no more server-side tool calls, use the vercelAiSdkAdapter to convert the response to the format expected by the AI Agent extension.

const result = vercelAiSdkAdapter.parseResponse(response)

The result should be the response of the API endpoint, and the return value of the resolver function.

You can also add chat messages to the result describing the tool that was called. This will display the result of the tool call in the chat conversation.

// Add the tool call message to the beginning of the list of new chat messages
result.chatMessages.unshift({
  type: 'ai',
  text: 'The weather in Berlin is sunny.',
  metadata: {
    // Include this metadata to mark the message as a server-side tool call
    // and display it differently in the UI
    isServerSideToolCall: true,
  },
})