# TASK: Implement Agent Hub (Team Assistant) using existing Messenger as core **Goal:** Створити головний "Agent Hub" інтерфейс (Team Assistant), який: - показує список microDAO / команд / агентів, - дозволяє вибрати агента й говорити з ним (на основі Messenger), - показує контекст (проєкти, задачі, квести, стан агента), - стане `/home` для користувача. **Constraints:** - Використати існуючий Messenger (channels, messages, WS) як ядро для чату. - Не дублювати логіку відправки/отримання повідомлень. - Agent Hub = надбудова над Messenger + Agents + Projects (stub). --- ## 1) Frontend structure **Create feature:** ``` src/features/agent-hub/ AgentHubPage.tsx components/ AgentSidebar.tsx AgentList.tsx AgentListItem.tsx AgentSummaryCard.tsx AgentContextPanel.tsx AgentStatusBadge.tsx hooks/ useAgents.ts useAgentHubState.ts api/ getAgents.ts getAgentSummary.ts getAgentContext.ts ``` **Route:** - Додати `/hub` або `/home`: ```tsx } /> ``` ### Layout (3-колонковий) ``` ┌──────────────────┬────────────────────────────┬───────────────────┐ │ Left: │ Center: │ Right: │ │ Agents sidebar │ Chat (Messenger embed) │ Context panel │ └──────────────────┴────────────────────────────┴───────────────────┘ ``` #### Left (AgentSidebar): - список: - "My microDAO" - "My agents" - "System agents" - кожен агент: name, kind, microDAO badge, status badge. - фільтр/пошук. #### Center: - Вбудований Messenger: - Reuse MessengerPage components: - ChannelHeader - MessageList - MessageComposer - Але: - працюємо з "direct" або "agent-specific" channel. - При виборі агента: - якщо ще немає direct channel з цим агентом: - викликати backend: ```http POST /api/messaging/channels { "name": "DM with Sofia-Prime", "type": "direct", "agent_id": "" } ``` - запамʼятати channel_id. - якщо є → просто підключити Messenger до цього channel_id. #### Right (AgentContextPanel): - картка обраного агента: - імʼя, архетип, модель, microDAO. - статус: active/idle, останній reply. - блок "Active projects" (stub): - отримати з `/api/agent-hub/agents/{id}/context` - список 3–5 проєктів/тасок (можна поки мок). - блок "Capabilities": - список інструментів агента (з blueprint): - "Can manage tasks" - "Can summarise channels" - "Can create follow-ups" --- ## 2) Backend: Agent Hub API **New service or extend existing agents-service:** `services/agents-service/` (якщо вже є, розширити) ### Endpoints: #### GET /api/agent-hub/agents → список агентів для поточного користувача: ```json [ { "id": "agent:sofia", "name": "Sofia-Prime", "kind": "assistant", "microdao_id": "microdao:7", "status": "online", "model": "gpt-4.1", "avatar_url": null } ] ``` #### GET /api/agent-hub/agents/{agentId}/summary → коротке резюме: ```json { "id": "agent:sofia", "name": "Sofia-Prime", "kind": "assistant", "microdao_id": "microdao:7", "specialization": "Team Assistant / PM", "description": "Допомагає планувати, підсумовувати, слідкує за задачами.", "last_activity_at": "...", "stats": { "messages_last_24h": 42, "channels": 5 } } ``` #### GET /api/agent-hub/agents/{agentId}/context → контекст: ```json { "projects": [ { "id": "...", "name": "Messenger v1", "status": "active" }, { "id": "...", "name": "City Dashboard", "status": "active" } ], "followups": [ { "id": "...", "title": "Перевірити NATS інтеграцію", "due_at": "..." } ] } ``` #### POST /api/agent-hub/agents/{agentId}/ensure-direct-channel Body: `{}` Behavior: - знайти чи існує direct channel між user та agent: ```sql SELECT FROM channels WHERE kind='direct' AND user_id=... AND agent_id=... ``` - якщо не існує: - створити в messaging-service: ```http POST /internal/messaging/channels { "name": "DM with Sofia-Prime", "kind": "direct", "microdao_id": "", "participants": ["user:...", "agent:sofia"] } ``` - повернути channel_id. - якщо існує → повернути channel_id. --- ## 3) Frontend wiring ### useAgents.ts: - `GET /api/agent-hub/agents` - зберігати список агентів + loading/error. ### useAgentHubState.ts: - стан: - `selectedAgentId` - `selectedChannelId` - методи: - `selectAgent(agentId)`: - викликати `/api/agent-hub/agents/{agentId}/ensure-direct-channel` - зберегти channelId - `selectChannel(channelId)` ### AgentHubPage.tsx: - Layout на 3 колонки. - Зліва: AgentSidebar (list, onSelect → selectAgent). - Центр: - якщо selectedChannelId: - рендер Messenger core: ```tsx ``` (створити обгортку над існуючими компонентами Messenger, яка приймає channelId як проп). - Праворуч: AgentContextPanel (summary + context для selectedAgent). --- ## 4) Reuse Messenger components **Створити lightweight обгортку:** `src/features/messenger/components/MessengerChannelView.tsx` Яка: - приймає `channelId` як проп, - внутрішньо використовує: - `useMessages(channelId)` - `useMessagingWebSocket(channelId)` - `MessageList` - `MessageComposer` - `ChannelHeader` (можна переоприділити title під імʼя агента). Це дозволяє: - зберегти один стек логіки для Messenger, - використовувати його і в `/messenger`, і в `/hub`. --- ## 5) Навігація Додати кнопку/посилання: - з Onboarding (PortalScene) → редірект у `/hub` замість `/city` або як додаткову опцію. - з `/city-v2` HUD: кнопка "Agent Hub" → `/hub`. - з `/messenger`: кнопка "Open Agent Hub" → `/hub`. --- ## 6) Документація Додати: - `docs/AGENT_HUB_MVP.md`: - опис ролі Agent Hub, - API endpoints, - UX flow (вибір агента → відкриття каналу → контекст справа), - як це повʼязано з agent-runtime (Phase 2). --- ## Acceptance Criteria - ✅ Route `/hub` відкривається без помилок. - ✅ В AgentSidebar видно список агентів для поточного користувача. - ✅ При виборі агента створюється (або знаходиться) direct channel, відкривається чат (Messenger components). - ✅ Праворуч показується хоча б stub-контекст (projects/followups з мокових даних). - ✅ Агент, підʼєднаний через Phase 2 (agent_filter + router + runtime), може відповідати в direct channel з Agent Hub. --- **Version:** 1.0.0 **Date:** 2025-11-24 **Priority:** High **Estimated Time:** 2 weeks **Dependencies:** TASK_PHASE2_AGENT_INTEGRATION.md (recommended but not blocking for UI)