Fragment responses
A fragment response contains only the elements the agent changed. Change one heading in a long manual, and the response holds that heading, not the manual. You pay for fewer tokens and wait less time.
A standard LLM call returns the whole document, because the model rewrites everything around the change to keep the HTML valid. CKEditor AI returns a fragment instead: the elements the agent edited, added, or removed, and a comment in place of everything else.
This page describes what a fragment contains and how to apply one to your document.
A fragment is one block of HTML and HTML comments that describes the changes to a document. Each element appears in one of these forms:
- Edited element: the element’s HTML with its new content and the
data-idit already had. - Added element: the element’s HTML with
data-id="new-element". - Removed element: the comment
<!-- removed data-id="the-id" -->. - Unchanged content: the comment
<!-- existing document -->. One comment stands for one group of elements that did not change, whether that group is one element or fifty.<!-- existing content -->means the same thing, and both forms arrive.
Add a unique data-id attribute to every element before you send the document. Without it, the fragment cannot tell you which element changed.
Every element in the fragment has a data-id attribute. For an edited or removed element, the data-id is the one the element has in the document you sent. Use it to find the element in your copy and apply the change.
The ids can take any form as long as they are unique. Short ones, such as four random letters, cost fewer tokens. They have to stay stable for the life of the request, and the copy you merge into has to be the snapshot you sent. A fragment never names an id the document did not have. After you apply one, give every element a unique id again, so the next request can address the new ones.
Reviews use the same convention. Each suggestion names the element it applies to. See How results are anchored.
Walk the fragment in document order and apply each part to your copy:
- Replace: an element that carries a
data-idfrom your document replaces that element. A change inside it, such as a new link or a bolded word, arrives as the whole element. - Insert: an element with
data-id="new-element"is new. Put it where it sits among the elements the fragment names around it, or at the top of the document when it comes first. - Remove:
<!-- removed data-id="p2" -->deletes that element and everything inside it. - Move: a move arrives as a removal in one place and a
new-elementinsertion in another. - Reorder: reordered elements arrive either as their whole parent with the children in the new order and their ids kept, or as a removal and a
new-elementinsertion per moved element, the same as a move. - Any depth: an element in the fragment can sit at any depth in your document, not only at the top level. Match on
data-idwherever the element is, or a nested change lands as an insertion and duplicates the content.
These fragments all describe changes to the same document:
<h2 data-id="h1">Handheld emperor</h2>
<p data-id="p1">Nintendo started as a card manufacturer in 1889.</p>
<h3 data-id="h2">Handheld gaming</h3>
<p data-id="p2">The Game Boy changed everything.</p>
<ul data-id="l1">
<li data-id="i1">LCD screen</li>
<li data-id="i2">Button cells</li>
</ul>
<p data-id="p3">Nintendo keeps redefining portable gaming.</p>Copy code“Rewrite the second paragraph and say how many Game Boys were sold” comes back as the rewritten element between two runs of unchanged content:
<!-- existing document -->
<p data-id="p2">The Game Boy sold 118 million units.</p>
<!-- existing document -->Copy codeApplied, only p2 differs from the document above.
“Remove the second heading, the paragraph, and the list behind it” names each element it removes:
<!-- existing document -->
<!-- removed data-id="h2" -->
<!-- removed data-id="p2" -->
<!-- removed data-id="l1" -->
<!-- existing document -->Copy codeThe list items i1 and i2 go with l1. What is left is:
<h2 data-id="h1">Handheld emperor</h2>
<p data-id="p1">Nintendo started as a card manufacturer in 1889.</p>
<p data-id="p3">Nintendo keeps redefining portable gaming.</p>Copy code“Add a Game & Watch era section after the second paragraph” names the elements on either side of the new ones, so you know where they go:
<!-- existing document -->
<p data-id="p2">The Game Boy changed everything.</p>
<h3 data-id="new-element">Game & Watch era</h3>
<p data-id="new-element">Nintendo's first portable line.</p>
<ul data-id="l1">
<li data-id="i1">LCD screen</li>
<li data-id="i2">Button cells</li>
</ul>
<!-- existing document -->Copy codeIn your copy, the heading and the paragraph sit between p2 and l1, and you give each of them an id of your own.
“Split the first paragraph into two” keeps the id on the first part. The second part is a new element, and the fragment names h2 so you know it goes before the heading:
<!-- existing document -->
<p data-id="p1">Nintendo started as a card manufacturer.</p>
<p data-id="new-element">The company was founded in 1889.</p>
<h3 data-id="h2">Handheld gaming</h3>
<!-- existing document -->Copy codeApplied, p1 holds the shorter sentence and a new paragraph follows it.
“Wrap the last paragraph in a blockquote” arrives as a new wrapper with a new paragraph inside, followed by the removal of the original:
<!-- existing document -->
<ul data-id="l1">
<li data-id="i1">LCD screen</li>
<li data-id="i2">Button cells</li>
</ul>
<blockquote data-id="new-element">
<p data-id="new-element">Nintendo keeps redefining portable gaming.</p>
</blockquote>
<!-- removed data-id="p3" -->Copy codeThe text is unchanged, but p3 is gone. Any state you keep against that id, such as a comment thread, needs a new anchor.
In CKEditor 5, the CKEditor AI plugin does the merge for you. See What comes back in the response.
To apply a fragment yourself, keep the document you sent and read the fragment in order. Apply each edit, addition, and removal to the element with the matching data-id, following the merge rules above. Two cases need care. A parent and its child can both appear in the fragment, and a user can edit the document while the request runs.
To ask for fragments, set responseFormat to arf. See Response format for the request field, and the Document Processing reference for the response schema.
- Document Processing covers the request and response for editing whole documents in one call.
- Streaming protocol lists the events that contain fragments on the streaming endpoints.