Эксперимент с ИИ
Я пригласил своего ИИ-агента в 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, который ждёт следующую команду из редактора. Если ничего не пришло, агент сохраняет курсор и снова начинает ожидание. Если команда есть, она содержит:
- текст инструкции;
- идентификатор команды;
- монотонный sequence;
- текущий путь в Builder;
- IDs открытого проекта, главы и сцены, когда они есть в URL;
- тип поверхности редактора и время захвата контекста;
- выделенный пользователем текст, если он есть.
Весь приложенный контекст помечается как недоверенный контент приложения. Это данные для работы, а не продолжение управляющей инструкции агента.
Агент выполняет задачу существующими MCP-инструментами Romergo. Например, он может прочитать проект и главу, найти ресурсы, изменить сцену, а затем проверить сохранённый результат.
Пока он работает, агент может вызвать romergo_report_builder_event и отправить в панель:
status— короткий промежуточный статус;question— вопрос, без ответа на который нельзя безопасно продолжить;reply— готовый результат;error— понятное описание ошибки.
Ответ привязывается к commandId, а следующая команда читается с последнего обработанного sequence. При первой выдаче API атомарно закрепляет команду за client_id OAuth-клиента. Другой подключённый агент не сможет одновременно забрать ту же задачу. Cursor помогает продолжить после timeout или переподключения, а одноразовые подтверждения конкретных tool calls защищены отпечатком аргументов и не могут быть повторно использованы для другого действия.
Права принадлежат комнате, а не prompt
Перед подключением пользователь видит настройки канала и выбирает, что агенту разрешено: читать проект, редактировать содержимое, работать с медиа и аудио, публиковать или удалять данные. Эти настройки можно в любой момент открыть через шестерёнку в шапке панели.
По умолчанию чтение, редактирование и работа с медиа доступны, а прямая просьба пользователя уже считается разрешением применить эти действия. Публикация и удаление отключены и включаются отдельно. При желании можно включить более строгий режим и повторно подтверждать каждое изменение либо только публикацию и удаление.
Это не просто текст в стартовом prompt. Общая серверная обёртка проверяет scope перед вызовом изменяющего MCP-инструмента. Если включено дополнительное подтверждение, Builder показывает точное действие с кнопками «разрешить один раз» и «отклонить», а исходный вызов продолжает ждать решение. Разрешение связано с командой, инструментом и отпечатком аргументов, после выполнения оно больше не действует.
Начало, завершение, ошибка и блокировка каждого изменяющего инструмента автоматически возвращаются в панель. Каждый финальный ответ обязан содержать структурированный итог со статусом и конкретным описанием результата. После изменений агент также перечисляет изменённые сущности, выполненные проверки и ссылки на результат; Builder показывает этот итог прямо под текстом ответа. Канал можно явно завершить из настроек; старый код перестаёт работать сразу.
Что находится в Romergo, а что остаётся у пользователя
Мне нравится рассматривать эту архитектуру как разделение ответственности.
Romergo предоставляет:
- редактор и визуальное рабочее пространство;
- текущий проект, страницу и выделение;
- временную комнату для двустороннего общения;
- доменные инструменты чтения, изменения и проверки проекта;
- OAuth, права доступа и историю событий сессии;
- интерфейс, в котором пользователь видит вопросы, ход работы и результат.
Пользовательский агент приносит:
- модель и вычисления;
- собственную подписку;
- reasoning и планирование;
- память и персонализацию, если их предоставляет выбранный агент;
- остальные подключённые инструменты;
- привычный пользователю стиль работы.
Интеллект не принадлежит приложению. Приложение создаёт место, в котором этот интеллект может безопасно работать.
Почему не сделать обычного встроенного copilot
Встроенный AI был бы проще объяснить и проще включить. Пользователь нажимает кнопку, приложение вызывает выбранную модель, всё работает.
Но тогда Romergo пришлось бы стать ещё и оператором AI-инфраструктуры:
- оплачивать inference или перекладывать его стоимость в тариф;
- выбирать модели за пользователя;
- создавать собственную память и персонализацию;
- повторно подключать внешние сервисы;
- хранить дополнительный чувствительный контекст;
- постоянно догонять возможности горизонтальных 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-экраном:
- какие страницы и сущности доступны конкретной комнате;
- какие действия разрешены без подтверждения;
- может ли текст проекта содержать prompt injection;
- как агент должен отличать пользовательскую команду от недоверенных данных;
- что происходит с командой после timeout;
- как показать пользователю фактические изменения, а не только уверенный текстовый ответ;
- как отозвать сессию и доказать, что агент действительно перестал слушать;
- какую часть памяти и внешних связей личного агента допустимо использовать в конкретном приложении.
Текущая версия ограничивает канал по пользователю и времени, использует OAuth, серверные scopes, одноразовые подтверждения, claim команды и явный lifecycle. Это всё ещё эксперимент, но важные границы теперь являются частью исполнения, а не только рекомендациями для агента.
Как это называть
Пока у меня нет окончательного названия.
Bring Your Own AI обычно означает собственный API key или выбор модели. Bring Your Own Agent ближе, потому что пользователь приносит не только модель, но и память, инструменты и agent loop. Однако BYOA не описывает важную часть эксперимента: приложение тоже может обращаться к агенту и поддерживает с ним живую сессию.
Возможно, это:
- a live agent channel;
- an application-agent session;
- an agent presence layer;
- a personal agent bridge;
- bidirectional MCP;
- или просто удачный эксперимент поверх уже существующих идей.
Я не хочу придумывать новый стандарт только ради названия. Сначала мне важнее понять, полезна ли такая модель за пределами Romergo и какие границы нужны, чтобы ей можно было доверять.
Возможно, приложениям не нужен собственный AI
Сегодня почти каждый продукт пытается встроить своего ассистента. В результате у пользователя появляется много отдельных AI: один в редакторе, другой в почте, третий в системе задач. У каждого своя короткая память, свои ограничения и отдельная цена.
Есть и другая возможная модель.
Приложение предоставляет рабочее пространство, живой контекст и специализированные инструменты. Пользователь приносит агента, которому уже доверяет. На время работы агент присоединяется к приложению, помогает выполнить задачу и уходит вместе с пользователем.
Я пока не знаю, станет ли это самостоятельной архитектурной категорией. Но теперь я знаю, что такой цикл можно собрать и что им действительно можно пользоваться.
Но точно знаю, что экспериментировать — это очень весело.