AI agent chatbot
Build a simple AI agent chatbot that can read and edit Tiptap documents.
Tech stack
- React + Next.js
- AI SDK by Vercel
- OpenAI models
- Tiptap AI Toolkit
Installation
Create a Next.js project:
npx create-next-app@latest ai-agent-chatbot
Install the core Tiptap packages and the Vercel AI SDK for OpenAI:
npm install @tiptap/react @tiptap/starter-kit ai @ai-sdk/react @ai-sdk/openai
Install the Tiptap AI Toolkit and the tool definitions for the Vercel AI SDK.
Pro package
The AI Toolkit is a pro package. Before installation, set up access to the private NPM registry by following the private registry guide.
npm install @tiptap-pro/ai-toolkit @tiptap-pro/ai-toolkit-ai-sdk
API endpoint
Create an API endpoint that uses the Vercel AI SDK to call the OpenAI model. Include the tool definitions for the Tiptap AI Toolkit.
// app/api/chat/route.ts
import { openai } from '@ai-sdk/openai'
import { toolDefinitions } from '@tiptap-pro/ai-toolkit-ai-sdk'
import { convertToModelMessages, streamText, UIMessage } from 'ai'
export async function POST(req: Request) {
const { messages }: { messages: UIMessage[] } = await req.json()
const result = streamText({
model: openai('gpt-5-mini'),
system: 'You are an assistant that can edit rich text documents.',
messages: convertToModelMessages(messages),
tools: toolDefinitions(),
})
return result.toUIMessageStreamResponse()
}
To access the OpenAI API, create an API key in the OpenAI Dashboard and add it as an environment variable. The environment variable will be detected automatically by the Vercel AI SDK.
# .env
OPENAI_API_KEY=your-api-key
Client
Create a client-side React component that renders the Tiptap Editor and a simple chat UI. This component leverages the useChat hook from the Vercel AI SDK to call the API endpoint and manage the chat conversation. When the AI model outputs a tool call, it uses the Tiptap AI Toolkit to execute the tool.
// app/page.tsx
'use client'
import { DefaultChatTransport, lastAssistantMessageIsCompleteWithToolCalls } from 'ai'
import { useChat } from '@ai-sdk/react'
import { EditorContent, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { useRef, useState } from 'react'
import { AiToolkit, getAiToolkit } from '@tiptap-pro/ai-toolkit'
export default function Page() {
const editor = useEditor({
immediatelyRender: false,
extensions: [StarterKit, AiToolkit],
content: `<h1>AI Agent Demo</h1><p>Ask the AI to improve this.</p>`,
})
// Fixes issue: https://github.com/vercel/ai/issues/8148
const editorRef = useRef(editor)
editorRef.current = editor
// The AI Agent reads the document in chunks. This variable keeps track of the current chunk
// that the AI Agent is reading.
const currentChunk = useRef(0)
const { messages, sendMessage, addToolResult } = useChat({
transport: new DefaultChatTransport({ api: '/api/chat' }),
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls,
async onToolCall({ toolCall }) {
const editor = editorRef.current
if (!editor) return
const { toolName, input, toolCallId } = toolCall
// Use the AI Toolkit to execute the tool
const toolkit = getAiToolkit(editor)
const result = toolkit.executeTool({
toolName,
input,
currentChunk: currentChunk.current,
})
currentChunk.current = result.currentChunk
addToolResult({ tool: toolName, toolCallId, output: result.output })
},
})
const [input, setInput] = useState('Replace the last paragraph with a short story about Tiptap')
if (!editor) return null
return (
<div>
<EditorContent editor={editor} />
{messages?.map((message) => (
<div key={message.id} style={{ whiteSpace: 'pre-wrap' }}>
<strong>{message.role}</strong>
<br />
{message.parts
.filter((p) => p.type === 'text')
.map((p) => p.text)
.join('\n')}
</div>
))}
<form
onSubmit={(e) => {
e.preventDefault()
if (input.trim()) {
sendMessage({ text: input })
setInput('')
}
}}
>
<input value={input} onChange={(e) => setInput(e.target.value)} />
</form>
</div>
)
}
End result
With additional CSS styles, the result is a simple but polished AI chatbot application:
See the source code on GitHub.
Next steps
Let your users review AI-generated changes with the review changes guide.