---
title: "Tiptap Edit workflow"
description: "Use the Tiptap AI Toolkit to build a workflow that edits documents with AI-generated content."
canonical_url: "https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/workflows/tiptap-edit"
---

# Tiptap Edit workflow

Use the Tiptap AI Toolkit to build a workflow that edits documents with AI-generated content.

Build a workflow that allows the AI to edit your Tiptap documents with precise, efficient operations.

> **Interactive demo:** [tiptap edit workflow](https://ai-toolkit-demos.vercel.app/tiptap-edit-workflow)

See the [source code on GitHub](https://github.com/ueberdosis/ai-toolkit-demos).

## Tech stack

- [React](https://react.dev/) + [Next.js](https://nextjs.org/)
- [AI SDK by Vercel](https://ai-sdk.dev/) + [OpenAI](https://openai.com/) models
- Tiptap AI Toolkit

## Project overview

This demo uses the AI Toolkit's Tiptap Edit workflow to apply edit operations to the document in real-time. The workflow supports replacing, inserting before, and inserting after nodes.

## Installation

Create a [Next.js](https://nextjs.org/) project:

```bash
npx create-next-app@latest tiptap-edit-workflow
```

Install the core Tiptap packages and the [Vercel AI SDK](https://ai-sdk.dev/) for OpenAI:

```bash
npm install @tiptap/react @tiptap/starter-kit ai @ai-sdk/react @ai-sdk/openai zod uuid
```

Install the Tiptap AI Toolkit:

> **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](https://tiptap.dev/docs/guides/pro-extensions.md).

```bash
npm install @tiptap-pro/ai-toolkit @tiptap-pro/ai-toolkit-tool-definitions
```

## Server setup

Create an API endpoint that uses the [Vercel AI SDK](https://ai-sdk.dev/) to call the OpenAI model.

If your backend is in another programming language than TypeScript, see [this guide](https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/advanced-guides/non-typescript-backends.md).

Inside the API endpoint, create and configure the Tiptap Edit workflow using the `createTiptapEditWorkflow` function. The workflow includes a ready-to-use system prompt that instructs the AI model on how to generate edit operations.

Additionally, you need to include these two properties in the user message:

- `content`: The content of the document to be edited (obtained from `tiptapRead`)
- `task`: The task to be performed by the AI. For example, `Make the text more formal`.
- `context`: (Optional) Additional context or background information related to the task.

As the AI model generates its response, the API endpoint streams the operations to the client.

```ts
// app/api/tiptap-edit-workflow/route.ts
import { openai } from '@ai-sdk/openai'
import { createTiptapEditWorkflow } from '@tiptap-pro/ai-toolkit-tool-definitions'
import { Output, streamText } from 'ai'

export async function POST(req: Request) {
  const { content, task, context } = await req.json()

  // Create and configure the Tiptap Edit workflow (with the default settings).
  // It includes the ready-to-use system prompt and the output schema.
  const workflow = createTiptapEditWorkflow()

  const result = streamText({
    model: openai('gpt-5.4-mini'),
    // System prompt
    system: workflow.systemPrompt,
    // User message
    prompt: JSON.stringify({
      content,
      task,
      context,
    }),
    output: Output.object({ schema: workflow.zodOutputSchema }),
  })

  return result.toTextStreamResponse()
}
```

## Client setup

Create a React component that renders the editor and applies the edits in real-time.

First, when the editing process starts, call the `tiptapRead` method of the AI Toolkit to read the document. The method returns the content in a format that is optimized for fast, precise edits.

Then, call the API endpoint to start the workflow. The component uses Vercel AI SDK's `useObject` hook to handle streaming, so that the response is received bit by bit and the edits are applied in real-time.

Every time the response changes, call the `tiptapEditWorkflow` method of the AI Toolkit to apply the edits to the document in real-time. The edits are applied immediately as they are received.

```tsx
// app/tiptap-edit-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,
  type TiptapReadResult,
  getAiToolkit,
  tiptapEditWorkflowOutputSchema,
} from '@tiptap-pro/ai-toolkit'
import { useEffect, useRef, useState } from 'react'
import { v4 as uuid } from 'uuid'

export default function Page() {
  const editor = useEditor({
    immediatelyRender: false,
    extensions: [StarterKit, AiToolkit],
    content: `<h1>Document Editor</h1><p>This is a sample document that can be edited by AI.</p>`,
  })

  const [workflowId, setWorkflowId] = useState('')
  const tiptapReadResultRef = useRef<TiptapReadResult | null>(null)
  const [task, setTask] = useState('Make the text more formal and professional')

  const { submit, isLoading, object } = useObject({
    api: '/api/tiptap-edit-workflow',
    schema: tiptapEditWorkflowOutputSchema,
  })

  const operations = object?.operations ?? []

  // Stream partial results as they arrive
  useEffect(() => {
    if (!editor || !operations) return

    const toolkit = getAiToolkit(editor)
    if (!tiptapReadResultRef.current) return

    toolkit.tiptapEditWorkflow({
      operations,
      workflowId,
      hasFinished: !isLoading,
      tiptapReadResult: tiptapReadResultRef.current,
    })
  }, [operations, workflowId, editor, isLoading])

  if (!editor) return null

  const editDocument = () => {
    const toolkit = getAiToolkit(editor)

    // Obtain the content of the document to be edited
    const readResult = toolkit.tiptapRead()
    tiptapReadResultRef.current = readResult

    // Each workflow must have a unique ID
    setWorkflowId(uuid())

    // Call the API endpoint to start the workflow
    submit({ content: readResult.content, task })
  }

  return (
    <div>
      <EditorContent editor={editor} />

      <input
        type="text"
        value={task}
        onChange={(e) => setTask(e.target.value)}
        placeholder="Enter editing task..."
      />

      <button onClick={editDocument} disabled={isLoading}>
        {isLoading ? 'Editing...' : 'Edit Document'}
      </button>
    </div>
  )
}
```

## End result

With additional CSS styles, the result is a polished document editing application with real-time AI editing:

> **Interactive demo:** [tiptap edit workflow](https://ai-toolkit-demos.vercel.app/tiptap-edit-workflow)

See the [source code on GitHub](https://github.com/ueberdosis/ai-toolkit-demos).

## Show the AI Caret

You can add the `AiCaret` extension to display a cursor that indicates where the AI is editing the document. This gives users real-time visual feedback during streaming.

```tsx
import { AiCaret, AiToolkit, getAiToolkit } from '@tiptap-pro/ai-toolkit'

const editor = useEditor({
  extensions: [StarterKit, AiToolkit, AiCaret],
})
```

See the [AI Caret guide](https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/advanced-guides/ai-caret.md) for configuration options and CSS styles.

## Edit part of the document

To edit only a sub-section of the document, set the `range` option. This argument takes a [Range](https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/advanced-guides/concepts.md#range) with the region to edit.

For example, to edit only the selected content:

```ts
const range = editor.state.selection

// Read only the selected part of the document
const { content } = toolkit.tiptapRead({ range })

const operations = callApi(content)

// Apply operations in the same range
toolkit.tiptapEditWorkflow({
  operations,
})
```

For large documents, you can use the [`tiptapReadChunks`](https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/api-reference/read-the-document.md#tiptapreadchunks) method to split the document into chunks and process them in parallel. Each chunk includes a [Range](https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/advanced-guides/concepts.md#range) with the region of that chunk.

## Show a review UI

Display changes in a review UI, so users can accept or reject them.

There are two approaches:

- Use the [**Tracked Changes**](https://tiptap.dev/docs/tracked-changes/getting-started/overview.md) extension to render the review UI. Changes persist as part of the document and are visible to other users.
- **AI Toolkit suggestions**: a decoration-based UI that's ephemeral and only visible to the current user of the document.

Configure the review UI by setting the `reviewOptions` parameter. Changes will show up as suggestions that users can accept or reject.

```tsx
await toolkit.tiptapEditWorkflow({
  // ... other options

  // Show the review UI with Tracked Changes
  reviewOptions: { mode: 'trackedChanges' },

  // Show the review UI with AI Toolkit suggestions
  reviewOptions: { mode: 'review' },
})
```

See the [review changes](https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/agents/review-changes.md) guide to learn more about the review UI.

See the [AI Toolkit demos](https://github.com/ueberdosis/ai-toolkit-demos) for examples on how to use AI Toolkit workflows with the review UI.

## Related guides

- [API reference](https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/api-reference/read-the-document.md#tiptapread) of the `tiptapRead` method
- [API reference](https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/api-reference/read-the-document.md#tiptapreadchunks) of the `tiptapReadChunks` method
- [API reference](https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/api-reference/workflows.md#tiptapeditworkflow) of the `tiptapEditWorkflow` method
- [Suggestions](https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/agents/review-changes.md): Learn about reviewing the document and displaying suggestions in the editor.
- [AI Caret](https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/advanced-guides/ai-caret.md): Show a cursor where the AI is inserting content.
