Why AI rewrites break your documents, and what it takes to not
A model cannot edit a document, only produce text. So a tool that asks it to rewrite a file has to convert the file to text, rewrite it, and rebuild a file from the result, and everything that was not text is lost at the first step: styles, tables, numbering, images, headers. The approach that survives is to never let the model see the file at all. Extract the editable text as numbered fragments, ask for replacements by number, and have the program write those replacements back into the original structure, which it never gave the model the chance to break.
You have a specification that needs its tone flattened, a deck whose speaker notes are in the wrong language, a contract with a company name that changed. The work is mechanical, there is a lot of it, and it is precisely the sort of thing an AI should do while you have coffee.
Then you try it, and you get back a Markdown transcript of your document. Or a new file where the tables are gone, the numbered list restarted at one, and the corporate template has been replaced by whatever the tool's default looked like. Nobody involved did anything wrong. The failure is structural, and it is worth understanding because it tells you which tools can possibly work.
A model produces text, not documents
A .docx or a .pptx is not a document in the way you think of one. It is a zip archive containing XML files: one describing the content, others describing styles, themes, numbering definitions, relationships, embedded images, fonts. What you see on screen is the result of all of those being interpreted together.
A language model emits a sequence of characters. It cannot write a zip archive, it cannot maintain the internal references that hold one together, and asking it to try produces a file that either fails to open or opens wrong. So every tool that offers AI document editing has to bridge that gap somehow, and how it bridges it determines everything about the result.
The three approaches, and how each one fails
Convert to text, rewrite, hand back text
The simplest and by far the most common. It works, and it does not return a document: you get prose you now have to reformat by hand, which is often more work than the edit was.
Convert to text, rewrite, generate a new file
The one that looks like it worked, which makes it the worst. The output is a real .docx, so nothing announces a problem. But it was built from a text transcript, so it carries the generator's styles rather than yours, and everything the transcript could not represent is quietly absent.
Extract only the text, edit the original in place
The one that preserves the document, because the structure is never converted to anything. It is more work to build and it is the only approach that can be correct by construction.
The second approach deserves the emphasis. A tool that hands you plain text has at least been honest about what it did. A tool that hands you a file has produced something that passes inspection at a glance and reveals its losses three days later, when someone asks why the appendix numbering restarts.
The idea that makes the third one work
Never show the model a file. Show it a list.
Walk the document and pull out its editable text fragments, numbering them in order: fragment 0 is the first paragraph, fragment 1 the second, and so on. Hand the model that numbered list and the instruction. Ask it to return only the fragments it changed, each keyed by its number.
What comes back is a small set of pairs: number, new text. The program then walks the original document again and, for each pair, replaces the content of that fragment and touches nothing else. Every byte of structure in the output was written by the program, because the model was never in a position to write any of it. The worst a bad response can do is produce wrong wording in the right place.
The details that decide whether it actually works
The idea is simple. Making it survive real documents is where the work is, and each of these was a bug before it was a rule.
- Numbering must be stable across both passes. The fragments are found once to build the list and again to write the result. If the two walks disagree about anything, even an empty paragraph, every edit after that point lands on the wrong text. An empty paragraph has to consume a number in both passes precisely because it is worth nothing.
- The file must not have moved. Numbers are positions, so if the document was edited between the read and the write, the edits are correct for a document that no longer exists. Checking that size and modification time are unchanged before writing turns a silent corruption into a refusal.
- A number the model invented has to be ignored. Models occasionally return a fragment 47 in a document with 30. Treating that as fatal throws away 29 good edits; applying it is nonsense. Dropping it is the only reasonable answer.
- An unchanged fragment is not a change. Models often echo text back identically. Filtering those out is what makes the count you show the user, the preview they read, and the bytes actually written all the same list.
- Untouched parts must be copied byte for byte. Styles, themes, images and fonts should not be re-encoded on the way out. Copying them through unchanged is what makes the output open identically rather than approximately.
- Whitespace has to be declared. XML collapses leading and trailing spaces unless the fragment is explicitly marked to preserve them. Miss it and edited sentences quietly lose the space before the next word.
Where the approach reaches its limit
Two honest ones, and they follow from the design rather than from unfinished work.
It edits text, not structure. Rewording a sentence, translating a section, changing a name throughout: all fine. Adding a paragraph, splitting a table, reordering sections: not this mechanism, because those change the numbering the whole method rests on. That is a real ceiling and it is where the safety comes from.
And PDFs are a different problem entirely. A PDF has no paragraphs, only characters placed at coordinates, so editing one means covering the old line and painting a new one. That can be done well, and it can hit cases it cannot do faithfully: replacement text too long for the space it must occupy, a line sitting on a gradient rather than a flat color, characters outside the encoding of the font being drawn with. The right behavior is to flag each of those and show you where, rather than to produce a page that looks finished and is subtly wrong.
How to evaluate a tool in five minutes
Take a real document, not a clean one. Something with a table, a numbered list, an image, a header, and at least one sentence with bold in the middle of it. Ask for a trivial edit, such as changing one word in one paragraph.
- Did you get a file back, or text? Text is honest but it is not editing.
- Open it. Is the table still a table, is the image still there, does the numbering still start where it did?
- Find the sentence with the bold fragment. Is the bold still in the middle of it, or is the whole sentence now one weight?
- Check the paragraphs you did not ask to change. If any of them are reworded, the tool regenerated your document rather than edited it, and it will do that every time.
- Look for the original file. If it was overwritten, that is the finding, and it is enough on its own.
A tool that passes all five is doing something like the third approach. One that fails the last two is doing the second one, and no amount of prompt tuning will fix that, because the loss happened before the model was involved. How Khint implements this is described on the documents page, and the agent that runs it is one of the four input sources covered in running your own prompts on selected text.