wip: deployment architecture research — Phase 05 ready to plan
- 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
This commit is contained in:
parent
c34db0e6c0
commit
8ffbe7b6b3
4 changed files with 308 additions and 29 deletions
72
.planning/.continue-here.md
Normal file
72
.planning/.continue-here.md
Normal file
|
|
@ -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
|
||||
---
|
||||
|
||||
<current_state>
|
||||
Phase 04 полностью завершена и закоммичена на ветке `feat/matrix-direct-agent-prototype` (135 тестов зелёные). Этот сеанс был посвящён архитектуре деплоя — изучили платформенные репозитории и обсудили топологию с командой платформы. Вся информация о деплое зафиксирована в `docs/deploy-architecture.md`. Phase 05 не спланирована, следующий шаг — `/gsd-plan-phase`.
|
||||
</current_state>
|
||||
|
||||
<completed_work>
|
||||
|
||||
- Изучены актуальные версии platform-agent, platform-agent_api, platform-master
|
||||
- Уточнена топология деплоя с платформой (схема с reverse proxy и shared volume)
|
||||
- Созданы `docs/deploy-architecture.md` — полное summary архитектуры деплоя
|
||||
</completed_work>
|
||||
|
||||
<remaining_work>
|
||||
|
||||
- Смержить `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` для деплоя
|
||||
</remaining_work>
|
||||
|
||||
<decisions_made>
|
||||
|
||||
- **Топология**: один инстанс 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` (один контекст на пользователя)
|
||||
</decisions_made>
|
||||
|
||||
<blockers>
|
||||
|
||||
- **AGENT_ID + COMPOSIO_API_KEY**: Composio смержен в main platform-agent, теперь обязателен. Значения нужны от Азамата перед деплоем.
|
||||
- **agent_api #9**: убирает `attachments` и `MsgEventSendFile` — если смержат до деплоя, сломает наш file transfer. Нужно уточнить сроки.
|
||||
</blockers>
|
||||
|
||||
## 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)
|
||||
|
||||
<context>
|
||||
Архитектура деплоя полностью прояснена. Нет неизвестных блокеров (кроме env-переменных от платформы). Phase 05 — чисто инженерная задача: обновить конфиг, sdk, Matrix адаптер, написать compose. Всё что нужно знать — в docs/deploy-architecture.md.
|
||||
</context>
|
||||
|
||||
<next_action>
|
||||
1. /clear
|
||||
2. /gsd-resume-work — прочитает этот файл и предложит план Phase 05
|
||||
3. Прочитать docs/deploy-architecture.md
|
||||
4. /gsd-plan-phase 05
|
||||
</next_action>
|
||||
|
|
@ -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."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
145
docs/deploy-architecture.md
Normal file
145
docs/deploy-architecture.md
Normal file
|
|
@ -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` не персистентный.
|
||||
Loading…
Add table
Add a link
Reference in a new issue