Tracked changes
Experimental
The Tracked Changes extension is currently in Alpha phase.
Continuation from the AI agent chatbot guide
This guide continues the AI agent chatbot guide. Read it first.
Display AI-generated changes as tracked changes, so your users can review and accept or reject them individually. This integrates the AI Toolkit with the Tracked Changes extension.
See the source code on GitHub.
Show tracked changes
To display AI edits as tracked changes, set reviewOptions.mode to 'trackedChanges' when executing a tool.
API endpoint
The API endpoint is the same as in the AI agent chatbot guide. No changes are needed on the server side to enable tracked changes.
// app/api/tracked-changes/route.ts
import { openai } from '@ai-sdk/openai'
import { toolDefinitions } from '@tiptap-pro/ai-toolkit-ai-sdk'
import { createAgentUIStreamResponse, ToolLoopAgent, type UIMessage } from 'ai'
export async function POST(req: Request) {
const { messages }: { messages: UIMessage[] } = await req.json()
const agent = new ToolLoopAgent({
model: openai('gpt-5.4-mini'),
instructions:
'You are an assistant that can edit rich text documents. Use tiptapRead before tiptapEdit.',
tools: toolDefinitions(),
})
return createAgentUIStreamResponse({
agent,
uiMessages: messages,
})
}Client-side setup
On the client, add the TrackedChanges extension and pass reviewOptions with mode 'trackedChanges' to the executeTool method.
The TrackedChanges extension must be configured with enabled: false — the AI Toolkit enables it automatically when needed.
import { useChat } from '@ai-sdk/react'
import { EditorContent, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { AiToolkit, getAiToolkit } from '@tiptap-pro/ai-toolkit'
import { TrackedChanges } from '@tiptap-pro/extension-tracked-changes'
import { DefaultChatTransport, lastAssistantMessageIsCompleteWithToolCalls } from 'ai'
export default function Page() {
const editor = useEditor({
immediatelyRender: false,
extensions: [
StarterKit,
TrackedChanges.configure({
enabled: false,
}),
AiToolkit,
],
content: `<p>Ask the AI to improve this document.</p>`,
})
const { messages, sendMessage, addToolOutput } = useChat({
transport: new DefaultChatTransport({ api: '/api/tracked-changes' }),
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls,
async onToolCall({ toolCall }) {
if (!editor) return
const toolkit = getAiToolkit(editor)
const result = toolkit.executeTool({
toolName: toolCall.toolName,
input: toolCall.input,
reviewOptions: {
mode: 'trackedChanges',
trackedChangesOptions: {
userId: 'ai-assistant',
userMetadata: {
name: 'AI',
},
},
},
})
addToolOutput({
tool: toolCall.toolName,
toolCallId: toolCall.toolCallId,
output: result.output,
})
},
})
// ... render editor and chat UI
}After the AI edits the document, the changes appear as tracked changes. Users can accept or reject them using the acceptSuggestion, rejectSuggestion, acceptAllSuggestions, and rejectAllSuggestions commands from the Tracked Changes extension.
End result
See the source code on GitHub.
Next steps
- Learn more about review options in the API reference.
- Add real-time streaming with the streaming guide.
- Learn about the Tracked Changes extension for styling and configuration options.
- Combine tracked changes with comments using the tracked changes with comments guide.