Custom nodes

Continuation from the AI agent chatbot guide

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

If your document includes custom nodes or marks, configure editor context so the Server AI Toolkit can describe them correctly to your AI model.

Why configure custom nodes?

Without editor context, the AI model might generate content that your editor does not support, or miss custom elements entirely. Adding custom node metadata gives the model enough context to generate those elements reliably.

Get editor context data

Start by generating editor context data from your editor. The Server AI Toolkit uses this data to describe your document structure to the AI model.

import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
import { getEditorContext, ServerAiToolkit } from '@tiptap/server-ai-toolkit'

const editor = new Editor({
  extensions: [StarterKit, ServerAiToolkit],
})

// Retrieve the editor context data
const editorContext = getEditorContext(editor)

Store the editor context data

The editor context data returned by getEditorContext is a JSON-serializable object that you can store in your database. You don't need to generate it every time. Update it when your editor extensions or schema change.

Configure custom nodes

If your document contains custom Nodes and Marks, add the addJsonSchemaAwareness option to the extension configuration. This allows the AI model to understand and generate that custom node or mark accurately.

For example, if you have a custom node called 'alert', configure it like this:

import { Node } from '@tiptap/core'
import { z } from 'zod'

const CustomExtension = Node.create({
  name: 'alert',

  addAttributes() {
    return {
      type: {
        default: 'info',
        parseHTML: (element) => element.getAttribute('data-type'),
        renderHTML: (attributes) => {
          if (!attributes.type) {
            return {}
          }

          return {
            'data-type': attributes.type,
          }
        },
      },
    }
  },

  addJsonSchemaAwareness() {
    return {
      name: 'Alert Box',
      description: `A highlighted box used to display important information, warnings, or tips to the user.
It can contain inline content like text and formatting marks.`,
      attributes: {
        type: z
          .enum(['info', 'warning', 'error', 'success'])
          .describe(
            'The type of alert. Can be one of these 4 values: info, warning, error, or success',
          ),
      },
    }
  },

  parseHTML() {
    return [
      {
        tag: 'div[data-alert]',
      },
    ]
  },

  renderHTML({ HTMLAttributes }) {
    return ['div', { ...HTMLAttributes, 'data-alert': '' }, 0]
  },
})

The addJsonSchemaAwareness function should return an object with:

  • name (string): The human-readable name of the element in English
  • description? (string): Explanation of the element in English for the AI model
  • attributes? (Record<string, z.ZodTypeAny>): Possible attributes of the element, defined as Zod schemas that will be converted to JSON schemas

What about official Tiptap extensions?

Editor context for official Tiptap extensions is automatically supported by the Server AI Toolkit. They do not need to be configured. You can still override the default editor context information for official Tiptap extensions by extending the extension and adding the addJsonSchemaAwareness option.

Next steps