Sign up (with export icon)

AI in multi-root and multi-editor setups

CKEditor AI features support multi-root editors and multiple editors sharing a Context. When your application splits content into separate editing areas – for example, a title and a body – AI Chat, AI Review, and AI Translate operate seamlessly across all of them.

Unlock this feature with selected CKEditor Plans

Try all premium features – no credit card needed.

Sign up for a free trial Select a Plan

Demo

Copy link

The editor below splits content into a title, a description, and a body. AI Chat, AI Review, and AI Translate work across all three.

Title
Description
Body

Supported setups

Copy link
  • Multi-root editor – one MultiRootEditor instance with several editable regions (like a title, a description, a body, and so on). AI features operate across all roots.
  • Multiple editors sharing a ContextContext.create( { /* ... */ } ). AI features operate across the editors in the Context instance.

Per-feature behavior

Copy link
  • AI Chat – the AI reads each root’s content together with its title and description, then decides which root to address based on the user’s prompt.
  • AI Chat history – conversation history is scoped per editor in a Context. Loading a previous conversation maps correctly even if some editors or roots have been destroyed.
  • AI Review and AI Translate – run across all roots of a multi-root editor and across all editors sharing a Context. Suggestions and translations land in the correct root and do not bleed across boundaries. Compatible with real-time collaboration.

Configuration

Copy link

This section shows how to configure CKEditor AI in the two supported setups. The base setup follows the AI integration guide; the snippets below highlight only what differs.

The fields worth pausing on are the root name, title, label, and description of each root – they look similar but each serves a distinct purpose. The AI uses them differently from assistive technologies, and the way they are declared differs between single-root editors and multi-root editors.

  • Root name – for multi-root editors, the key under config.roots property. It identifies the root in the editor’s model and in collaboration sessions, and must be stable and unique per editor. Single-root editors (ClassicEditor, BalloonEditor, InlineEditor, DecoupledEditor) do not configure a name – their root is internally named main and the name cannot be customized. Root name is used only for content mapping purposes and is not processed by LLM.
  • title – a human-readable name of the editable area. Used by the LLM to understand the meaning of a particular section. Set it on config.root for single-root editors and on each config.roots.<rootName> entry for multi-root editors. Users can refer to particular sections in the prompt – “rewrite the description”, “add a paragraph to the body” – AI will use the title to find the correct target for the query. If a root has no title, the AI falls back to its label.
  • label – the aria-label of the editable area, used by assistive technologies. It is independent of the AI, but serves as a fallback name when no title is set.
  • description – a short, human-readable description of what the root contains. Provides additional context for a particular section beyond its title. Treat the description like a short editor tooltip: a sentence that says what the root is for, oriented around its role (for example, “The main body of the article.” or “A panel that lists the article’s footnotes.”), rather than its position on the page (“The column on the right.”).

Without titles and descriptions, in multi-root or multi-editor setups, the AI cannot reliably distinguish editing areas: a suggested edit may land in the wrong area. The editor logs ai-document-root-missing-title and ai-chat-documents-missing-description warnings when this is detected.

Multi-root editor

Copy link

In a multi-root editor setup, a single editor exposes multiple editing areas. The AI feature plugins load directly on the editor, just like in any single-root setup. Each editing area is then declared under config.roots.<rootName> with its DOM element, initial data, a title and a description used by the AI, and an accessible label.

MultiRootEditor
    .create( {
        plugins: [
            AIChat, AIChatHistory, AIChatShortcuts,
            AIQuickActions, AIReviewMode, AITranslate,
            AIEditorIntegration, TrackChanges, /* ... */
        ],
        roots: {
            title: {
                element: document.querySelector( '#title' ),
                initialData: '<h1>...</h1>',
                title: 'Article title',
                label: 'Article title editing area',
                description: 'Article title that names the piece for readers.'
            },
            description: {
                element: document.querySelector( '#description' ),
                initialData: '<p>...</p>',
                title: 'Article description',
                label: 'Article description editing area',
                description: 'Article description with a short summary of the piece.'
            },
            body: {
                element: document.querySelector( '#body' ),
                initialData: '<p>...</p>',
                title: 'Article body',
                label: 'Article body editing area',
                description: 'Main article body — the primary content of the piece.'
            }
        },
        toolbar: [ 'toggleAi', 'aiQuickActions', /* ... */ ],
        ai: {
            container: {
                type: 'sidebar',
                element: document.querySelector( '.ai-sidebar' )
            }
        }

        // ... Other configuration options ...
    } )
    .then( /* ... */ )
    .catch( /* ... */ );
Copy code

Multiple editors sharing a Context

Copy link

When several editors share a Context, the AI feature plugins move to the Context-level config.plugins array, so a single Chat, History, Review, and Translate UI is shared across all editors. The editor-integration plugins stay on each editor. The config.ai.container configuration also sits on the Context – the individual editors do not need their own config.ai configuration.

Note

The Context must declare its own config.collaboration.channelId, separate from any channel IDs on the individual editors. AI Chat history is scoped per Context (not per editor), and AI will throw ai-chat-missing-channel-id if the Context has no channel ID configured.

Context
    .create( {
        plugins: [ AIChat, AIChatHistory, AIChatShortcuts, AIReviewMode, AITranslate ],
        ai: {
            container: {
                type: 'sidebar',
                element: document.querySelector( '.ai-sidebar' )
            }
        },
        collaboration: {
            channelId: 'shared-context-channel-id'
        }

        // ... Other configuration options ...
    } )
    .then( context => Promise.all( [
        ClassicEditor.create( {
            context,
            attachTo: document.querySelector( '#article-editor' ),
            plugins: [ AIEditorIntegration, AIQuickActions, TrackChanges, /* ... */ ],
            root: {
                title: 'Article body',
                label: 'Article body editing area',
                description: 'Main article body — the primary content of the piece.'
            }
        } ),

        ClassicEditor.create( {
            context,
            attachTo: document.querySelector( '#sidebar-editor' ),
            plugins: [ AIEditorIntegration, AIQuickActions, TrackChanges, /* ... */ ],
            root: {
                title: 'Related links',
                label: 'Related links editing area',
                description: 'Sidebar listing articles and resources related to the main piece.'
            }
        } )
    ] ) )
    .then( /* ... */ )
    .catch( /* ... */ );
Copy code

Known issues

Copy link

CKEditor AI does not process inline-only roots, such as $inlineRoot and custom inline-only roots. AI features operate on standard block-level roots only. Support for inline-only roots is planned for a future release.