docs(05-04): document split deployment artifacts

- document prod vs fullstack compose usage
- align operator docs with shared /agents contract
This commit is contained in:
Mikhail Putilovskij 2026-04-28 01:15:41 +03:00
parent 85e2fda6bc
commit 22a3a2b60a
2 changed files with 50 additions and 24 deletions

View file

@ -7,7 +7,7 @@
| Поверхность | Статус |
|---|---|
| Telegram | 🔨 В разработке, отдельный worktree `feat/telegram-adapter` |
| Matrix | ✅ Рабочий прототип, запускается через root `docker compose` вместе с `platform-agent` |
| Matrix | ✅ MVP runtime: `docker-compose.prod.yml` для bot-only handoff, `docker-compose.fullstack.yml` для internal E2E |
---
@ -90,7 +90,7 @@ class PlatformClient(Protocol):
Бот передаёт `user_id` + `chat_id` + сообщение; платформа сама решает нужно ли поднять контейнер.
Сейчас: `MockPlatformClient` в `sdk/mock.py`, а Matrix real backend собирается через `sdk/real.py` при `MATRIX_PLATFORM_BACKEND=real`.
Файловый контракт уже path-based: бот пишет файлы в shared `/workspace` и передаёт платформе относительные пути в `attachments`.
Файловый контракт уже path-based: бот пишет файлы в shared `/agents` и передаёт платформе относительные пути в `attachments`, которые агент читает внутри своего `/workspace`.
Когда SDK готов: добавляем `SdkPlatformClient`, меняем одну строку в DI. Адаптеры и ядро не трогаем.
---
@ -121,9 +121,13 @@ MATRIX_PASSWORD=... # или MATRIX_ACCESS_TOKEN=...
# Выбор backend: mock (по умолчанию) или real (подключение к platform-agent)
MATRIX_PLATFORM_BACKEND=real
# compose runtime: platform-agent service name + shared /workspace
AGENT_BASE_URL=http://platform-agent:8000
SURFACES_WORKSPACE_DIR=/workspace
# production handoff: bot connects to externally managed agent endpoint
AGENT_BASE_URL=https://lambda.coredump.ru/agent_0/
SURFACES_WORKSPACE_DIR=/agents
SURFACES_SHARED_VOLUME=surfaces-agents
# internal full-stack compose defaults
AGENT_ID=matrix-dev
# platform-agent provider
PROVIDER_MODEL=openai/gpt-4o-mini
@ -137,19 +141,28 @@ PROVIDER_API_KEY=...
2. Если готовишься к multi-agent routing, добавь `MATRIX_AGENT_REGISTRY_PATH=config/matrix-agents.yaml` в `.env`
3. Этот registry сейчас является конфигурационным артефактом Task 1; текущий Matrix runtime его ещё не читает
### 4. Compose runtime
### 4. Compose artifacts
Root `docker-compose.yml` теперь является основным локальным runtime для Matrix и platform-agent.
Он поднимает `matrix-bot`, `platform-agent` и общий volume `/workspace`.
Production handoff uses `docker-compose.prod.yml`.
Этот файл поднимает только `matrix-bot`, монтирует shared volume в `/agents` и ожидает, что `AGENT_BASE_URL`
указывает на уже управляемый внешней платформой agent endpoint.
```bash
docker compose up --build
docker compose --env-file .env -f docker-compose.prod.yml up -d --build
```
Compose собирает `platform-agent` из актуального upstream `external/platform-agent` Dockerfile (`development` target),
монтирует live-код из `external/platform-agent/src` и `external/platform-agent_api`, и подготавливает shared `/workspace`
с правами для agent runtime.
Matrix бот подключается к `platform-agent` по service name, а не к отдельно запущенному `localhost`.
Internal full-stack E2E uses `docker-compose.fullstack.yml`.
Этот файл поднимает `matrix-bot` вместе с локальным `platform-agent`, использует тот же shared volume
(`SURFACES_SHARED_VOLUME`) и ждёт `service_healthy` вместо sleep-based sequencing.
```bash
docker compose --env-file .env -f docker-compose.fullstack.yml up --build
```
`docker-compose.fullstack.yml` собирает `platform-agent` из актуального upstream `external/platform-agent`
(`development` target), монтирует live-код из `external/platform-agent/src` и `external/platform-agent_api`,
а shared volume виден как `/agents` в bot container и как `/workspace` в `platform-agent`.
Старый root compose harness остаётся только как historical local reference и больше не является рекомендуемым runtime path.
На `2026-04-21` локальный compose runtime использует vendored upstream-версии платформы без локальных патчей:
@ -159,7 +172,7 @@ Matrix бот подключается к `platform-agent` по service name, а
### 4. Staged attachments в Matrix
Если Matrix-клиент отправляет файлы отдельными media events, бот не вызывает агента сразу.
Вместо этого он сохраняет файлы в shared `/workspace`, ставит их в очередь для конкретного чата и пользователя, и ждёт следующего обычного сообщения.
Вместо этого он сохраняет файлы в shared `/agents`, ставит их в очередь для конкретного чата и пользователя, и ждёт следующего обычного сообщения.
Как отправить файлы агенту:

View file

@ -4,6 +4,18 @@
---
## Compose Artifacts
- **Production deploy:** `docker-compose.prod.yml`
Bot-only handoff. Поднимает только `matrix-bot`, монтирует shared volume в `/agents`, требует внешний `AGENT_BASE_URL`.
- **Internal full-stack E2E:** `docker-compose.fullstack.yml`
Внутренний harness. Поднимает `matrix-bot` и `platform-agent`, использует тот же volume name и health-gated startup через `condition: service_healthy`.
Production operators should run the bot with `docker-compose.prod.yml`; internal verification should use `docker-compose.fullstack.yml`.
Старый root compose harness больше не является primary runtime contract для Phase 05.
---
## Топология
```
@ -22,7 +34,7 @@ lambda.coredump.ru
- **Один инстанс Matrix-бота** обслуживает всех пользователей.
- **Один агент-контейнер на пользователя.** Изоляция по agent_id, не через chat_id внутри одного инстанса.
- **Shared volume** `/agents/` смонтирован и в Matrix-бот, и в каждый агент-контейнер. Агент видит свой подкаталог как `/workspace`.
- **Shared volume** `/agents/` смонтирован в Matrix-бот. В internal full-stack harness тот же volume mounted as `/workspace` inside `platform-agent`, чтобы bot-side absolute paths и agent workspace относились к одному и тому же хранилищу.
---
@ -58,24 +70,25 @@ agents:
```python
from lambda_agent_api.agent_api import AgentApi
connected_agents: dict[str, AgentApi] = {}
connected_agents: dict[tuple[str, int], AgentApi] = {}
def on_agent_disconnect(agent: AgentApi):
del connected_agents[agent.id]
connected_agents.pop((agent.id, agent.chat_id), None)
async def on_message(matrix_user_id: str, text: str):
async def on_message(matrix_user_id: str, matrix_room_id: str, text: str):
agent_id = get_agent_id_by_user(matrix_user_id) # из user_agents конфига
platform_chat_id = get_room_platform_chat_id(matrix_room_id)
agent = connected_agents.get(agent_id)
agent = connected_agents.get((agent_id, platform_chat_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, один чат на агента
chat_id=platform_chat_id, # отдельный thread на Matrix room
)
await agent.connect()
connected_agents[agent_id] = agent
connected_agents[(agent_id, platform_chat_id)] = agent
async for event in agent.send_message(text):
...
@ -86,7 +99,7 @@ async def on_message(matrix_user_id: str, text: str):
AgentApi(
agent_id: str,
base_url: str, # ws://host:port/agent_N/
chat_id: int = 0, # default — один чат на агента
chat_id: int = 0, # surfaces must supply per-room platform_chat_id
on_disconnect: callable,
)
```
@ -111,7 +124,7 @@ AgentApi(
2. Matrix-бот читает файл: `/agents/{N}/output/report.pdf`
3. Отправляет как Matrix file message пользователю
**Ключевое:** поверхность видит `/agents/` целиком через shared volume. Прямой HTTP-доступ к файлам не нужен.
**Ключевое:** production handoff через `docker-compose.prod.yml` и internal E2E через `docker-compose.fullstack.yml` используют один и тот же `/agents` contract на стороне поверхности. Прямой HTTP-доступ к файлам не нужен.
---
@ -140,6 +153,6 @@ AgentApi(
## Что НЕ решено / открытые вопросы
- Ветка `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` (один контекст на пользователя).
- `chat_id`каждый Matrix chat room должен иметь собственный `platform_chat_id`. `!clear` должен ротировать `platform_chat_id` только для текущей комнаты, чтобы получить новый thread и чистый контекст без смены Matrix room.
- Composio `AGENT_ID` в `.env` для каждого агента — уточнить у платформы значения.
- Что происходит с историей при рестарте агента — `MemorySaver` не персистентный.