# Matrix Direct-Agent Prototype

> **ВНИМАНИЕ: Это исторический документ.**
> Описанный здесь прототип был интегрирован в `main` и стал основой для Matrix MVP, но архитектура претерпела значительные изменения. Для актуальной информации по деплою смотрите `docs/deploy-architecture.md`, а для создания новой поверхности — `docs/max-surface-guide.md`.

Русскоязычная заметка по прототипу Matrix surface, который ходит не в `MockPlatformClient`, а напрямую в живой agent backend по WebSocket.

## Что сделали

В этой ветке собран рабочий Matrix-only прототип с минимальным вмешательством в существующую архитектуру.

Ключевая идея:
- Matrix-адаптер и `core/` остаются на старом контракте `PlatformClient`
- вместо `sdk/mock.py` можно включить `sdk/real.py`
- `sdk/real.py` внутри разделяет две ответственности:
  - `sdk/agent_session.py` — прямое общение с agent по WebSocket
  - `sdk/prototype_state.py` — локальный user/settings state для прототипа

Это позволило не переписывать Matrix-логику под нестабильный `platform/master` и при этом подключить живого агента вместо мока.

## Что поменялось в `surfaces-bot`

Добавлено:
- `sdk/agent_session.py`
- `sdk/prototype_state.py`
- `sdk/real.py`
- тесты для transport/state/real backend

Изменено:
- `adapter/matrix/bot.py`
- `adapter/matrix/handlers/auth.py`
- `README.md`
- интеграционные и Matrix dispatcher тесты

Функционально это дало:
- переключение Matrix backend через env:
  - `MATRIX_PLATFORM_BACKEND=mock`
  - `MATRIX_PLATFORM_BACKEND=real`
- прямую отправку текста в live agent через `AGENT_BASE_URL`
- локальное хранение settings и user mapping
- изоляцию backend memory по `thread_id`
- исправление повторных invite: бот теперь сначала `join()`, а уже потом решает, нужно ли пере-провиженить Space/chat tree

## Что поменяли в `platform-agent`

Для прототипа потребовался минимальный локальный патч в клонированном `external/platform-agent`.

Изменения:
- `src/api/external.py`
- `src/agent/service.py`

Смысл патча:
- agent больше не использует один общий hardcoded `thread_id="default"`
- `thread_id` читается из query parameter WebSocket-соединения
- дальше этот `thread_id` передаётся в config memory/checkpointer

Локальный commit в clone:
- `1dca2c1` — `feat: support websocket thread ids`

Важно:
- этот commit живёт в `external/platform-agent`
- он не входит в git-историю `surfaces-bot`
- если прототип должен запускаться у других людей без ручных патчей, этот commit надо отдельно запушить или повторить в platform repo

## Текущая архитектура прототипа

Поток сообщения сейчас такой:

1. Matrix room event попадает в `adapter/matrix`
2. адаптер переводит его в `IncomingMessage` / `IncomingCommand`
3. `EventDispatcher` вызывает handler из `core/`
4. handler вызывает `PlatformClient`
5. при real backend это `RealPlatformClient`
6. `RealPlatformClient` строит `thread_key`
7. `AgentSessionClient` открывает WebSocket на `agent_ws/?thread_id=...`
8. ответ агента возвращается обратно в Matrix

Что остаётся локальным в v1:
- `!settings`
- `!skills`
- `!soul`
- `!safety`
- user registration mapping

Что реально идёт в живого агента:
- обычные текстовые сообщения
- память по чатам через `thread_id`

## Ограничения прототипа

Сейчас это не полный platform integration, а рабочий direct-agent prototype.

Ограничения:
- только текстовый чат
- без attachments в agent
- без async task callbacks/webhooks
- без реального control-plane из `platform/master`
- encrypted Matrix rooms пока не поддержаны
- repeat invite не создаёт новую Space-структуру, если user уже был провиженен локально
- backend/provider ошибки пока не везде деградируют в user-facing reply; часть ошибок всё ещё может уронить процесс surface

## Как запускать

Нужно поднять два процесса:
- patched `platform-agent`
- Matrix bot из `surfaces-bot`

### 1. Подготовить `platform-agent`

Локальный clone:
- [external/platform-agent](/Users/a/MAI/sem2/lambda/surfaces-bot/external/platform-agent)

И связанный SDK clone:
- [external/platform-agent_api](/Users/a/MAI/sem2/lambda/surfaces-bot/external/platform-agent_api)

Первичная подготовка:

```bash
cd /Users/a/MAI/sem2/lambda/surfaces-bot/external/platform-agent
uv sync
uv pip install --python .venv/bin/python -e ../platform-agent_api
```

Если у вас был активирован чужой venv, сначала сделайте:

```bash
deactivate
```

Иначе `uv pip install` может поставить пакет не в тот interpreter.

### 2. Запустить agent backend

Пример с OpenRouter:

```bash
cd /Users/a/MAI/sem2/lambda/surfaces-bot/external/platform-agent

export PROVIDER_URL=https://openrouter.ai/api/v1
export PROVIDER_API_KEY='YOUR_OPENROUTER_KEY'
export PROVIDER_MODEL='qwen/qwen3.5-122b-a10b'

uv run uvicorn src.main:app --host 0.0.0.0 --port 8000
```

После этого WebSocket endpoint должен быть доступен по:

```text
ws://127.0.0.1:8000/agent_ws/
```

### 3. Запустить Matrix bot

В отдельном терминале:

```bash
cd /Users/a/MAI/sem2/lambda/surfaces-bot

export MATRIX_PLATFORM_BACKEND=real
export AGENT_BASE_URL=http://127.0.0.1:8000
export MATRIX_HOMESERVER=https://matrix.lambda.coredump.ru
export MATRIX_USER_ID=@lambda_surface_test_bot:matrix.lambda.coredump.ru
export MATRIX_PASSWORD='YOUR_PASSWORD'

PYTHONPATH=. uv run python -m adapter.matrix.bot
```

Если всё ок, в логах будет что-то вроде:

```text
Matrix bot starting ...
```

## Точные команды

Ниже команды в том виде, в котором реально поднимался рабочий прототип.

### Platform / agent backend

```bash
cd /Users/a/MAI/sem2/lambda/surfaces-bot/external/platform-agent
deactivate 2>/dev/null || true
uv sync
uv pip install --python .venv/bin/python -e ../platform-agent_api

export PROVIDER_URL=https://openrouter.ai/api/v1
export PROVIDER_API_KEY='YOUR_OPENROUTER_KEY'
export PROVIDER_MODEL='qwen/qwen3.5-122b-a10b'

uv run uvicorn src.main:app --host 0.0.0.0 --port 8000
```

### Matrix bot

```bash
cd /Users/a/MAI/sem2/lambda/surfaces-bot

export MATRIX_PLATFORM_BACKEND=real
export AGENT_BASE_URL=http://127.0.0.1:8000
export MATRIX_HOMESERVER=https://matrix.lambda.coredump.ru
export MATRIX_USER_ID=@lambda_surface_test_bot:matrix.lambda.coredump.ru
export MATRIX_PASSWORD='YOUR_PASSWORD'

PYTHONPATH=. uv run python -m adapter.matrix.bot
```

### Перезапуск Matrix state с нуля

```bash
cd /Users/a/MAI/sem2/lambda/surfaces-bot
rm -f lambda_matrix.db
rm -rf matrix_store
PYTHONPATH=. uv run python -m adapter.matrix.bot
```

## Smoke test

Рекомендуемый сценарий ручной проверки:

1. Пригласить бота в fresh unencrypted room
2. Дождаться join
3. Если это первый invite для данного локального state:
   - бот создаст private Space
   - бот создаст room `Чат 1`
4. Открыть `Чат 1`
5. Отправить `!start`
6. Отправить обычное текстовое сообщение
7. Проверить, что ответ пришёл от live backend, а не от `[MOCK]`
8. Проверить `!new`
9. Проверить, что память разделяется между чатами

Если бот уже был однажды провиженен и локальный state не очищался:
- повторный invite не создаст новую Space-структуру
- бот просто зайдёт в room и будет отвечать там

Это нормальное поведение текущей реализации.

## Сброс локального Matrix state

Если нужно повторно проверить именно first-invite provisioning:

```bash
cd /Users/a/MAI/sem2/lambda/surfaces-bot
rm -f lambda_matrix.db
rm -rf matrix_store
PYTHONPATH=. uv run python -m adapter.matrix.bot
```

После этого можно снова приглашать бота как "с нуля".

## Частые проблемы

### 1. `ModuleNotFoundError: lambda_agent_api`

Значит `platform-agent_api` не установлен в `.venv` агента.

Исправление:

```bash
cd /Users/a/MAI/sem2/lambda/surfaces-bot/external/platform-agent
uv pip install --python .venv/bin/python -e ../platform-agent_api
```

### 2. `CERTIFICATE_VERIFY_FAILED` при запуске Matrix bot

Это не ошибка surface logic. Это TLS trust problem до Matrix homeserver.

Нужно:
- либо установить системные/Python certificates
- либо передать корпоративный CA через `SSL_CERT_FILE`

### 3. Бот заходит в room, но не создаёт новую Space

Скорее всего user уже есть в локальном state.

Варианты:
- это ожидаемо для repeat invite
- либо очистить `lambda_matrix.db` и `matrix_store`

### 4. Бот падает после message send

Значит backend/provider вернул ошибку, которая ещё не была деградирована в user-facing ответ.

Пример уже встречавшегося кейса:
- неверный model id
- key не имеет доступа к model

Сначала проверяйте:
- `PROVIDER_URL`
- `PROVIDER_MODEL`
- `PROVIDER_API_KEY`

## Полезные ссылки внутри repo

- [README.md](/Users/a/MAI/sem2/lambda/surfaces-bot/README.md)
- [adapter/matrix/bot.py](/Users/a/MAI/sem2/lambda/surfaces-bot/adapter/matrix/bot.py)
- [sdk/agent_session.py](/Users/a/MAI/sem2/lambda/surfaces-bot/sdk/agent_session.py)
- [sdk/real.py](/Users/a/MAI/sem2/lambda/surfaces-bot/sdk/real.py)
- [sdk/prototype_state.py](/Users/a/MAI/sem2/lambda/surfaces-bot/sdk/prototype_state.py)
- [2026-04-08-matrix-direct-agent-prototype-design.md](/Users/a/MAI/sem2/lambda/surfaces-bot/docs/superpowers/specs/2026-04-08-matrix-direct-agent-prototype-design.md)
- [2026-04-08-matrix-direct-agent-prototype.md](/Users/a/MAI/sem2/lambda/surfaces-bot/docs/superpowers/plans/2026-04-08-matrix-direct-agent-prototype.md)
