Когда ассистент должен изменить документ, запустить расчёт или выполнить действие в приложении, у меня появляются конкретные инженерные вопросы. Как назвать операцию? Кто проверит права? Что показать пользователю при частичном сбое? Как продолжить задачу, если ответ потерялся?

Эти вопросы связывают три моих проекта: открытый runtime EBCA, RPG-конструктор Tabletop Forge и работу над AI-runtime в VIVIAI. Ниже — решения из их устройства, с обозначенными границами применения.

Сначала определяю действия и состояние

Для каждого инструмента нужны понятные входы, результат и место в пользовательском процессе. Например, «подготовить HTML-кадр» и «сохранить изображение» — разные операции. У них разные параметры, ошибки и владельцы состояния.

В EBCA я описываю состояние компонентами, а поведение — системами, реагирующими на события. Команда выражает намерение. Обработчик проверяет её и изменяет состояние через общую границу — ComponentManager.

В публичном примере счётчика можно проследить полный путь: принять величину приращения, отклонить некорректное значение, получить текущий компонент, записать новое значение и завершить команду. Пример маленький специально: границы операции видны без чтения всего приложения.

Модели показываю доступные инструменты

В VIVIAI доступные команды связаны с текущим шагом диалога. Runtime собирает контекст, передаёт модели инструменты и проверяет параметры вызова до отправки команды в домен.

Так проще отделить два вида ошибок. Если модель не заполнила обязательное поле, это проблема входа инструмента. Если внешний генератор недоступен, это ошибка выполнения операции. Пользовательский интерфейс и восстановление должны учитывать эту разницу.

Состояние команды сохраняется. Благодаря этому приложение может распознать незавершённый шаг после прерывания. Сам факт сохранения ещё требует согласованного механизма восстановления: важно определить, какой результат уже получен и какое действие допустимо повторить.

Права остаются у приложения

В Tabletop Forge агент подключается через MCP от имени авторизованного аккаунта. Инструменты проверяют роль ведущего и разрешённые операции. Подключение не создаёт дополнительных полномочий.

Для игрового действия есть последовательность:

  1. Прочитать актуальное состояние и доступные взаимодействия.
  2. Собрать параметры выбранного действия.
  3. При необходимости проверить условия без выполнения.
  4. Выполнить действие через серверный игровой runtime.
  5. Получить сохранённый результат и изменения состояния.

Проверка доступности не резервирует будущий результат: между чтением и исполнением состояние может измениться. Поэтому сервер снова проверяет действие при выполнении. Броски, игровые правила и журнал остаются частью общего runtime.

Повтор отличаю от новой команды

После сетевого сбоя неизвестно, не дошёл запрос или потерялся только ответ. В игровом API Tabletop Forge клиент использует actionId. При неизвестном результате он читает запись действия или повторяет тот же запрос с тем же идентификатором. Новое намерение получает новый идентификатор.

Этот контракт относится к конкретному игровому API. Для платежа, отправки письма или операции во внешней CRM нужно отдельно выяснить, какие гарантии повторения предоставляет другая сторона.

Результат генерации тоже проходит проверку

В HTML-генерации VIVIAI модель создаёт редактируемую структуру кадра. Приложение проверяет разрешённые переменные, структуру HTML и ограничения CSS. При ошибке генератор получает обратную связь в ограниченном цикле исправления.

Успешный ответ модели и пригодный артефакт — разные этапы приёмки. Проверки формата полезны, но визуальное качество и полезность результата оцениваются отдельно на пользовательских примерах.

Что проверяю перед расширением сценария

  • Какие действия агент может вызывать и какие данные ему нужны.
  • Где проверяются пользовательские полномочия и параметры.
  • Как хранится состояние долгой задачи.
  • Что происходит при повторе, таймауте и частично выполненной операции.
  • Чем подтверждается качество результата и когда требуется человек.

Исходники EBCA, включая отчёты runtime, доступны публично. Из этих проектов я беру конкретные приёмы, а способ их применения выбираю по ограничениям новой задачи. Перенос framework целиком нужен далеко не каждому продукту.