Tiptap Editor 3.0 Beta is out. Start here

Integrate your LLM

You can integrate the AI Agent extension with your own backend and LLM provider instead of using Tiptap Cloud. This gives you complete control over the AI model, tools, and conversation flow.

Custom LLM demo

We provide our Business and Enterprise customers with a detailed Custom LLM demo. It includes the client and server code, and instructions on how to run and deploy it. See plans and pricing.

Basic setup

To get started, follow these steps:

  1. Create a backend service that communicates with your LLM provider
  2. Configure the AI Agent extension to call your backend service

Create a backend service that calls your LLM

When you're building an AI Agent, you need to define a set of tools that it can call. The AIAgentToolkit class provides a list of text-editing tools that you can send to the LLM provider API. You can combine these tools with your own custom tools (like web search, agentic RAG, or orchestration) to build a custom AI Agent that can edit rich text as well as perform other actions.

In your server code, install the @tiptap-pro/extension-ai-agent and @tiptap-pro/extension-ai-agent-server libraries.

npm install @tiptap-pro/extension-ai-agent @tiptap-pro/extension-ai-agent-server

The AiAgentToolkit class provides methods for generating the system prompt and tool definitions in a format that can be sent to your LLM provider API or your AI Agent framework of choice.

import { openaiChatCompletionsAdapter } from '@tiptap-pro/extension-ai-agent'
import { AiAgentToolkit } from '@tiptap-pro/extension-ai-agent-server'

const toolkit = new AiAgentToolkit()

const response = await openai.chat.completions.create({
  model: 'gpt-4.1',
  messages: [
    {
      role: 'system',
      content: `You are Tiptap AI Agent, an AI agent that edits rich text documents.
// ... other system prompt instructions
${toolkit.getSystemPrompt()}`,
    },
    ...args.llmMessages,
  ],
  tools: [
    ...toolkit.getTools(openaiChatCompletionsAdapter),
    // ... combine with your custom tools
    customWebSearchTool,
    customWeatherReportTool,
  ],
})

Configure the AI Agent extension to call your backend

The AI Agent extension provides a resolver option that allows you to integrate with your custom backend service. This function is responsible for sending the messages to the LLM and returning the response.

import { AiAgentProvider } from '@tiptap-pro/extension-ai-agent'

const provider = new AiAgentProvider({
  resolver: async (options) => {
    // Your custom logic to send the chat messages to the LLM
    // and return the response
    const response = await yourCustomBackend.sendChatMessages(options.llmMessages)
    return response
  },
  // ... Other options
})

The resolver's response should contain these properties:

  • chatMessages: An array of regular chat messages generated by the AI, typically containing text responses. It does not include tool call messages.

  • toolCallChatMessages: An array of tool call messages generated by the AI, representing actions the AI wants to take. These messages contain instructions for tools to execute specific operations, such as editing the document or asking the user a question.

These properties allow you to separate the AI's textual responses from its requested actions, giving you more control over how to handle and display the AI's output in your application.

You can use the adapter's parseResponse function to convert the LLM response to the format expected by the AI Agent extension.

import { openaiChatCompletionsAdapter } from '@tiptap-pro/extension-ai-agent-server'

// In the server, call your LLM provider API
const response = await openai.chat.completions.create({
  // ...
})

// Parse the response to get the chat messages and tool calls in the format expected by the resolver
const result = openaiChatCompletionsAdapter.parseResponse(response)

Adapters

Adapters convert between the AI Agent's internal format and the format used by different LLM providers and AI Agent frameworks. The extension includes these built-in adapters:

AdapterProvider
openaiResponsesAdapterOpenAI API Responses API
openaiChatCompletionsAdapterOpenAI API Chat Completions API
anthropicMessagesAdapterAnthropic Claude Messages API

Need more adapters?

We are working on adding more adapters for different LLM providers and frameworks. If you need an adapter for a specific provider that is not yet available, contact us with your specific use case

If you want to use an LLM provider that is not yet supported by our backend library, you can create a custom adapter by implementing the AiAgentAdapter interface.

Configure the AI Agent's tools

You can customize the AiAgentToolkit instance by passing custom text-editing tools to its constructor.

import { AiAgentToolkit, toolsStarterKit } from '@tiptap-pro/extension-ai-agent-server'

const toolkit = new AiAgentToolkit({
  // The tools starter kit contains all the built-in tools
  ...toolsStarterKit(),
  // Add, for example, a tool to search the editor's content
  customSearchTool()
})

Built-in tools

The AI Agent extension includes these pre-built tools:

Tool CategoryTools
Readingread_first_chunk, read_next_chunk, read_previous_chunk
Writingreplace_chunk, replace_document
Formattingrun_command (with various commands like setBold, setItalic, etc.)
Workflowplan, ask_user, finish_with_summary

Each tool has two components:

  1. Tool definition: Defines the tool's ID, description, and JSON schema. This data is sent to the LLM to generate the tool calls.
  2. Tool handler: Implements the logic for executing the tool in the editor. If you define a tool in your backend, you must define a tool handler in the AI Agent provider, in the toolHandlers option.

Custom tools

You can create custom tools to extend the AI Agent's capabilities. First, define the tool (server-side):

import { AiAgentTool } from '@tiptap-pro/extension-ai-agent-server'

export const customSearchTool = (): AiAgentTool => ({
  id: 'search_document',
  toolDescription: 'Searches for text in the document',
  jsonSchema: {
    type: 'object',
    properties: {
      query: {
        type: 'string',
        description: 'The text to search for',
      },
    },
    required: ['query'],
  },
  // Optional additional rules for the system prompt
  systemPromptRules: [
    'Use this tool when you need to find specific content in the document',
    'The search is case-insensitive',
  ],
})

Then, implement the tool handler (client-side)

import { AiAgentToolCallHandler } from '@tiptap-pro/extension-ai-agent'
import { z } from 'zod'

// Schema for validating tool arguments
const SearchToolSchema = z.object({
  query: z.string(),
})

export const searchToolHandler = (): AiAgentToolCallHandler => ({
  id: 'search_document',
  modifiesEditor: false, // This tool doesn't modify the document
  handleToolCall: ({ editor, toolCall }) => {
    // Validate arguments
    const args = SearchToolSchema.parse(toolCall.arguments)

    // Implement search logic
    const html = editor.getHTML()
    const results = findTextInHtml(html, args.query)

    // Return results to the LLM
    return 'Found these results: ' + results.join(', ')
  },
})

Finally, add the tool to your toolkit and provider:

// Server-side
const toolkit = new AiAgentToolkit({
  tools: [
    // Built-in tools
    ...toolsStarterKit(),
    // Custom tools
    customSearchTool(),
  ],
})

// Client-side
const provider = new CustomAiAgentProvider({
  toolHandlers: [
    // Tool handlers for built-in tools
    ...toolHandlersStarterKit(),
    // Custom handlers
    searchToolHandler(),
  ],
})

Develop your backend in other programming languages than TypeScript

Although the @tiptap-pro/extension-ai-agent-server package is written in TypeScript, you can develop your backend in any other programming language.

First, extract the system prompt and tool definitions from the AiAgentToolkit instance by converting them to JSON. Then, use the JSON data to call the LLM provider in your code written in another programming language.

const toolkit = new AiAgentToolkit()

// Get the system prompt and tool definitions in JSON format
const systemPrompt: string = toolkit.getSystemPrompt()
const toolDefinitions: string = JSON.stringify(toolkit.getTools(openaiChatCompletionsAdapter))