Comments workflow
Build a workflow that allows the AI to manage comments and threads in your Tiptap documents.
See the source code on GitHub.
Tech stack
- React + Next.js
- AI SDK by Vercel + Anthropic models
- Tiptap AI Toolkit
- Tiptap Comments extension
Project overview
This demo uses the AI Toolkit's Comments workflow to manage threads and comments in the document. The AI can create new threads, add comments, update comments, remove comments, and manage thread status.
Installation
Create a Next.js project:
npx create-next-app@latest comments-workflowInstall the core Tiptap packages and the Vercel AI SDK for Anthropic:
npm install @tiptap/react @tiptap/starter-kit ai @ai-sdk/react @ai-sdk/anthropic zod uuidInstall the Tiptap AI Toolkit and Comments extension:
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-tool-definitions @tiptap-pro/extension-commentsServer setup
Create an API endpoint that uses the Vercel AI SDK to call the Anthropic model.
Inside the API endpoint, create and configure the Comments workflow using the createEditThreadsWorkflow function. The workflow includes a ready-to-use system prompt that instructs the AI model on how to manage comments.
The user message should include:
content: The content of the document (obtained fromtiptapRead)threads: The existing threads in the document (obtained fromgetThreads)task: The task to be performed by the AI. For example,Add a comment suggesting improvements to the introduction.
// app/api/comments-workflow/route.ts
import { anthropic } from '@ai-sdk/anthropic'
import { createEditThreadsWorkflow } from '@tiptap-pro/ai-toolkit-tool-definitions'
import { Output, streamText } from 'ai'
export async function POST(req: Request) {
const { content, threads, task } = await req.json()
// Create and configure the Comments workflow (with the default settings).
// It includes the ready-to-use system prompt and the output schema.
const workflow = createEditThreadsWorkflow()
const result = streamText({
model: anthropic('claude-haiku-4-5'),
// System prompt
system: workflow.systemPrompt,
// User message
prompt: JSON.stringify({
content,
threads,
task,
}),
output: Output.object({ schema: workflow.zodOutputSchema }),
})
return result.toTextStreamResponse()
}Client setup
Create a React component that renders the editor with the Comments extension and applies comment operations.
The workflow supports streaming, which means operations are applied incrementally as they arrive from the AI model, providing real-time feedback to users.
First, when the workflow starts, call the tiptapRead method to get the document content and getThreads method to get existing threads.
Then, call the API endpoint to start the workflow. Use the editThreadsWorkflow method to apply the comment operations. The isStreaming parameter ensures operations are applied incrementally as they stream in.
// app/comments-workflow/page.tsx
'use client'
import { experimental_useObject as useObject } from '@ai-sdk/react'
import { EditorContent, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { AiToolkit, getAiToolkit, editThreadsWorkflowOutputSchema } from '@tiptap-pro/ai-toolkit'
import { Comments } from '@tiptap-pro/extension-comments'
import { useEffect, useState } from 'react'
import { v4 as uuid } from 'uuid'
// Create a simple comments provider
const commentsProvider = {
threads: [],
getThreads: () => commentsProvider.threads,
createThread: (thread) => {
commentsProvider.threads.push(thread)
return thread
},
updateThread: (id, data) => {
const index = commentsProvider.threads.findIndex((t) => t.id === id)
if (index !== -1) {
commentsProvider.threads[index] = { ...commentsProvider.threads[index], ...data }
}
},
deleteThread: (id) => {
commentsProvider.threads = commentsProvider.threads.filter((t) => t.id !== id)
},
}
export default function Page() {
const editor = useEditor({
immediatelyRender: false,
extensions: [
StarterKit,
AiToolkit,
Comments.configure({
provider: commentsProvider,
}),
],
content: `<h1>Document with Comments</h1><p>This is a sample document where AI can add and manage comments.</p>`,
})
const [workflowId, setWorkflowId] = useState('')
const [task, setTask] = useState('Add a comment suggesting improvements to this document')
const { submit, isLoading, object } = useObject({
api: '/api/comments-workflow',
schema: editThreadsWorkflowOutputSchema,
})
// Apply operations as they stream in
useEffect(() => {
if (!editor || !object?.operations) return
const toolkit = getAiToolkit(editor)
toolkit.editThreadsWorkflow({
operations: object.operations,
workflowId,
isStreaming: isLoading,
})
}, [editor, object, workflowId, isLoading])
if (!editor) return null
const manageComments = () => {
setWorkflowId(uuid())
const toolkit = getAiToolkit(editor)
// Get the document content and existing threads
const { content } = toolkit.tiptapRead()
const { threads } = toolkit.getThreads()
// Call the API endpoint to start the workflow
submit({ content, threads, task })
}
return (
<div>
<EditorContent editor={editor} />
<input
type="text"
value={task}
onChange={(e) => setTask(e.target.value)}
placeholder="Enter task for comments..."
/>
<button onClick={manageComments} disabled={isLoading}>
{isLoading ? 'Processing...' : 'Manage Comments with AI'}
</button>
</div>
)
}Available operations
The Comments workflow supports the following operations:
| Operation | Description |
|---|---|
| Create thread | Creates a new thread at a specific location |
| Create comment | Adds a comment to an existing thread |
| Update comment | Updates an existing comment |
| Remove comment | Removes a comment from a thread |
| Remove thread | Removes an entire thread |
| Resolve thread | Marks a thread as resolved |
| Unresolve thread | Marks a thread as unresolved |
End result
With additional CSS styles, the result is a polished comments management application:
See the source code on GitHub.
Related guides
- API reference of the
tiptapReadmethod - API reference of the
getThreadsmethod - API reference of the
editThreadsWorkflowmethod - Comments extension: Learn more about the Comments extension.