Tracked changes

Experimental API

This guide uses the Tracked Changes extension, which is is experimental and may change in future releases.

Continuation from the AI agent chatbot guide

This guide continues the AI agent chatbot guide. Read it first.

Display server-side AI edits as tracked changes, so your users can review and accept or reject them individually. This integrates the Server AI Toolkit with the Tracked Changes extension.

See the source code on GitHub.

How it works

  1. The AI reads the document with tiptapRead.
  2. The AI edits the document with tiptapEdit in trackedChanges mode.
  3. The server writes tracked change marks instead of directly mutating the document.
  4. The client displays the tracked changes and lets users accept or reject them.

Show tracked changes

To display server-side AI edits as tracked changes, configure reviewOptions for trackedChanges mode when executing tools. See the review options reference for all available settings.

Execute tools with tracked changes

Pass reviewOptions when calling execute-tool:

const result = await fetch(`${apiBaseUrl}/toolkit/execute-tool`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${jwtToken}`,
    'X-App-Id': appId,
  },
  body: JSON.stringify({
    toolName: 'tiptapEdit',
    input: toolCallInput,
    schemaAwarenessData,
    sessionId,
    experimental_documentOptions: {
      documentId: 'your-document-id',
      userId: 'ai-assistant',
    },
    reviewOptions: {
      mode: 'trackedChanges',
      trackedChangesOptions: {
        userId: 'ai-assistant',
        userMetadata: {
          name: 'AI Assistant',
        },
      },
    },
  }),
})

See the review options reference for the full reviewOptions shape, including trackedChangesOptions and diffUtilityOptions.

Client-side setup

On the client, add the ServerAiToolkit and TrackedChanges extensions. The TrackedChanges extension must be configured with enabled: false because the server enables it automatically when writing tracked changes.

import { useChat } from '@ai-sdk/react'
import { Collaboration } from '@tiptap/extension-collaboration'
import { EditorContent, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { TrackedChanges, findSuggestions } from '@tiptap-pro/extension-tracked-changes'
import { TiptapCollabProvider } from '@tiptap-pro/provider'
import { ServerAiToolkit, getSchemaAwarenessData } from '@tiptap-pro/server-ai-toolkit'

export default function Page() {
  const editor = useEditor({
    immediatelyRender: false,
    extensions: [
      StarterKit.configure({ undoRedo: false }),
      Collaboration.configure({ document: doc }),
      TrackedChanges.configure({ enabled: false }),
      ServerAiToolkit,
    ],
  })

  // ... 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.

See the source code on GitHub.

Add comments with tracked changes

See the source code on GitHub.

You can make the AI provide a justification for each change. Each justification becomes a comment thread linked to its tracked change, using the Comments extension.

API endpoint

When fetching tool definitions, pass the top-level operationMeta option to add a meta field to tiptapEdit operations. Then instruct the AI to provide a justification in that meta field.

const response = await fetch(`${apiBaseUrl}/toolkit/tools`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${jwtToken}`,
    'X-App-Id': appId,
  },
  body: JSON.stringify({
    schemaAwarenessData,
    tools: {
      tiptapEdit: true,
    },
    operationMeta: 'Brief justification explaining why this change improves the document.',
  }),
})

Execute tools with comments

Pass experimental_commentsOptions alongside reviewOptions when calling execute-tool:

const result = await fetch(`${apiBaseUrl}/toolkit/execute-tool`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${jwtToken}`,
    'X-App-Id': appId,
  },
  body: JSON.stringify({
    toolName: 'tiptapEdit',
    input: toolCallInput,
    schemaAwarenessData,
    sessionId,
    experimental_documentOptions: {
      documentId: 'your-document-id',
      userId: 'ai-assistant',
    },
    reviewOptions: {
      mode: 'trackedChanges',
      trackedChangesOptions: {
        userId: 'ai-assistant',
        userMetadata: {
          name: 'AI Assistant',
        },
      },
    },
    experimental_commentsOptions: {
      threadData: { userName: 'Tiptap AI' },
      commentData: { userName: 'Tiptap AI' },
    },
  }),
})

Each non-empty meta field in the edit operations becomes a comment thread linked to its tracked change. The justification is stored as the thread's first comment content and as suggestionReason in the thread data.

Client-side setup

On the client, add the CommentsKit extension with a TiptapCollabProvider:

import { CommentsKit } from '@tiptap-pro/extension-comments'
import { TrackedChanges } from '@tiptap-pro/extension-tracked-changes'
import { ServerAiToolkit } from '@tiptap-pro/server-ai-toolkit'

const editor = useEditor({
  extensions: [
    StarterKit.configure({ undoRedo: false }),
    Collaboration.configure({ document: doc }),
    TrackedChanges.configure({ enabled: false }),
    ServerAiToolkit,
    CommentsKit.configure({
      provider, // Your TiptapCollabProvider instance
    }),
  ],
})

Users can review the tracked change and read the AI's justification in the comments sidebar.

See the source code on GitHub.

Next steps