# ADR: DAARWIZZ Orchestration Mode (Гібридна архітектура)

**Дата:** 2026-01-19  
**Статус:** Прийнято  
**Версія:** 1.0

---

## Контекст

DAARION.city має 5 спеціалізованих агентів:
- **Helion** — енергетика, DePIN
- **Nutra** — харчування, дієти
- **Druid** — біомедичні добавки, лабораторії
- **GreenFood** — крафтові виробники, кооперативи
- **DAARWIZZ** — системний координатор

**Проблема:** Користувачі не знають, до якого агента звернутися. Потрібна єдина точка входу з автоматичною маршрутизацією.

---

## Рішення: Гібридна архітектура (3 етапи)

### Етап A (зараз): Ізольовані боти + "м'який" DAARWIZZ

**Поведінка:**
- Прямі боти (@energyunionBot, @NutraChat_bot, @DRUID73bot) працюють ізольовано
- @DAARWIZZBot працює як **довідник + маршрутизатор**:
  - Класифікує intent користувача
  - Рекомендує правильного агента
  - Може зробити "soft handoff" (передати запит, але відповідь йде через DAARWIZZ)
  - **НЕ робить автоматичний handoff без згоди користувача**

**Приклад:**
```
Користувач: "що їсти на сніданок?"
DAARWIZZ: "Це питання харчування. Рекомендую @NutraChat_bot. 
           Можу передати запит туди зараз — дозволиш?"
```

### Етап B (пізніше): DAARWIZZ-first для 30-50% трафіку

**Поведінка:**
- @DAARWIZZBot стає **рекомендованим entry point** для нових користувачів
- Автоматичний handoff для "safe" класів запитів (single-domain)
- Прямі боти залишаються як "pro mode" для профі-користувачів

### Етап C (майбутнє): Повна оркестрація multi-agent сценаріїв

**Поведінка:**
- DAARWIZZ планує multi-step сценарії (handoff між доменами)
- Збір фактів від кількох агентів
- Контекстні контракти: що можна передавати між агентами

---

## Handoff Contract (стандартизований пакет)

### Структура:

```python
{
    "intent": "nutrition_advice",  # Що хоче користувач
    "domain": "nutrition",          # Домен (energy/food/supplements)
    "user_goal": "що їсти на сніданок",  # Оригінальне питання
    "target_agent": "nutra",       # Куди делегувати
    "constraints": {
        "max_response_time": 30,    # Секунд
        "format": "short",          # short/medium/detailed
        "language": "uk"
    },
    "context_summary": "Користувач питає про сніданок",  # БЕЗ секретів
    "sources": [],                  # IDs повідомлень/Co-Memory, не plaintext
    "privacy_level": "public",     # public/team/confidential
    "requires_consent": true       # Чи потрібна згода користувача
}
```

### Правила передачі:

1. **Single-domain запити** → автоматичний handoff (після Етапу A)
2. **Multi-domain запити** → DAARWIZZ робить plan + збирає відповіді
3. **Confidential/E2EE** → тільки sanitized summary або явна згода

---

## Розділення пам'яті

### Персональна пам'ять агентів (Nutra/Helion/Druid):
- **Qdrant:** `{agent_id}_messages`, `{agent_id}_docs`
- **Neo4j:** `:{AgentId}_*` labels
- **НЕ передається** автоматично в DAARWIZZ

### Orchestration пам'ять DAARWIZZ:
- **Qdrant:** `daarwizz_orchestration` (логи планів, стани задач)
- **Neo4j:** `:Orchestration` nodes (handoff історія)
- **НЕ містить** приватний контент користувачів

---

## Політика приватності

### За замовчуванням:
- **Public запити** → можна делегувати з context_summary
- **Team запити** → тільки в межах команди
- **Confidential запити** → тільки sanitized summary або явна згода

### Ескалація:
- Якщо запит потребує handoff, але privacy_level = confidential:
  - DAARWIZZ питає: "Дозволиш передати це питання в Nutra? (буде передано тільки узагальнений контекст)"
  - Користувач підтверджує → handoff
  - Користувач відхиляє → DAARWIZZ відповідає сам (якщо може)

---

## Технічна реалізація

### 1. Intent Router в DAARWIZZ

```python
def route_intent(message: str) -> Dict:
    """
    Визначає intent та рекомендованого агента.
    Повертає handoff contract (якщо потрібно).
    """
    # Класифікація через LLM або keyword matching
    # Повертає: intent, domain, target_agent, confidence
```

### 2. Handoff Handler

```python
async def handle_handoff(contract: HandoffContract) -> Dict:
    """
    Виконує handoff до target_agent.
    Повертає відповідь для користувача.
    """
    # Викликає Router з target_agent
    # Повертає результат через DAARWIZZ
```

### 3. NATS Subjects для handoff

```
agent.daarwizz.handoff.request  # Запит на handoff
agent.daarwizz.handoff.response # Відповідь від агента
agent.{agent_id}.invoke         # Прямий виклик агента
```

---

## Покрокове впровадження

### ✅ Етап A (зараз): "М'який" DAARWIZZ
- [x] DAARWIZZ класифікує intent
- [x] DAARWIZZ рекомендує агента
- [ ] DAARWIZZ пропонує "soft handoff" (з згодою)
- [ ] Логування handoff рішень

### ⏳ Етап B (пізніше): DAARWIZZ-first
- [ ] Автоматичний handoff для single-domain
- [ ] Метрики: % трафіку через DAARWIZZ
- [ ] A/B тестування: DAARWIZZ vs прямі боти

### 📋 Етап C (майбутнє): Multi-agent оркестрація
- [ ] Планування multi-step сценаріїв
- [ ] Збір фактів від кількох агентів
- [ ] Контекстні контракти

---

## Критерії успіху

1. **Користувачі знають, куди звернутися** (через DAARWIZZ)
2. **Прямі боти залишаються швидкими** для профі-користувачів
3. **Приватність збережена** (confidential не передається без згоди)
4. **Масштабування без міграції UX** (можна додавати нових агентів)

---

## Альтернативи (відхилені)

1. **Тільки прямі боти** — користувачі не знають, куди звернутися
2. **Тільки DAARWIZZ** — втрата швидкості для профі-користувачів
3. **Повна оркестрація одразу** — занадто складно для MVP

---

**Версія:** 1.0  
**Останнє оновлення:** 2026-01-19
