Workflows
Workflows are scenarios where the AI model has a single, well-defined task. The AI Toolkit includes these built-in workflows:
Below is the API reference for the methods that support these built-in workflows.
createProofreaderWorkflow (server-side utility)
Creates a ready-made workflow configuration for proofreading. Returns a system prompt and schemas for validating AI output.
The workflow expects a user prompt as a JSON object with:
content: The content of the document to be proofread (see the client-side setup section on how to obtain it)task: A string describing the task to completecontext: (Optional) Additional context or background information related to the task
Returns
systemPrompt(string): Ready-to-use system prompt that instructs the AI model on how to generate proofreading operationszodOutputSchema(ZodObject): Zod schema for validating the AI outputjsonOutputSchema(object): JSON schema for validating the AI output
The systemPrompt field contains an example ready-to-use prompt with sensible defaults. We encourage you to read it and modify it to fit your needs.
Example
import { createProofreaderWorkflow } from '@tiptap-pro/ai-toolkit-tool-definitions'
import { Output, streamText } from 'ai'
import { openai } from '@ai-sdk/openai'
// Get the content from the API endpoint request
const { content } = apiEndpointRequest
// Create and configure the workflow
const workflow = createProofreaderWorkflow()
const result = streamText({
model: openai('gpt-5-mini'),
// System prompt
system: workflow.systemPrompt,
// User message with the content and the task
prompt: JSON.stringify({
content,
task: 'Correct all grammar and spelling mistakes',
context: 'This is a formal business document',
}),
output: Output.object({ schema: workflow.zodOutputSchema }),
// If you use gpt-5-mini, set the reasoning effort to minimal to improve the
// response time.
providerOptions: {
openai: {
reasoningEffort: 'minimal',
},
},
})createInsertContentWorkflow (server-side utility)
Creates a ready-made workflow configuration for inserting or replacing content. Returns a system prompt for the AI model.
The workflow expects a user prompt that is a JSON object with the following properties:
task: the task to completereplace: the HTML content to be replaced (optional)before: the HTML content before (optional)after: the HTML content after (optional)
Returns
systemPrompt(string): Ready-to-use system prompt that instructs the AI model on how to generate HTML content
The systemPrompt field contains an example ready-to-use prompt with sensible defaults. We encourage you to read it and modify it to fit your needs.
Example
import { createInsertContentWorkflow } from '@tiptap-pro/ai-toolkit-tool-definitions'
import { streamText } from 'ai'
import { openai } from '@ai-sdk/openai'
// Get the task and selection from the API endpoint request
const { task, replace } = apiEndpointRequest
// Create and configure the workflow
const workflow = createInsertContentWorkflow()
const result = streamText({
model: openai('gpt-5-mini'),
// System prompt
system: workflow.systemPrompt,
// User message with the task and content in a JSON object
prompt: JSON.stringify({
task,
replace,
}),
// If you use gpt-5-mini, set the reasoning effort to minimal to improve the
// response time.
providerOptions: {
openai: {
reasoningEffort: 'minimal',
},
},
})
return result.toTextStreamResponse()proofreaderWorkflow
Applies a list of proofreading operations to the document.
Parameters
options(ProofreaderWorkflowOptions): Configuration optionsoperations(PartialProofreaderOperation[]): Array of proofreading operations.workflowId(unknown): Unique ID for this workflow runreviewOptions?(ReviewOptions): Control preview/review behaviormode?('disabled' | 'review' | 'preview'): Whether to review the changes before or after applying them.'disabled'means no review,'review'means review after applying,'preview'means preview before applying. Default:'disabled'diffMode?('detailed' | 'full'): How to display the difference between the original and the modified content, when review mode is enabled.'detailed'compares the documents before and after the change and displays the deleted content and added content as a rich diff.'full'displays the deleted content and added content in a whole block, as a single change containing the deleted and added content. Default:'detailed'displayOptions?(DisplayOptions<{ suggestion: Suggestion }>): Customize how suggestions are displayedshowAsDiff?(boolean): Whether to show the suggestion as a diff where inserted and original content are displayed side by side. Default:truediffPosition?('before' | 'after'): The position of the diff relative to the suggestion. Default:'before'attributes?(Record<string, any>): Extra HTML attributes to be added to the suggestionrenderDecorations?(RenderDecorations<{ suggestion: Suggestion }>): A function to render the suggestion as ProseMirror decorations
metadata?(Record<string, any>): Extra metadata for the suggestions that can be used to store additional information about them (e.g. their source or their category). It is not used internally by the extension but it may help developers customize how the suggestions are displayed in the UI.diffUtilityConfig?(DiffUtilityConfig): Options for comparing the documents with the diff utilitysimplifyChanges?(boolean): Whether to simplify the changes. Iftrue, the changes will be simplified so that, for example, two changes in the same word are merged into a single change. Only applies when mode is 'detailed', 'smartInline', or 'smartInlineV2'. Default:trueignoreAttributes?(string[]): The attributes to ignore. Default:['id', 'data-thread-id']ignoreMarks?(string[]): The marks to ignore. Default:['inlineThread']changeMergeDistance?(number | null): Maximum distance (in document positions) between changes to merge them. If two adjacent changes have a distance less than or equal to this value in either rangeA or rangeB, they will be merged into a single change. Set tonullorundefinedto disable merging. Only applies when mode is 'detailed'. Default:nullmode?('detailed' | 'block' | 'smartInline' | 'smartInlineV2'): The diff mode to use for comparison.'detailed'performs character-level diff that identifies precise changes within text (default).'block'performs block-level diff that treats each top-level node as a single unit. Block mode is useful when you only need to know which paragraphs, headings, or other block-level elements have changed, without character-level detail. In block mode,simplifyChangesandchangeMergeDistanceoptions are ignored.'smartInline'combines both approaches: first identifies changed blocks, then performs inline diff within those blocks. This is more efficient for documents where only portions have changed, while still providing character-level precision. 'smartInlineV2' improves on 'smartInline' by displaying changes in block elements (like tables) correctly. Default:'detailed'
range?(Range): The range to apply the proofreading operations tofrom(number): Start positionto(number): End position
selectableNodeTypes?(string[]): Array of node type names that should always have hashes, even if they are not top-level nodes. By default, all block node types can have hashes. If set to[], only top-level nodes will have hashes.
Returns (ProofreaderWorkflowResult)
doc(Node): The modified document after applying operationsoperations(ProofreaderOperationResult[]): Array of operation results, in the same order as the input operations. Each result contains:delete(string): The text that was deleted (or supposed to be deleted)insert(string): The text that was inserted (or supposed to be inserted)success(boolean): Whether the operation was successfulerror?(string): Error message if the operation failed
Example
const toolkit = getAiToolkit(editor)
// Get the document in a format that allows the AI to make fast, efficient edits
const { content } = toolkit.tiptapRead()
const operations = await callApiEndpoint({ content })
// Apply proofreading corrections
const result = toolkit.proofreaderWorkflow({
operations,
workflowId: 'proofread-123',
reviewOptions: {
mode: 'preview',
},
})createTiptapEditWorkflow (server-side utility)
Creates a ready-made workflow configuration for editing documents. Returns a system prompt and schemas for validating AI output.
The workflow expects a user prompt as a JSON object with:
content: The content of the document to be edited (obtained fromtiptapRead)task: A string describing the editing task to completecontext: (Optional) Additional context or background information related to the task
Returns
systemPrompt(string): Ready-to-use system prompt that instructs the AI model on how to generate edit operationszodOutputSchema(ZodObject): Zod schema for validating the AI outputjsonOutputSchema(object): JSON schema for validating the AI output
Example
import { createTiptapEditWorkflow } from '@tiptap-pro/ai-toolkit-tool-definitions'
import { Output, streamText } from 'ai'
import { openai } from '@ai-sdk/openai'
// Get the content and task from the API endpoint request
const { content, task } = apiEndpointRequest
// Create and configure the workflow
const workflow = createTiptapEditWorkflow()
const result = streamText({
model: openai('gpt-5-mini'),
system: workflow.systemPrompt,
prompt: JSON.stringify({ content, task, context }),
output: Output.object({ schema: workflow.zodOutputSchema }),
})tiptapEditWorkflow
Applies a list of edit operations to the document.
Parameters
options(TiptapEditWorkflowOptions): Configuration optionsoperations(PartialTiptapEditOperation[]): Array of edit operations. Each operation is a tuple[type, target, content]:type:'replace'|'insertBefore'|'insertAfter'target: The 6-character hash of the node (fromtiptapRead) or'doc'for entire documentcontent: HTML string with the content to insert
workflowId(unknown): Unique ID for this workflow runselectableNodeTypes?(string[]): Array of node type names that should always have hashes, even if they are not top-level nodes. By default, all block node types can have hashes. If set to[], only top-level nodes will have hashes.reviewOptions?(ReviewOptions): Control preview/review behavior (same options asproofreaderWorkflow)tiptapEditHooks?(TiptapEditHooks): Hooks for intercepting and modifying operations. See the Tiptap Edit hooks guide for details.beforeOperation?((context: BeforeOperationContext) => BeforeOperationResult): Called before each operation is applied. Return{ action: 'accept' }to apply the operation (optionally withfragmentoroperationTypeoverrides), or{ action: 'reject', error }to skip it.
Returns (TiptapEditWorkflowResult)
doc(Node): The modified document after applying operationssuccessful(string[]): Array of successfully processed operationsfailed({ target: string; error?: string }[]): Array of failed operations with error messages
Example
const toolkit = getAiToolkit(editor)
// Get the document content
const { content } = toolkit.tiptapRead()
const operations = await callApiEndpoint({ content, task: 'Make the text more formal' })
// Apply edit operations
const result = toolkit.tiptapEditWorkflow({
operations,
workflowId: 'edit-123',
reviewOptions: {
mode: 'preview',
},
})createEditThreadsWorkflow (server-side utility)
Creates a ready-made workflow configuration for managing comments and threads. Returns a system prompt and schemas for validating AI output.
The workflow expects a user prompt as a JSON object with:
content: The content of the document (obtained fromtiptapRead)threads: The existing threads in the document (obtained fromgetThreads)task: A string describing the comment management task to complete
Returns
systemPrompt(string): Ready-to-use system prompt that instructs the AI model on how to manage commentszodOutputSchema(ZodObject): Zod schema for validating the AI outputjsonOutputSchema(object): JSON schema for validating the AI output
Example
import { createEditThreadsWorkflow } from '@tiptap-pro/ai-toolkit-tool-definitions'
import { Output, streamText } from 'ai'
import { openai } from '@ai-sdk/openai'
// Get the content, threads, and task from the API endpoint request
const { content, threads, task } = apiEndpointRequest
// Create and configure the workflow
const workflow = createEditThreadsWorkflow()
const result = streamText({
model: openai('gpt-5-mini'),
system: workflow.systemPrompt,
prompt: JSON.stringify({ content, threads, task }),
output: Output.object({ schema: workflow.zodOutputSchema }),
})getThreads
Retrieves all threads in the document with their comments and location information.
Returns (GetThreadsResult)
threadCount(number): The number of threads in the documentthreads(ThreadInfo[]): Array of thread information, each containing:id(string): The unique identifier of the threadcomments({ id: string; content: string }[]): Array of comments in the threadnodeRange?(string): The range of nodes where the thread is locateddocumentContent?(string): The HTML content where the thread is applied
Example
const toolkit = getAiToolkit(editor)
// Get all threads in the document
const result = toolkit.getThreads()
console.log(`Found ${result.threadCount} threads`)
result.threads.forEach((thread) => {
console.log(`Thread ${thread.id}: ${thread.comments.length} comments`)
})editThreadsWorkflow
Applies comment and thread operations to the document.
Parameters
options(EditThreadsWorkflowOptions): Configuration optionsoperations(string[][]): Array of comment operations as tuples.selectableNodeTypes?(string[]): Array of node type names that should always have hashes, even if they are not top-level nodes. By default, all block node types can have hashes. If set to[], only top-level nodes will have hashes.commentsOptions?(CommentsOptions): Options for comment operationsthreadData?(Record<string, any>): Extra metadata for created threadscommentData?(Record<string, any>): Extra metadata for created comments
Returns (EditThreadsWorkflowResult)
operations(EditThreadsOperationResult[]): Array of operation resultssuccess(boolean): Whether all operations were successful
Example
const toolkit = getAiToolkit(editor)
// Get document and threads
const { content } = toolkit.tiptapRead()
const { threads } = toolkit.getThreads()
const operations = await callApiEndpoint({ content, threads, task: 'Add review comments' })
// Apply comment operations
const result = toolkit.editThreadsWorkflow({
operations,
})
if (result.success) {
console.log('All comment operations completed successfully')
}createTemplateWorkflow (server-side utility)
Creates a ready-made workflow configuration for filling templates. Accepts an HTML template string (generated by the createHtmlTemplate method on the client), auto-extracts all template keys, and returns a system prompt and schemas for validating AI output.
The workflow expects a user prompt as a JSON object with:
task: A string describing what content to generate for the templatecontext: (Optional) Additional context or background information related to the task
Parameters
options(CreateTemplateWorkflowOptions): Configuration optionshtmlTemplate(string): The template as an HTML string, generated by thecreateHtmlTemplatemethod on the client
Returns
systemPrompt(string): Ready-to-use system prompt that instructs the AI model on how to fill the templatezodOutputSchema(ZodObject): Zod schema for validating the AI outputjsonOutputSchema(object): JSON schema for validating the AI output
Example
import { createTemplateWorkflow } from '@tiptap-pro/ai-toolkit-tool-definitions'
import { Output, streamText } from 'ai'
import { openai } from '@ai-sdk/openai'
const { htmlTemplate, task } = apiEndpointRequest
const workflow = createTemplateWorkflow({ htmlTemplate })
const result = streamText({
model: openai('gpt-5-mini'),
system: workflow.systemPrompt,
prompt: JSON.stringify({ task, context }),
output: Output.object({ schema: workflow.zodOutputSchema }),
})
return result.toTextStreamResponse()templateWorkflow
Fills a Tiptap JSON template with AI-generated values and inserts the result into the editor. The template uses special attributes (_templateSlot, _templateIf, _templateAttributes) to mark dynamic parts.
Parameters
options(TemplateWorkflowOptions): Configuration optionstemplate(Record<string, any>): The template in Tiptap JSON format (a doc node or fragment array)values(TemplateValues): AI-generated values to fill the template. Keys correspond to template attribute values.position?(InsertPosition): Where to insert the filled template. Default:'selection'hasFinished?(boolean): Whether streaming has finished. When omitted, the method runs in non-streaming mode. Default:trueworkflowId?(unknown): Unique ID for this workflow run. When provided, enables streaming mode where the method tracks the insertion range across calls and replaces content progressively.reviewOptions?(ReviewOptions): Control preview/review behaviormode?('disabled' | 'review' | 'preview'): Whether to review the changes before or after applying them. Default:'disabled'
Example
import { experimental_useObject as useObject } from '@ai-sdk/react'
import { getAiToolkit } from '@tiptap-pro/ai-toolkit'
import { z } from 'zod'
const templateSchema = z.object({}).passthrough()
const { submit, isLoading, object } = useObject({
api: '/api/template-workflow',
schema: templateSchema,
})
// Stream partial results in a useEffect
useEffect(() => {
if (!editor || !object) return
const toolkit = getAiToolkit(editor)
toolkit.templateWorkflow({
template: templateJson,
values: object as Record<string, unknown>,
position: 'document',
hasFinished: !isLoading,
workflowId,
})
}, [object, workflowId, editor, isLoading])createHtmlTemplate
Converts a Tiptap JSON template to an HTML string with template attributes preserved. The resulting HTML can be sent to the server where createTemplateWorkflow parses the template keys.
Since this is an AI Toolkit method, the editor schema is automatically available — you only need to pass the template.
Parameters
template(Record<string, unknown>): The template as Tiptap JSON (a doc node or fragment array)
Returns
- An HTML
stringwith lowercased template attributes (_templateslot,_templateif,_templateattributes)
Example
const toolkit = getAiToolkit(editor)
const htmlTemplate = toolkit.createHtmlTemplate(templateJson)