Безопасное частичное редактирование контента 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.