Безопасное частичное редактирование контента LLM-агентами
Безопасное частичное редактирование контента LLM-агентами
Это частная проблема из более широкой области архитектурных проблем современных LLM-агентов.
Проблема
При обычном CRUD-подходе большое текстовое поле вроде content обновляется целиком. Для классического детерминированного клиента это часто приемлемо. Для LLM-агента такая модель опаснее: если задача состоит в изменении одной строки, ссылки, абзаца или секции, агент всё равно вынужден получить документ, воспроизвести его целиком и отправить новую полную версию.
Из-за этого небольшая правка получает слишком большую область воздействия. Возникают лишние токены и операции, а вместе с ними — риск случайно изменить соседний текст, потерять часть документа, затереть более свежую версию или внести незапланированные изменения.
Эта проблема проявилась практически при работе с Concepts fi1osof.ru: ради исправления одной внутренней ссылки агенту пришлось повторно отправлять весь content. Для системы, где AI-агенты должны регулярно создавать и поддерживать большие статьи, Concepts, задачи и другой контент, такой способ редактирования плохо масштабируется.
Что уже существует в инженерной практике
Идея частичного изменения ресурса появилась задолго до LLM. RFC 5789 — PATCH Method for HTTP вводит PATCH именно потому, что PUT означает полную замену представления ресурса, тогда как многим приложениям нужно менять только его часть.
Для структурированных JSON-данных RFC 6902 — JSON Patch описывает последовательность операций add, remove, replace, move, copy, test. Это важный прецедент: клиент передаёт не новое состояние целиком, а набор изменений к существующему состоянию.
Современные coding agents используют сходный подход уже специально для LLM. Инструмент OpenAI Apply Patch позволяет модели изменять файлы через структурированные diff-операции вместо возврата полного содержимого файла. GitHub Copilot coding agent также строит рабочий процесс вокруг изменений в отдельной ветке и проверки итогового diff: официальная документация GitHub.
На уровне tool-протоколов Model Context Protocol рассматривает инструменты как операции воздействия на внешние системы: MCP Tools specification. В развитии MCP отдельно формализуется словарь риска инструментов — readOnly, destructive, idempotent и другие характеристики: Tool Annotations as Risk Vocabulary. Это не решает задачу частичного редактирования напрямую, но подтверждает общий переход от «у модели есть функция» к более строгому описанию последствий операции.
При этом готового общепринятого стандарта для безопасного редактирования произвольных CMS/MDX-документов LLM-агентами пока нет. Coding-agent patch-механизмы решают близкую задачу для файлов, а HTTP/JSON Patch — для классических API, но agent-native content editing остаётся отдельной инженерной проблемой.
Требования к будущему решению
Для haih-agent нужен механизм, при котором агент может изменить минимально необходимую часть документа и не обязан заново генерировать весь content.
Желательные свойства:
- изменение должно быть локальным и ограниченным;
- сервер должен проверять, что агент редактирует ту версию документа, которую видел;
- неоднозначная операция не должна применяться молча;
- несколько изменений желательно применять атомарно;
- после изменения документ должен проходить повторную MDX/Markdown-валидацию;
- полная замена
contentдолжна оставаться доступной для случаев, когда действительно требуется полное переписывание материала; - механизм должен быть пригоден не только для Concepts, но и для Tasks, Projects и других сущностей с большими текстовыми полями.
Вариант 1. Частичное редактирование через text matching
Самый компактный по контексту вариант — агент читает обычный Markdown/MDX и отправляет команды, содержащие ожидаемый исходный фрагмент и его замену.
Концептуально:
replace:
match: "точный существующий фрагмент"
with: "новый Markdown/MDX"
expectedMatches: 1
Механизм может поддерживать несколько универсальных операций: замена, удаление, вставка до или после найденного фрагмента. Это не отдельные методы для ссылок, слов или предложений, а общий язык локальных текстовых изменений.
Плюсы
- минимальный рост контекста: агент продолжает читать компактный исходный MDX;
- легко объяснить модели и человеку;
- хорошо подходит для небольших и средних локальных изменений;
- сервер может безопасно отказаться от операции, если
matchне найден или найден неоднозначно; - сравнительно небольшая сложность первой реализации.
Минусы
- exact matching чувствителен к уже произошедшим изменениям текста;
- агенту иногда приходится передавать довольно большой уникальный фрагмент-контекст;
- структурные операции вроде «добавить пункт именно в этот список» выражаются менее естественно;
- текстовый matching знает меньше о семантике MDX-документа.
Вариант 2. Чтение и адресация через MDX AST
MDX уже имеет структурное представление через unified/remark ecosystem. remark-mdx позволяет разбирать MDX в syntax tree. Базовый формат unist содержит для узлов position.start и position.end; точки могут включать offset, то есть узел можно связать с точным диапазоном исходного файла: unist specification.
В такой модели агент читает Concept не только как текст, а как дерево: heading, paragraph, link, listItem, MDX JSX element и т.д. Затем он может адресовать конкретный узел или диапазон и отправлять новый Markdown/MDX только для изменяемой части.
Важно, что после этого необязательно сериализовать весь AST обратно. Позиции можно использовать для изменения соответствующего диапазона исходного source, сохраняя остальную часть документа byte-for-byte.
Плюсы
- агент видит реальную структуру документа, а не только последовательность символов;
- проще безопасно различать заголовки, ссылки, списки, MDX-компоненты и другие узлы;
- структурные изменения могут быть точнее и естественнее;
- потенциально даёт сильную основу для дальнейших agent-native операций над контентом.
Минусы
- AST значительно объёмнее исходного Markdown/MDX и может вызвать взрывной рост передаваемого контекста и стоимости;
- нужно решить, насколько стабильно адресовать узлы между чтением и записью;
- offsets становятся недействительными после конкурентного изменения документа;
- интерфейс команд для агента становится сложнее;
- полноценный AST для больших статей может быть неоправданно дорог, если требуется изменить одну строку.
Возможная комбинация
Два подхода не обязательно взаимоисключающие.
Базовый режим может использовать компактный исходный MDX + text matching для большинства правок. AST можно подключать по требованию: для сложного структурного изменения агент запрашивает дерево только нужной секции или документа, а затем выполняет адресную операцию.
Такой гибрид потенциально сохраняет главное преимущество Markdown — компактность контекста — и при этом оставляет структурный режим для случаев, где plain-text patch слишком хрупок.
Защита от устаревшей версии
Независимо от выбранного способа адресации нужен контроль версии. RFC 5789 отдельно обращает внимание на риск коллизий PATCH и использование conditional requests/ETag для предотвращения применения изменения к неожиданному состоянию ресурса.
Для haih-agent аналогом может быть revision/hash/updatedAt: агент получает версию вместе с документом, а patch применяется только если она не изменилась. Иначе операция отклоняется, и агент перечитывает актуальный контекст.
Текущий статус
Это проработка архитектурной проблематики, а не описание реализованной функции.
Реализация partial/agent-safe editing в haih-agent пока не начата. Сейчас фиксируются требования, существующие отраслевые практики и два основных варианта собственного решения: компактное редактирование через text matching и структурное редактирование через MDX AST.
Вернуться к реализации планируется обязательно: при текущем направлении развития fi1osof.ru и других сайтов AI-агенты будут много работать с большим объёмом контента. Полная перезапись огромной статьи ради изменения отдельных строк, абзацев или блоков создаёт неоправданные расходы и риск потери данных. Поэтому безопасное частичное редактирование становится не удобством, а необходимым инфраструктурным слоем agent-managed CMS.