From 8ffbe7b6b3ef2ca270da1fb41c1704bd06d46533 Mon Sep 17 00:00:00 2001 From: Mikhail Putilovskij Date: Mon, 27 Apr 2026 21:46:27 +0300 Subject: [PATCH] =?UTF-8?q?wip:=20deployment=20architecture=20research=20?= =?UTF-8?q?=E2=80=94=20Phase=2005=20ready=20to=20plan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - docs/deploy-architecture.md: full deployment topology, agent API, file transfer via shared volume - .planning/HANDOFF.json + .continue-here.md: session state for Phase 05 planning --- .planning/.continue-here.md | 72 ++++++++++++++++++ .planning/HANDOFF.json | 112 +++++++++++++++++++++------- .planning/STATE.md | 8 +- docs/deploy-architecture.md | 145 ++++++++++++++++++++++++++++++++++++ 4 files changed, 308 insertions(+), 29 deletions(-) create mode 100644 .planning/.continue-here.md create mode 100644 docs/deploy-architecture.md diff --git a/.planning/.continue-here.md b/.planning/.continue-here.md new file mode 100644 index 0000000..f27ae84 --- /dev/null +++ b/.planning/.continue-here.md @@ -0,0 +1,72 @@ +--- +context: pre-planning +phase: 05-deployment +task: 0 +total_tasks: 0 +status: ready-to-plan +last_updated: 2026-04-27T18:44:51.832Z +--- + + +Phase 04 полностью завершена и закоммичена на ветке `feat/matrix-direct-agent-prototype` (135 тестов зелёные). Этот сеанс был посвящён архитектуре деплоя — изучили платформенные репозитории и обсудили топологию с командой платформы. Вся информация о деплое зафиксирована в `docs/deploy-architecture.md`. Phase 05 не спланирована, следующий шаг — `/gsd-plan-phase`. + + + + +- Изучены актуальные версии platform-agent, platform-agent_api, platform-master +- Уточнена топология деплоя с платформой (схема с reverse proxy и shared volume) +- Созданы `docs/deploy-architecture.md` — полное summary архитектуры деплоя + + + + +- Смержить `feat/matrix-direct-agent-prototype` → `main` +- Спланировать Phase 05 (деплой) +- Выполнить Phase 05: + - Обновить `config/matrix-agents.yaml` (добавить `base_url`, `workspace_path`, `user_agents`) + - Обновить `sdk/real.py` (AgentApi конструктор, file transfer) + - Обработка `MsgEventSendFile` в Matrix адаптере (скачать файл из volume, отправить пользователю) + - Обработка входящих файлов от Matrix пользователей (сохранить в workspace, передать в attachments) + - Написать `docker-compose.yml` для деплоя + + + + +- **Топология**: один инстанс Matrix-бота, один агент-контейнер на пользователя, reverse proxy на `lambda.coredump.ru:7000` роутит по пути `/agent_N/` +- **Файлы**: через shared volume `/agents/`. Surface пишет файл в `/agents/{N}/`, передаёт относительный путь в `attachments=["file.txt"]`. При `MsgEventSendFile(path)` — читает файл из `/agents/{N}/{path}` и шлёт в Matrix. +- **Agent API**: используем master (`attachments` и `MsgEventSendFile` есть). Ветку `#9-clientside-tool-call` игнорируем — она в разработке и убирает нужные фичи. +- **Конфиг**: два словаря — `user_id → agent_id` и `agent_id → {base_url, workspace_path}` +- **Master**: не используем для MVP. Статический конфиг. При готовности Master — мигрируем. +- **chat_id**: пока `chat_id=0` (один контекст на пользователя) + + + + +- **AGENT_ID + COMPOSIO_API_KEY**: Composio смержен в main platform-agent, теперь обязателен. Значения нужны от Азамата перед деплоем. +- **agent_api #9**: убирает `attachments` и `MsgEventSendFile` — если смержат до деплоя, сломает наш file transfer. Нужно уточнить сроки. + + +## Required Reading (in order) + +1. `docs/deploy-architecture.md` — полная архитектура деплоя, топология, API, файловый обмен, конфиг +2. `adapter/matrix/routed_platform.py` — текущий RoutedPlatformClient +3. `sdk/real.py` — текущий AgentApi wrapper +4. `config/matrix-agents.yaml` и `config/matrix-agents.example.yaml` — текущий формат конфига (нужно расширить) + +## Infrastructure State + +- Ветка: `feat/matrix-direct-agent-prototype` — готова к merge, 135 тестов зелёные +- `config/matrix-agents.yaml` — незакоммичен (live config, добавить в `.gitignore`) +- `docs/deploy-architecture.md` — незакоммичен (новый файл этого сеанса) +- platform-agent main: Composio уже смержен (требует `AGENT_ID`, `COMPOSIO_API_KEY` в env) + + +Архитектура деплоя полностью прояснена. Нет неизвестных блокеров (кроме env-переменных от платформы). Phase 05 — чисто инженерная задача: обновить конфиг, sdk, Matrix адаптер, написать compose. Всё что нужно знать — в docs/deploy-architecture.md. + + + +1. /clear +2. /gsd-resume-work — прочитает этот файл и предложит план Phase 05 +3. Прочитать docs/deploy-architecture.md +4. /gsd-plan-phase 05 + diff --git a/.planning/HANDOFF.json b/.planning/HANDOFF.json index 65c6bdb..853265c 100644 --- a/.planning/HANDOFF.json +++ b/.planning/HANDOFF.json @@ -1,38 +1,100 @@ { "version": "1.0", - "timestamp": "2026-04-24T12:16:09.301Z", - "phase": "04", - "phase_name": "matrix-mvp-shared-agent-context-and-context-management", - "phase_dir": "04-matrix-mvp-shared-agent-context-and-context-management-comma", - "plan": null, - "task": null, - "total_tasks": null, - "status": "paused", + "timestamp": "2026-04-27T18:44:51.832Z", + "phase": "05", + "phase_name": "deployment", + "phase_dir": null, + "plan": 0, + "task": 0, + "total_tasks": 0, + "status": "pre-planning", "completed_tasks": [ - {"id": 1, "name": "docker-compose config mount + MATRIX_AGENT_REGISTRY_PATH", "status": "done"}, - {"id": 2, "name": "debug logging in sdk/real.py (_stream_agent_events)", "status": "done"}, - {"id": 3, "name": "debug logging in platform-agent service.py", "status": "done"} + { + "id": 1, + "name": "Research platform repos (agent, agent_api, master)", + "status": "done", + "commit": null + }, + { + "id": 2, + "name": "Clarify deployment topology with platform team", + "status": "done", + "commit": null + }, + { + "id": 3, + "name": "Create docs/deploy-architecture.md", + "status": "done", + "commit": null + } ], "remaining_tasks": [ - {"id": 4, "name": "run docker compose up --build and get platform-agent logs with stream_event lines", "status": "not_started"}, - {"id": 5, "name": "analyze logs: content_type and langgraph_node to find where first chunk is lost", "status": "not_started"}, - {"id": 6, "name": "fix in service.py based on findings (filter by node, handle list content, or capture subagent output)", "status": "not_started"} + {"id": 4, "name": "Merge feat/matrix-direct-agent-prototype → main", "status": "not_started"}, + {"id": 5, "name": "Plan Phase 05 (deployment)", "status": "not_started"}, + {"id": 6, "name": "Execute Phase 05", "status": "not_started"} + ], + "blockers": [ + { + "description": "agent_api #9-clientside-tool-call убирает attachments и MsgEventSendFile — если смержат до деплоя, сломает file transfer", + "type": "external", + "workaround": "Используем master пока #9 не merged. Уточнить у Азамата сроки." + }, + { + "description": "AGENT_ID и COMPOSIO_API_KEY значения для каждого агента — нужны от платформы", + "type": "human_action", + "workaround": "Запросить у Азамата перед деплоем" + } ], - "blockers": [], "human_actions_pending": [ - {"action": "run docker compose up --build and reproduce the alphabet/image truncation bug", "context": "Need platform-agent logs with DEBUG level to see stream_event lines", "blocking": true} + { + "action": "Получить значения AGENT_ID и COMPOSIO_API_KEY для каждого агента от платформы", + "context": "Composio смержен в main platform-agent, теперь обязателен", + "blocking": true + }, + { + "action": "Уточнить у Азамата сроки мержа agent_api #9 (убирает attachments/MsgEventSendFile)", + "context": "Мы строим file transfer на этих фичах из master", + "blocking": false + }, + { + "action": "Уточнить: chat_id=0 для всех или используем разные chat_id для C1/C2/C3", + "context": "Платформа показала пример с одним AgentApi на агента без явного chat_id", + "blocking": false + } ], "decisions": [ - {"decision": "Bug is in platform-agent service.py __astream, not in surfaces bot", "rationale": "Logs show first text chunk already truncated at index=0 level", "phase": "04"}, - {"decision": "deepagents uses dispatcher+subagent architecture", "rationale": "create_deep_agent wraps SubAgentMiddleware with general-purpose subagent", "phase": "04"}, - {"decision": "astream_events v2 processes on_chat_model_stream from ALL nodes without filtering", "rationale": "service.py has no namespace/node filtering", "phase": "04"} + { + "decision": "Один инстанс Matrix-бота на всех пользователей, один агент-контейнер на пользователя", + "rationale": "Подтверждено платформой. Reverse proxy на lambda.coredump.ru:7000 роутит по пути /agent_N/", + "phase": "pre-05" + }, + { + "decision": "Файлы через shared volume /agents/, не через API", + "rationale": "Surface и агент видят один volume. Surface пишет файл → передаёт путь в attachments. Агент эмитит MsgEventSendFile → Surface читает файл и шлёт в Matrix", + "phase": "pre-05" + }, + { + "decision": "Используем agent_api master (с attachments и MsgEventSendFile), не ветку #9", + "rationale": "master стабильный, #9 в разработке и убирает нужные нам фичи", + "phase": "pre-05" + }, + { + "decision": "Конфиг: два словаря — user_id→agent_id и agent_id→{base_url, workspace_path}", + "rationale": "Платформа подтвердила статический маппинг для MVP без Master", + "phase": "pre-05" + }, + { + "decision": "Master (platform-master feat/storage) не используем для MVP", + "rationale": "Ещё в разработке. Используем статический конфиг. При готовности Master — мигрируем.", + "phase": "pre-05" + } ], "uncommitted_files": [ - "sdk/real.py (debug logging added)", - "docker-compose.yml (config volume mount added)", - "config/matrix-agents.example.yaml (label names updated)", - "external/platform-agent/src/agent/service.py (debug logging added, in submodule)" + "docs/deploy-architecture.md", + "docs/superpowers/plans/2026-04-24-matrix-multi-agent-routing-and-restart-state.md", + "config/matrix-agents.yaml", + ".planning/STATE.md" ], - "next_action": "Run: docker compose up --build. Send a message that triggers the bug (e.g. 'Напомни алфавит' after sending an image). Look for stream_event lines in platform-agent-1 logs. Check content_type and langgraph_node values for truncated responses.", - "context_notes": "Investigating first-chunk truncation bug in Matrix bot responses. The bug appears when agent uses tools (image analysis) OR when images are in context. Platform-agent uses deepagents framework (dispatcher+subagent pattern). The hypothesis is that on_chat_model_stream events from multiple graph nodes are all forwarded as MsgEventTextChunk without filtering, OR that chunk.content is sometimes a list instead of str causing validation issues. Added logging to confirm. The fix will likely be in service.py: either filter by langgraph_node or handle list content type." + "next_action": "Запустить /gsd-plan-phase 05 для планирования фазы деплоя. Прочитать docs/deploy-architecture.md перед планированием.", + "context_notes": "Phase 04 полностью завершена, ветка feat/matrix-direct-agent-prototype готова к merge. Этот сеанс был посвящён архитектуре деплоя — исследовали платформу, обсуждали с командой. Всё что знаем про деплой — в docs/deploy-architecture.md. Phase 05 = деплой: обновить конфиг, sdk/real.py, добавить file transfer в Matrix адаптер, написать docker-compose." } diff --git a/.planning/STATE.md b/.planning/STATE.md index e3451ae..5d87f69 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,8 +2,8 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: — Production-ready surfaces -status: Phase 04 multi-agent follow-up complete -last_updated: "2026-04-24T14:10:00Z" +status: Phase 04 complete — deployment architecture clarified, Phase 05 ready to plan +last_updated: "2026-04-27T18:44:51Z" progress: total_phases: 5 completed_phases: 2 @@ -92,5 +92,5 @@ All 5 tasks of the multi-agent routing follow-up are committed on `feat/matrix-d ## Session - Last session: 2026-04-24T14:10:00Z -- Stopped at: Phase 04 multi-agent follow-up fully committed (e733119); 135 tests green; branch feat/matrix-direct-agent-prototype ready for review/merge -- Resume file: HANDOFF deleted; no pending tasks +- Stopped at: Deployment architecture clarified with platform team; docs/deploy-architecture.md written; Phase 05 ready to plan +- Resume file: .planning/.continue-here.md diff --git a/docs/deploy-architecture.md b/docs/deploy-architecture.md new file mode 100644 index 0000000..8746e56 --- /dev/null +++ b/docs/deploy-architecture.md @@ -0,0 +1,145 @@ +# Deployment Architecture — Matrix Bot + Agents + +> Сформировано 2026-04-27 по итогам обсуждения с платформой. + +--- + +## Топология + +``` +lambda.coredump.ru +├── :7000 (reverse proxy, path-based routing) +│ ├── /agent_0/ → agent_0 container +│ ├── /agent_1/ → agent_1 container +│ └── /agent_N/ → agent_N container +│ +└── Matrix bot instance (один инстанс на всех) + └── volume /agents/ (shared с агентами) + ├── /agents/0/ ← workspace agent_0 + ├── /agents/1/ ← workspace agent_1 + └── /agents/N/ +``` + +- **Один инстанс Matrix-бота** обслуживает всех пользователей. +- **Один агент-контейнер на пользователя.** Изоляция по agent_id, не через chat_id внутри одного инстанса. +- **Shared volume** `/agents/` смонтирован и в Matrix-бот, и в каждый агент-контейнер. Агент видит свой подкаталог как `/workspace`. + +--- + +## Конфиг (два словаря) + +```yaml +# config/matrix-agents.yaml + +user_agents: + "@user0:matrix.lambda.coredump.ru": agent-0 + "@user1:matrix.lambda.coredump.ru": agent-1 + "@user2:matrix.lambda.coredump.ru": agent-2 + +agents: + - id: agent-0 + label: "Agent 0" + base_url: "ws://lambda.coredump.ru:7000/agent_0/" + workspace_path: "/agents/0/" + + - id: agent-1 + label: "Agent 1" + base_url: "ws://lambda.coredump.ru:7000/agent_1/" + workspace_path: "/agents/1/" +``` + +- `user_agents` — маппинг Matrix user_id → agent_id (статический, выдаётся платформой) +- `agents` — маппинг agent_id → URL агента и путь к его workspace на shared volume + +--- + +## Agent API (используем master ветку `platform/agent_api`) + +```python +from lambda_agent_api.agent_api import AgentApi + +connected_agents: dict[str, AgentApi] = {} + +def on_agent_disconnect(agent: AgentApi): + del connected_agents[agent.id] + +async def on_message(matrix_user_id: str, text: str): + agent_id = get_agent_id_by_user(matrix_user_id) # из user_agents конфига + + agent = connected_agents.get(agent_id) + if not agent: + agent = AgentApi( + agent_id, + get_agent_base_url(agent_id), # ws://lambda.coredump.ru:7000/agent_0/ + on_disconnect=on_agent_disconnect, + chat_id=0, # default, один чат на агента + ) + await agent.connect() + connected_agents[agent_id] = agent + + async for event in agent.send_message(text): + ... +``` + +**Параметры конструктора (master):** +```python +AgentApi( + agent_id: str, + base_url: str, # ws://host:port/agent_N/ + chat_id: int = 0, # default — один чат на агента + on_disconnect: callable, +) +``` + +**Lifecycle:** агент автоматически отключается после нескольких минут бездействия. +`on_disconnect` удаляет из пула → следующее сообщение создаёт новое соединение. + +--- + +## Передача файлов + +### Пользователь → Агент (входящий файл) + +1. Matrix-бот получает файл от пользователя +2. Сохраняет в workspace агента: `/agents/{N}/incoming/{filename}` +3. Вызывает `agent.send_message(text, attachments=["incoming/filename"])` + — путь относительно `/workspace` агента + +### Агент → Пользователь (исходящий файл) + +1. Агент эмитит `MsgEventSendFile(path="output/report.pdf")` +2. Matrix-бот читает файл: `/agents/{N}/output/report.pdf` +3. Отправляет как Matrix file message пользователю + +**Ключевое:** поверхность видит `/agents/` целиком через shared volume. Прямой HTTP-доступ к файлам не нужен. + +--- + +## Текущее состояние platform-agent (main) + +- Composio интегрирован в main (`#9-интеграция-composIO`) +- Агент требует в `.env`: `AGENT_ID`, `COMPOSIO_API_KEY` +- Backend: `IsolatedShellBackend` (main) / `CompositeBackend` (ветка `#19`, не merged) +- Memory: `MemorySaver` — история слетает при рестарте контейнера (known limitation) + +--- + +## platform-master (будущее, пока не используем) + +Ветка `feat/storage` реализует реальный Master-сервис: +- `POST /api/v1/create {chat_id}` → поднимает/переиспользует sandbox-контейнер +- TTL-based lifecycle (300с default, конфигурируемо) +- `ChatStorage` — API для upload/download файлов через Master +- Auth + p2p lease — вне текущего scope MVP + +**Для деплоя MVP используем статический конфиг без Master.** +При готовности Master: `get_agent_url()` будет вызывать `POST /api/v1/create`, URL возвращается в ответе. + +--- + +## Что НЕ решено / открытые вопросы + +- Ветка `platform-agent_api #9-clientside-tool-call` убирает `attachments` и `MsgEventSendFile` — пока игнорируем, используем master. Уточнить у Азамата сроки мержа перед деплоем. +- `chat_id` — при нашей модели C1/C2/C3 каждый чат должен иметь отдельный `chat_id`. Нужно решить: один `AgentApi` на агента (chat_id=0) или по инстансу на чат (chat_id=1/2/3). Пока берём `chat_id=0` (один контекст на пользователя). +- Composio `AGENT_ID` в `.env` для каждого агента — уточнить у платформы значения. +- Что происходит с историей при рестарте агента — `MemorySaver` не персистентный.