# 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*