Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions docs/adr/0013-conversation-orchestration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# ADR-0013: Conversation Service владеет диалогом

- Status: accepted
- Date: 2026-09-14

## Контекст

`Channel Gateway` уже принимает общий текстовый запрос и вызывает `Agent Runtime`. Следующий шаг —
создать сохранённое действие и вернуть карточку подтверждения. Если эту цепочку реализовать внутри
каждого канала или Gateway, Web, Telegram и VK начнут по-разному обрабатывать повторы, состояние
диалога и ошибки.

`Agent Runtime` не должен сохранять действие: он переводит текст в предложение. `Action Service`
не должен вести диалог: он хранит и выполняет уже сформированное действие.

## Решение

Создать отдельный `Conversation Service` как владельца прикладной оркестрации сообщения.

```mermaid
sequenceDiagram
participant Channel as Telegram / Web / VK
participant Edge as Channel Gateway
participant Talk as Conversation Service
participant Agent as Agent Runtime
participant Action as Action Service

Channel->>Edge: текст + requestKey
Edge->>Talk: нормализованное сообщение + identity
Talk->>Agent: разобрать текст
Agent-->>Talk: предложение или вопрос
alt данных достаточно
Talk->>Action: создать действие
Action-->>Talk: actionId + payloadHash + payload
Talk-->>Edge: карточка подтверждения
else нужно уточнение
Talk-->>Edge: текстовый вопрос
end
Edge-->>Channel: общий ответ канала
```

Границы компонентов:

- `Channel Gateway` проверяет identity, нормализует запрос и переводит общий ответ в протокол канала.
Он остаётся stateless и не вызывает `Agent Runtime` или `Action Service` напрямую после миграции.
- `Conversation Service` хранит сообщения и состояние диалога, обеспечивает идемпотентность по
`tenantId + subject + requestKey`, вызывает Agent и Action.
- `Agent Runtime` только возвращает предложение действия или вопрос для уточнения.
- `Action Service` остаётся источником истины для `actionId`, `payloadHash`, статуса и результата.
- `Widget SDK` проверяет и отображает общий контракт карточки. Он не вызывает Agent, MCP или базу.
- Кнопка карточки отправляет решение вместе с `actionId` и `payloadHash`; только `Action Service`
принимает или отклоняет действие.

Переход выполняется совместимо: существующий `/api/v1/messages` остаётся временным техническим
маршрутом до появления Conversation Service. Новый диалоговый endpoint добавляется отдельно; старый
удаляется только в следующей major-версии контракта.

## Причина

Так один и тот же диалог работает во всех каналах, а границы остаются простыми: Gateway отвечает за
транспорт, Conversation — за ход диалога, Agent — за разбор текста, Action — за надёжное действие.
Повтор доставки из Telegram или VK не создаёт второе действие.

## Последствия

- Появится отдельный репозиторий `conversation-service` со своей базой и миграциями.
- До его реализации Channel Gateway продолжает прямой вызов Agent как временный мост.
- Контракт ответа канала должен различать текст, карточку подтверждения и результат.
- Карточка содержит только отображаемые данные и ссылку на сохранённое действие; секреты и правила
выполнения в неё не попадают.
- Реальные бизнес-правила уточнений и текста карточки требуют отдельного решения владельца продукта.
4 changes: 4 additions & 0 deletions docs/architecture/PLATFORM.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ flowchart TB
- Transactional outbox согласует изменения локального состояния и публикацию событий.
- Контракты обратно совместимы в пределах major-версии и проверяются в CI.
- Все сервисы передают W3C Trace Context и отправляют данные OpenTelemetry.
- Channel Gateway не хранит диалог и не оркестрирует бизнес-сервисы.
- Conversation Service владеет состоянием диалога и цепочкой Agent → Action.
- Agent Runtime предлагает действие, а Action Service остаётся источником его состояния и payload hash.
- Widget SDK отображает контракт ответа, но никогда не вызывает MCP напрямую.

## Границы репозиториев

Expand Down
9 changes: 6 additions & 3 deletions docs/delivery/CURRENT_STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
| Репа | Что меняем или добавляем | Ожидаемый результат | Фактический результат | Следующий шаг |
|---|---|---|---|---|
| `.github` | Общие workflows и правила | Одинаковый CI/CD для всех сервисов | Java, Python, Node, docs, security и container workflows работают | Подключать правила к каждой новой репе |
| `contracts` | Версионируемые внешние и внутренние API | Один проверяемый источник сетевых DTO | Bundle `2.2.0` выпущен; добавлен Channel Gateway API | Спроектировать контракт ответа для виджета |
| `contracts` | Версионируемые внешние и внутренние API | Один проверяемый источник сетевых DTO | Bundle `2.2.0` выпущен; добавлен Channel Gateway API | Добавить совместимый ответ диалога и карточку подтверждения |
| `action-service` | Подтверждение и надёжное выполнение | `AWAITING_APPROVAL → APPROVED → EXECUTING → SUCCEEDED/FAILED` | jOOQ, outbox, Temporal worker и вызов MCP Gateway работают; backend acceptance зелёный | Принимать команду через Channel Gateway |
| `calendar-mcp` | `create_event` | Идемпотентное создание fake-события | Fake Calendar, OIDC и защита от дублей работают в общем сценарии | Оставить эталонным fake-коннектором |
| `mcp-gateway` | OIDC, allowlist и MCP client | Безопасный stateless-маршрутизатор | Foundation смержен и проверен вызовом Calendar MCP | Добавлять коннекторы только по контракту |
| `deploy` | Приложения в локальном Compose | Одна команда поднимает вертикальный backend-срез | Channel, Agent, Action, Temporal, MCP Gateway и Calendar поднимаются; GitHub smoke зелёный | Ускорить сборку полного smoke |
| `test-lab` | Календарный acceptance-тест | Один JWT и один контракт на всём пути | Схема Agent `2.1.0`, подтверждение и проверка часового пояса работают | Добавить повтор запроса и проверку отсутствия дубля |
| `agent-runtime` | Текст в предложение действия | Детерминированное предложение встречи без скрытого выполнения | API `2.1.0`, проверка JWT и календарное предложение работают в общем сценарии | Вызывать через Channel Gateway, AI-модель пока не выбирать |
| `channel-gateway` | Общий вход каналов | Web и Telegram используют один контракт | Репа создана; JWT, OpenAPI-типы и вызов Agent работают в общем acceptance | Добавить сохранённое action в ответ после выбора orchestration |
| `channel-gateway` | Общий вход каналов | Web и Telegram используют один контракт | Репа создана; JWT, OpenAPI-типы и вызов Agent работают в общем acceptance | После Conversation Service заменить временный прямой вызов Agent |
| `conversation-service` | Состояние диалога и прикладная оркестрация | Повтор сообщения не создаёт второе действие | Граница закреплена в ADR-0013; репа ещё не создана | Добавить контракт API и создать TDD-каркас |
| `widget-sdk` | Карточка подтверждения | Один UI-контракт для разных каналов | Репа ещё не создана | Спроектировать тип карточки и создать репу |

## Что уже проверено
Expand Down Expand Up @@ -41,7 +42,9 @@
-> [готово] Action Service и Temporal worker
-> [готово] Channel Gateway и Agent Runtime в общем Compose
-> [готово] backend acceptance
-> [следом] контракт карточки подтверждения и Widget SDK
-> [решено] Conversation Service владеет диалогом и цепочкой Agent → Action
-> [следом] совместимый контракт диалога и карточки подтверждения
-> Conversation Service и Widget SDK
-> Telegram adapter
```

Expand Down
14 changes: 8 additions & 6 deletions docs/delivery/MVP_ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,14 @@
2. Сначала написать сквозной acceptance-тест на fake AI и fake Calendar MCP.
3. Реализовать Channel Gateway без зависимости от Telegram.
4. Сделать Telegram адаптер примером канала, а не центром архитектуры.
5. Создать Widget SDK и карточку подтверждения.
6. Реализовать Conversation Service, Approval Service и MCP Gateway минимального размера.
7. Подключить один реальный календарь за тем же контрактом, что и fake.
8. Добавить audit trail, policy decision и durable workflow.
9. Провести load, soak, chaos и restore проверки.
10. Выпустить публичную MVP-версию с demo и инструкцией запуска.
5. Добавить совместимый контракт ответа диалога и карточки подтверждения.
6. Реализовать Conversation Service минимального размера и переключить на него Channel Gateway.
7. Создать Widget SDK, который проверяет и отображает общий контракт.
8. Реализовать Approval Service только когда появятся правила подтверждения сложнее текущего Action API.
9. Подключить один реальный календарь за тем же контрактом, что и fake.
10. Добавить audit trail, policy decision и durable workflow.
11. Провести load, soak, chaos и restore проверки.
12. Выпустить публичную MVP-версию с demo и инструкцией запуска.

Definition of Done MVP:

Expand Down
Loading