Идея: автономные агенты — серверные раны, отвязанные от окна браузера (event-sourced) #184
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Мотивация
Хочу автономных агентов, которые продолжают работать без открытого окна браузера после запуска: поставил задачу — агент крутится на сервере, наработки персистятся, к ним можно вернуться, экспортировать, и любой следующий запуск видит сделанное. Сегодня это невозможно в принципе: цикл агента живёт ровно столько, сколько открыт HTTP-запрос (
res.hijack()вai-chat.controller.ts), фонового исполнения нет.Ключевой сдвиг
Ран агента — серверный персистентный объект, а не функция внутри HTTP-запроса. БД — единственный источник истины. Все остальные (UI-лайв, экспорт, респаун, второй таб, автономный воркер) — её читатели/подписчики.
Составляющие
1.
ai_chat_runs— ран как первоклассный объектstatus(pending / running / succeeded / failed / aborted),chat_id,trigger(user / autostart / schedule / api / continue),created_by, токен/шаг-бюджет,error, тайминги.runId).2. Запись по событию, проекция — сообщение
status='streaming') и инкрементально материализуется: текст — коалесцированно, tool result — немедленно (граница сайд-эффекта). Это уже делает #183.ai_chat_eventsкак полный аудит, аai_chat_messages— его проекция.3. Воркер на BullMQ
embedding.processor.ts). Переиспользуем как исполнитель агентского цикла, отвязанного от сокета. HTTP только ставит ран и подписывается.flushAssistant(capturedSteps, status)из #183 переиспользуется воркером как есть.4. Триггеры рана без открытого окна
auto_start/launch_message(ai-agent-roles) — чисто клиентское поведение (клиент авто-отправляет сообщение). Перенести в серверный триггер рана.5. Клиент — просто подписчик
runId(AI SDK v6 умеет нативно, Redis уже есть). На reload / втором табе — реплей из персистентного стрима, никакого in-memory-only состояния.Что нужно решить отдельно (риски автономии)
findRecent(50).users.is_agent+agent-provenance(pages.last_updated_ai_chat_id,comments.ai_chat_id); переиспользовать для атрибуции автономных правок.Чем #183 готовит почву (не противоречит этой идее)
flushAssistantкак чистая функция от накопленных шагов → готова к вызову из воркера.status— это и есть проекция, которую позже поддержит слойai_chat_runs/ событий.consumeStream) — не усиливаем привязку к HTTP.Ориентир по этапам (когда дойдут руки)
ai_chat_runs, resumable stream поrunId, проекция событий, single active run per chat.Ghost referenced this issue2026-06-28 04:26:20 +03:00
Ghost referenced this issue2026-06-28 22:18:12 +03:00
Ghost referenced this issue2026-06-29 00:31:40 +03:00