Find out what's new in Tiptap V3

Get started with the Anthropic Claude Messages API

The Anthropic Claude Messages API allows you to build an AI Agent with Anthropic's models.

Code demo available

This guide includes a code demo to help you get started. See the GitHub repository.

Client-side setup

First, install the AI Agent extension.

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

Then, import the extension and configure it with the AiAgentProvider class.

import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
import AiAgent, { AiAgentProvider } from '@tiptap-pro/extension-ai-agent'

const provider = new AiAgentProvider()

const editor = new Editor({
  extensions: [
    StarterKit,
    AiAgent.configure({
      provider,
    }),
  ],
})

Inside the AI Agent provider, define a resolver function that calls your backend.

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

const provider = new AiAgentProvider({
  // The `chatMessages` property contains the chat messages of the conversation
  resolver: async ({ chatMessages, schemaAwarenessData }) => {
    // Call the API endpoint of your backend
    const response = await fetch('/api-endpoint', {
      method: 'POST',
      body: JSON.stringify({ chatMessages, schemaAwarenessData }),
    })
    return await response.json()
  },
})

In the next section, we'll see how to implement the API endpoint that returns the response in the correct format.

Server-side setup

First, install the AI Agent and Anthropic server libraries.

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

Get the chat messages and schema awareness data from the request parameters.

// Code inside your API endpoint. Code depends on your backend framework
const { chatMessages, schemaAwarenessData } = request

Then, inside your API endpoint, create an AiAgentToolkit instance. It lets you configure the tools that will be available to the AI model.

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

const toolkit = new AiAgentToolkit({
  adapter: anthropicMessagesAdapter,
  schemaAwarenessData,
})

Also define a ChatMessagesFormatter instance. It lets you convert the chat messages to the format expected by the Anthropic Claude Messages API.

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

const formatter = new ChatMessagesFormatter({
  initialMessages: chatMessages,
  adapter: anthropicMessagesAdapter,
})

After creating the toolkit and the formatter, send the request to the Anthropic Claude Messages API.

import {
  AiAgentToolkit,
  anthropicMessagesAdapter,
  ChatMessagesFormatter,
} from '@tiptap-pro/extension-ai-agent-server'
import Anthropic from '@anthropic-ai/sdk'

const { chatMessages, schemaAwarenessData } = request

const toolkit = new AiAgentToolkit({
  adapter: anthropicMessagesAdapter,
  schemaAwarenessData,
})

const formatter = new ChatMessagesFormatter({
  // Get the chat messages from the request body
  initialMessages: chatMessages,
  adapter: anthropicMessagesAdapter,
})

// Initialize the Anthropic client
const anthropic = new Anthropic()

// Call the Anthropic Claude Messages API
const response = await anthropic.messages.create({
  model: 'claude-sonnet-4-0',
  max_tokens: 2048,
  system: `
<Your system prompt>
${toolkit.getSystemPrompt()}
`,
  messages: formatter.format(),
  // Provide the tools that the AI model can call
  tools: toolkit.format(),
})

At the end of the system prompt, include the system prompt generated by the AiAgentToolkit instance, like this: toolkit.getSystemPrompt(). This contains instructions on how to use the tools.

To write the system prompt, see the system prompt guide. It includes an example system prompt that you can use as a starting point.

Finally, use the formatter to convert the response to the format expected by the AI Agent extension.

formatter.addAiResponse(response)

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.