# Phase 05: MVP Deployment — Context **Gathered:** 2026-04-27 **Status:** Ready for planning ## Phase Boundary Подготовить Matrix-бот к реальному деплою на lambda.coredump.ru: 1. Расширить config/matrix-agents.yaml — добавить user_agents (Matrix user_id → agent_id) и per-agent base_url/workspace_path 2. Обновить AgentRegistry и _build_platform_from_env для per-agent URL routing 3. Реализовать file transfer через shared volume /agents/: входящие файлы → incoming/{filename} в workspace агента, исходящие — читать из workspace и отправлять в Matrix 4. Написать docker-compose.prod.yml только для Matrix-бота (агентские контейнеры — зона платформы) 5. Удалить команду !agent (legacy от динамического роутинга) НЕ входит: - Конфигурация агентских контейнеров (платформа) - Telegram-адаптер - E2EE - platform-master интеграция ## Implementation Decisions ### !agent команда - **D-01:** Удалить полностью. Маппинг user→agent теперь статический из config. Пользователь не может менять агента. ### Конфиг агентов (config/matrix-agents.yaml) - **D-02:** Расширить текущий matrix-agents.yaml — добавить user_agents dict и поля base_url/workspace_path к каждому агенту. Один файл, один парсер. Формат по docs/deploy-architecture.md: ```yaml user_agents: "@user0:matrix.lambda.coredump.ru": agent-0 "@user1:matrix.lambda.coredump.ru": agent-1 agents: - id: agent-0 label: "Agent 0" base_url: "ws://lambda.coredump.ru:7000/agent_0/" workspace_path: "/agents/0/" ``` - **D-03:** AgentDefinition расширяется полями base_url (str) и workspace_path (str). AgentRegistry добавляет user_agents dict (Matrix user_id → agent_id) и метод get_agent_id_by_user(matrix_user_id). ### Роутинг user → agent в _build_platform_from_env - **D-04:** Вместо глобального AGENT_BASE_URL — per-agent URL из конфига. _build_platform_from_env строит delegates с правильным base_url для каждого агента. RoutedPlatformClient._resolve_delegate использует user_agents из registry для определения delegate по Matrix user_id. ### Входящие файлы (пользователь → агент) - **D-05:** Путь внутри workspace агента: `incoming/{filename}`. Абсолютный путь: `{workspace_path}/incoming/{filename}` (например `/agents/0/incoming/photo.jpg`). Обновить files.py: `build_workspace_attachment_path` принимает workspace_path агента и строит путь `incoming/{filename}`. Передавать в agent.send_message() как attachments=["incoming/{filename}"] (относительно /workspace). - **D-06:** workspace_path агента берётся из AgentDefinition по agent_id пользователя. ### Исходящие файлы (агент → пользователь) - **D-07:** При получении MsgEventSendFile(path="output/report.pdf") — читать файл из `{workspace_path}/{path}`. Отправлять как Matrix file message. Обработчик в Matrix bot.py при обработке stream-ответов от агента. ### docker-compose для prod - **D-08:** Отдельный docker-compose.prod.yml только для Matrix-бота. Монтирует /agents/ как host path volume (платформа обеспечивает сам volume на хосте). Env vars из .env.prod. Запуск: `docker compose -f docker-compose.prod.yml up`. ### Claude's Discretion - Обработка случая когда Matrix user_id не найден в user_agents: вернуть ошибку пользователю или fallback на mock? - Имя переменной окружения для пути к prod-конфигу (MATRIX_AGENT_REGISTRY_PATH уже существует — скорее всего оставить) - Формат .env.prod ## Canonical References **Downstream agents MUST read these before planning or implementing.** ### Deployment architecture (PRIMARY) - `docs/deploy-architecture.md` — Топология, формат конфига, AgentApi lifecycle, file transfer protocol, открытые вопросы ### Существующий код (изменяем) - `adapter/matrix/agent_registry.py` — AgentRegistry, AgentDefinition, load_agent_registry — расширяем - `adapter/matrix/bot.py` — _build_platform_from_env, _load_agent_registry_from_env — обновляем роутинг - `adapter/matrix/routed_platform.py` — RoutedPlatformClient._resolve_delegate — обновляем логику - `adapter/matrix/files.py` — build_workspace_attachment_path, download_matrix_attachment — меняем путь - `adapter/matrix/handlers/agent.py` — удаляем или делаем no-op (!agent handler) - `config/matrix-agents.yaml` — расширяем формат - `docker-compose.yml` — существующий dev compose (за основу для prod варианта) ### SDK (используем как есть) - `sdk/real.py` — RealPlatformClient — base_url теперь per-instance, но сам класс не меняется - `sdk/upstream_agent_api.py` — AgentApi, MsgEventSendFile — читаем MsgEventSendFile в стриме ## Existing Code Insights ### Reusable Assets - `adapter/matrix/files.py::build_workspace_attachment_path` — уже строит путь к файлу, нужно заменить логику `surfaces/matrix/...` на `incoming/{filename}` - `adapter/matrix/files.py::download_matrix_attachment` — скачивает файл, нужно передавать workspace_path агента - `adapter/matrix/agent_registry.py::load_agent_registry` — парсер YAML, расширяем без переписывания ### Established Patterns - `RoutedPlatformClient` + delegates: dict[agent_id, RealPlatformClient] — паттерн уже есть, нужно только per-agent URL при создании delegates - `MATRIX_PLATFORM_BACKEND=real` активирует prod-path — сохраняем - `MATRIX_AGENT_REGISTRY_PATH` — env var для пути к конфигу — сохраняем ### Integration Points - `_build_platform_from_env` создаёт delegates — здесь меняется источник URL (из конфига, не из env) - `RoutedPlatformClient._resolve_delegate` — здесь добавляется lookup по user_agents - Matrix bot stream handler — здесь добавляется обработка MsgEventSendFile ## Specific Ideas - AgentApi конструктор в master ветке: `AgentApi(agent_id, base_url, on_disconnect=..., chat_id=0)` — base_url это ws:// URL агента - Входящий файл: bot скачивает из Matrix → пишет в `{workspace_path}/incoming/{filename}` → вызывает `agent.send_message(text, attachments=["incoming/{filename}"])` (путь relative to /workspace) - Исходящий файл: при `MsgEventSendFile(path="output/report.pdf")` → читаем `{workspace_path}/output/report.pdf` → отправляем в Matrix через `client.upload()` → `client.room_send(m.file)` - docker-compose.prod.yml монтирует volume: `volumes: ["/agents/:/agents/"]` — хост обеспечивает директорию ## Deferred Ideas - platform-master интеграция (динамический get_agent_url через POST /api/v1/create) — когда feat/storage будет готов - !agent как admin-override — не нужен для MVP, можно добавить позже если потребуется - Per-chat context isolation через разные chat_id (сейчас chat_id=0 для всех) — ждём platform сигнал --- *Phase: 05-mvp-deployment* *Context gathered: 2026-04-27*