Server-side tools (OpenAI Responses API)
This guide explains how to call server-side tools using the OpenAI Responses API. It presents an example of a tool that returns the weather in a given location.
Code demo available
This guide includes a code demo to help you get started. See the GitHub repository.
First, define the tool in the OpenAI Responses API tool format:
import OpenAI from 'openai' const weatherTool: OpenAI.Responses.Tool = { type: 'function', name: 'get_weather', parameters: { type: 'object', properties: { location: { type: 'string', description: 'The location to get the weather for', }, }, required: ['location'], }, strict: false, }Then, when you call the OpenAI API, include the tool in the tools array.
import { AiAgentToolkit, openaiResponsesAdapter, ChatMessagesFormatter, } from '@tiptap-pro/extension-ai-agent-server' import OpenAI from 'openai' const { chatMessages, schemaAwarenessData } = request const toolkit = new AiAgentToolkit({ adapter: openaiResponsesAdapter, schemaAwarenessData, }) const formatter = new ChatMessagesFormatter({ initialMessages: chatMessages, adapter: openaiResponsesAdapter, }) // Initialize the OpenAI client const openai = new OpenAI() // Call the OpenAI Responses API const response = await openai.responses.create({ model: 'gpt-4.1', input: [ { role: 'developer', content: ` <Your system prompt> ${toolkit.getSystemPrompt()} `, }, ...formatter.format(), ], // Include the weather tool in the tools array, beside // the other tools provided by AiAgentToolkit tools: [...toolkit.format(), weatherTool], })First, add the response to the formatter so that it is included in the conversation.
formatter.addAiResponse(response)Then, check if the response contains a server-side tool call like the weather tool. If so, call the tool and add the result to the formatter. Then, call the OpenAI API again.
Repeat this process until there are no more server-side tool calls in the response.
const isGetWeatherMessage = ( message: OpenAI.Responses.ResponseOutputItem, ): message is OpenAI.Responses.ResponseFunctionToolCall => message.type === 'function_call' && message.name === 'get_weather' let response: OpenAI.Responses.Response | null = null while (!response || response.output?.some(isGetWeatherMessage)) { // Call the OpenAI Responses API response = await openai.responses.create({ model: 'gpt-4.1', input: [ { role: 'developer', content: `${systemPrompt}\n${toolkit.getSystemPrompt()}`, }, ...formatter.format(), ], // Include the weather tool in the tools array, beside the other tools provided by AiAgentToolkit tools: [...toolkit.format(), weatherTool], }) // Convert the response to the format expected by the AI Agent extension formatter.addAiResponse(response) // Process weather tool calls for (const toolCall of response.output) { if (isGetWeatherMessage(toolCall)) { const args = locationSchema.parse(JSON.parse(toolCall.arguments)) const weatherResult = await getWeather(args.location) // Add the tool call result to the formatter formatter.addChatMessage({ type: 'toolCallResult', toolName: 'get_weather', toolCallId: toolCall.call_id, result: weatherResult, isError: false, }) } } }Finally, when there are no more server-side tool calls, use the formatter to convert the response to the format expected by the AI Agent extension.
const response = formatter.getResolverResponse()The value returned from formatter.getResolverResponse() should be the response of your API endpoint and the return value of the resolver function.