Эксперимент с ИИ

Я пригласил своего ИИ-агента в Romergo, и я не знаю, что это и как правильно назвать.

Большинство AI-интеграций в приложениях устроены предсказуемо. Продукт добавляет кнопку с искрой, отправляет запрос собственной модели и показывает ответ в боковой панели.

Есть и другой распространённый вариант. Приложение предоставляет MCP-сервер, а пользователь открывает ChatGPT, Claude или другого агента и просит его поработать с данными приложения. Это даёт агенту хорошие инструменты, но разговор происходит где-то ещё. Нужно покинуть редактор, объяснить, что сейчас открыто, переключиться обратно и проверить результат.

Переключаться между чатом и редактором мне надоело, и пришла идея, как это обойти.

Я добавил AI-панель непосредственно в редактор, но не стал подключать к ней модель, которую хостит Romergo. Вместо этого пользователь приглашает в открытую сессию своего личного AI-агента.

Агент остаётся там, где он уже живёт: в ChatGPT, Claude, Codex или другом MCP-совместимом клиенте. Он сохраняет свою модель, подписку, память, настройки и доступные ему инструменты. Romergo предоставляет только рабочее пространство, текущий контекст и специализированные инструменты для редактирования проекта.

После подключения пользователь может писать агенту прямо из Builder:

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

Это началось как эксперимент

У меня не было намерения изобрести новый протокол или придумать новую категорию продукта. Я хотел проверить одну простую мысль: может ли личный агент пользователя не просто управлять Romergo снаружи через MCP, а временно присоединиться к живой сессии внутри редактора?

Первая версия была экспериментом. К моему удивлению, она заработала достаточно хорошо, чтобы я начал пользоваться ею сам.

Самую короткую схему можно нарисовать так:

Personal AI agent  <->  MCP  <->  Romergo Builder

Но важен знак в обе стороны.

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

После этого агент использует обычные инструменты Romergo, чтобы прочитать или изменить проект, и через тот же канал возвращает результат в Builder.

Получается замкнутый цикл:

1. User -> Builder panel: "Replace the music in this chapter"
2. Builder -> authenticated channel: command + current page + selection
3. Personal agent -> MCP: wait for the next Builder command
4. Agent -> Romergo MCP tools: inspect and edit the project
5. Agent -> MCP channel: status, question, result, or error
6. Builder panel -> User: live response from the personal agent

Romergo не запускает модель ни на одном из этих шагов.

При этом я не менял сам MCP и не добавлял в него настоящий server push. С точки зрения протокола все вызовы по-прежнему начинает агент. Обратное направление реализовано как защищённый почтовый ящик: Builder записывает команду в канал, а агент ждёт её через обычный long-poll MCP tool. Затем агент таким же обычным tool call отправляет событие обратно.

То есть «двусторонность» появляется на уровне сессии приложения, а не за счёт новой версии MCP transport. Это важное различие: текущую реализацию правильнее считать небольшим session contract, собранным поверх стандартных MCP-вызовов.

Как агент входит в сессию

Builder создаёт временный код канала. Пользователь копирует в свой AI-чат небольшой стартовый prompt примерно такого смысла:

Подключись к моему каналу Romergo Builder. Выполняй каждую новую команду один раз, отправляй результат или вопрос обратно в Builder и продолжай ждать, пока я явно не попрошу остановиться.

Затем агент вызывает MCP-инструмент romergo_join_builder_channel и передаёт код. Это handshake: Romergo проверяет OAuth-сессию, владельца канала и срок его действия, после чего возвращает состояние разговора и курсор последней команды.

Дальше агент вызывает romergo_wait_for_builder_command. Это long-poll, который ждёт следующую команду из редактора. Если ничего не пришло, агент сохраняет курсор и снова начинает ожидание. Если команда есть, она содержит:

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

Агент выполняет задачу существующими MCP-инструментами Romergo. Например, он может прочитать проект и главу, найти ресурсы, изменить сцену, а затем проверить сохранённый результат.

Пока он работает, агент может вызвать romergo_report_builder_event и отправить в панель:

Ответ привязывается к commandId, а следующая команда читается с последнего обработанного sequence. При первой выдаче API атомарно закрепляет команду за client_id OAuth-клиента. Другой подключённый агент не сможет одновременно забрать ту же задачу. Cursor помогает продолжить после timeout или переподключения, а одноразовые подтверждения конкретных tool calls защищены отпечатком аргументов и не могут быть повторно использованы для другого действия.

Права принадлежат комнате, а не prompt

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

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

Это не просто текст в стартовом prompt. Общая серверная обёртка проверяет scope перед вызовом изменяющего MCP-инструмента. Если включено дополнительное подтверждение, Builder показывает точное действие с кнопками «разрешить один раз» и «отклонить», а исходный вызов продолжает ждать решение. Разрешение связано с командой, инструментом и отпечатком аргументов, после выполнения оно больше не действует.

Начало, завершение, ошибка и блокировка каждого изменяющего инструмента автоматически возвращаются в панель. Каждый финальный ответ обязан содержать структурированный итог со статусом и конкретным описанием результата. После изменений агент также перечисляет изменённые сущности, выполненные проверки и ссылки на результат; Builder показывает этот итог прямо под текстом ответа. Канал можно явно завершить из настроек; старый код перестаёт работать сразу.

Что находится в Romergo, а что остаётся у пользователя

Мне нравится рассматривать эту архитектуру как разделение ответственности.

Romergo предоставляет:

Пользовательский агент приносит:

Интеллект не принадлежит приложению. Приложение создаёт место, в котором этот интеллект может безопасно работать.

Почему не сделать обычного встроенного copilot

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

Но тогда Romergo пришлось бы стать ещё и оператором AI-инфраструктуры:

При использовании личного агента всё это уже существует на стороне пользователя. Romergo не пытается построить ещё один ChatGPT. Он даёт ChatGPT, Claude или другому агенту специализированное рабочее место и понятные инструменты.

Это особенно интересно для творческого редактора. Один и тот же агент может знать, как пользователь пишет диалоги, какой тон предпочитает, какие референсы уже обсуждались и какими внешними инструментами он пользуется. Romergo не обязан копировать всю эту систему, чтобы помочь заменить один фон или перестроить сцену.

Самая странная часть: агент одновременно снаружи и внутри

Физически агент не переезжает в Romergo. Его модель и agent loop продолжают работать в исходном AI-клиенте.

Но с точки зрения пользователя агент присутствует внутри редактора:

Поэтому выражения «AI внутри приложения» и «AI снаружи через MCP» здесь оба не совсем точны. Это скорее временное присутствие внешнего агента в сессии приложения.

Я не первый, кто движется в эту сторону

После того как эксперимент заработал, я начал искать похожие подходы.

Agent Client Protocol позволяет редакторам вроде Zed и JetBrains подключать внешние coding agents. Tidewave помещает Claude Code, Codex и других ACP-агентов рядом с работающим веб-приложением и передаёт им browser и runtime context. Obsidian Agent Client показывает Claude Code, Codex и Gemini прямо возле заметок и автоматически прикладывает активный документ и выделение. marimo даёт внешнему агенту живой notebook как общее рабочее пространство.

Есть и более общие эксперименты. AG-UI стандартизует двустороннюю связь между пользовательским интерфейсом и agent backend. WebMCP предлагает веб-страницам регистрировать инструменты, доступные подключённому browser или desktop agent. Agent Application Protocol описывает модель, в которой приложение владеет UI и доменными инструментами, а внешний агент — reasoning, историей и общими инструментами.

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

Эксперимент Romergo интересен мне немного другим вопросом: что произойдёт, если в обычное творческое приложение сможет войти именно личный агент пользователя?

Не новая модель. Не API key к модели. Не встроенный copilot приложения. Агент, которым человек уже пользуется каждый день.

Удобство — только половина задачи

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

Возникают вопросы, на которые нельзя ответить одним OAuth-экраном:

Текущая версия ограничивает канал по пользователю и времени, использует OAuth, серверные scopes, одноразовые подтверждения, claim команды и явный lifecycle. Это всё ещё эксперимент, но важные границы теперь являются частью исполнения, а не только рекомендациями для агента.

Как это называть

Пока у меня нет окончательного названия.

Bring Your Own AI обычно означает собственный API key или выбор модели. Bring Your Own Agent ближе, потому что пользователь приносит не только модель, но и память, инструменты и agent loop. Однако BYOA не описывает важную часть эксперимента: приложение тоже может обращаться к агенту и поддерживает с ним живую сессию.

Возможно, это:

Я не хочу придумывать новый стандарт только ради названия. Сначала мне важнее понять, полезна ли такая модель за пределами Romergo и какие границы нужны, чтобы ей можно было доверять.

Возможно, приложениям не нужен собственный AI

Сегодня почти каждый продукт пытается встроить своего ассистента. В результате у пользователя появляется много отдельных AI: один в редакторе, другой в почте, третий в системе задач. У каждого своя короткая память, свои ограничения и отдельная цена.

Есть и другая возможная модель.

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

Я пока не знаю, станет ли это самостоятельной архитектурной категорией. Но теперь я знаю, что такой цикл можно собрать и что им действительно можно пользоваться.

Но точно знаю, что экспериментировать — это очень весело.

Назад в dev-блог