# Phase 4: Matrix MVP — Agent Context + Context Management — Context **Gathered:** 2026-04-16 **Status:** Ready for planning **Source:** Conversation context (2026-04-16 design session) ## Phase Boundary Привести Matrix-бот к рабочему состоянию для MVP-деплоя в контейнер: - Убрать наш кастомный `AgentSessionClient` и thread_id патч из `platform-agent`, перейти на актуальный origin/main платформы с `AgentApi` из `lambda_agent_api` - Добавить 4 команды управления контекстом агента: `!save`, `!load`, `!reset`, `!context` - Упаковать Matrix-бот в Docker-контейнер НЕ входит в фазу: - Изменения в platform-agent (это задача команды платформы) - Telegram адаптер - E2EE - Skills system (ждём платформу) ## Implementation Decisions ### Архитектура платформы (locked) - **Один контейнер = один чат**: `AgentService` с `thread_id = "default"` — намеренная архитектура. Изоляция на уровне контейнеров, не thread_id. Не менять. - **Убрать thread_id патч**: наш коммит `1dca2c1` в `external/platform-agent` удаляем. Переходим на `origin/main` platform-agent. - **Удалить `build_thread_key`**: функция больше не нужна. Убрать из `sdk/agent_session.py` и `sdk/real.py`. - **Заменить `AgentSessionClient` на `AgentApi`**: использовать `AgentApi` из `external/platform-agent_api/lambda_agent_api/agent_api.py`. Он уже правильно обрабатывает все event-типы (неизвестные → `logger.warning`, без краша). ### !save (locked) - Синтаксис: `!save` (автоимя по дате/времени) или `!save [имя]` - Механизм: Matrix-бот посылает агенту текстовое сообщение "Summarize our conversation and save to /workspace/contexts/[name].md. Reply only with: Saved: [name]" - Имена сохранений хранятся в `PrototypeStateStore` (список для `!load`) - Агент сам пишет файл через свои инструменты (`write_file`) ### !load (locked) - `!load` без аргументов → бот показывает нумерованный список сохранений - Пользователь вводит **число** (1, 2, 3...) для выбора - Выход из состояния: `0` или `!cancel` - После выбора: бот посылает агенту "Load context from /workspace/contexts/[name].md and use it as background for our conversation. Reply: Loaded: [name]" - Состояние ожидания выбора хранится в Matrix store (аналогично pending_confirm) ### !reset (locked) - Показывает confirmation-диалог: ``` Сбросить контекст агента? Выбери: !yes — сбросить !save [имя] — сохранить и сбросить !no — отмена ``` - `!yes` → вызвать `POST {AGENT_BASE_URL}/reset` (resets AgentService singleton) - `!save имя` → сначала выполняется логика !save, затем POST /reset - `!no` → отмена - Fallback если `/reset` endpoint недоступен (404): вернуть пользователю "Reset endpoint недоступен. Обратитесь к администратору." - `AGENT_BASE_URL` — новая env переменная (HTTP base URL агента, отдельно от `AGENT_WS_URL`) ### !context (locked) - Показывает: имя текущей сессии (если загружали через `!load`), токены из последнего ответа (`tokens_used` из `MsgEventEnd`), список сохранений (имена + даты) - Не делает никаких вызовов к агенту ### Dockerfile + docker-compose (locked) - `Dockerfile` для Matrix-бота (`adapter/matrix/bot.py`) - `docker-compose.yml` с сервисом `matrix-bot` - Env переменные через `.env` файл - Platform-agent запускается отдельно (не входит в compose этой фазы) ### Claude's Discretion - Структура хранения saved sessions в PrototypeStateStore (dict name→timestamp) - Формат автоимени для !save без аргументов - HTTP клиент для POST /reset (aiohttp или httpx) - Точный формат промптов к агенту для save/load ## Canonical References **Downstream agents MUST read these before planning or implementing.** ### Platform клиент (заменяем) - `sdk/agent_session.py` — текущий AgentSessionClient, УДАЛЯЕМ/ЗАМЕНЯЕМ - `sdk/real.py` — RealPlatformClient, обновляем под AgentApi - `external/platform-agent_api/lambda_agent_api/agent_api.py` — новый клиент AgentApi - `external/platform-agent_api/lambda_agent_api/server.py` — типы сообщений (MsgStatus, MsgEventTextChunk, MsgEventEnd, etc.) - `external/platform-agent_api/lambda_agent_api/client.py` — MsgUserMessage ### Matrix адаптер (расширяем) - `adapter/matrix/bot.py` — точка входа, MatrixBot, build_runtime - `adapter/matrix/handlers/` — существующие обработчики команд - `adapter/matrix/store.py` — get_room_meta, set_pending_confirm (паттерн для !load state) - `sdk/prototype_state.py` — PrototypeStateStore, расширяем для saved sessions ### Состояние платформы - `.planning/threads/matrix-dev-prototype-agent-platform-state.md` — исследование от 2026-04-14 ### Существующая архитектура команд - `core/protocol.py` — IncomingCommand, OutgoingMessage, OutgoingUI - `core/handlers/` — паттерны регистрации обработчиков ## Specific Ideas - `AgentApi` требует явного `connect()` при старте и `close()` при завершении — lifecycle нужно встроить в `MatrixBot` - `AgentApi.send_message()` — AsyncIterator, возвращает `MsgEventTextChunk` чанки и `MsgEventEnd` - Для `!load` состояние "ожидаем число" хранить по ключу `load_pending:{matrix_user_id}:{room_id}` в store (аналог pending_confirm) - `AGENT_BASE_URL` — HTTP URL, например `http://127.0.0.1:8000`; `AGENT_WS_URL` = `ws://127.0.0.1:8000/agent_ws/` - platform-agent origin/main: `POST /reset` эндпоинта нет — это нужно запросить у команды платформы. До тех пор `!reset` возвращает "Reset endpoint недоступен" ## Deferred Ideas - Замена `PrototypeStateStore` на реальный control-plane из platform-master (Phase 3) - Skills интеграция через SkillsMiddleware (ждём платформу) - E2EE для Matrix - `!reset` через docker restart (заменяется на /reset endpoint когда платформа добавит) - Суммаризация контекста (агент сам решает как писать в файл) --- *Phase: 04-matrix-mvp-shared-agent-context-and-context-management-comma* *Context gathered: 2026-04-16 via conversation design session*