Files
microdao-daarion/docs/services/AGENTS_SERVICE_SPEC.md
Apple 3de3c8cb36 feat: Add presence heartbeat for Matrix online status
- matrix-gateway: POST /internal/matrix/presence/online endpoint
- usePresenceHeartbeat hook with activity tracking
- Auto away after 5 min inactivity
- Offline on page close/visibility change
- Integrated in MatrixChatRoom component
2025-11-27 00:19:40 -08:00

444 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AGENTS SERVICE SPEC (PORT 7002)
# Version: 1.0.0
---
## 0. PURPOSE
`Agents Service` — це центральний сервіс текстових агентів DAGI:
- надає API для виклику Helion, Helix, Metamorph та інших текстових агентів;
- інтегрується з DAGI Router / ProjectBus / Mesh Directory;
- застосовує:
- Agent Registry,
- Context Router,
- Silence Policy,
- Throttling,
- TeamDefinition/ProjectBus контекст.
Це логічний "Runtime осередок" для текстової частини DAGI.
Порт за замовчуванням (NODE1/NODE2): **7002**.
---
## 1. HIGH-LEVEL ARCHITECTURE
```text
[ Gateway (Telegram/Web/Matrix/...) ]
[ DAGI Router (gateway.daarion.city) ]
[ Agents Service (7002) ]
[ LLM Providers / Swapper / DAGI Mesh ]
```
Agents Service отримує **RouterEvent-like** запити від DAGI Router (або внутрішніх сервісів) та:
1. Визначає, які агенти доступні (через AgentRegistry + Mesh Directory + TeamDefinition).
2. Обирає найвідповіднішого/декількох (Context Router).
3. Перевіряє Silence Policy.
4. Застосовує throttling.
5. Викликає відповідний LLM / backend агента.
6. Повертає відповідь + metadata.
---
## 2. DEPENDENCIES
### 2.1. Внутрішні модулі
Agents Service використовує:
* `configs/AGENT_REGISTRY.yaml`
* `configs/AGENT_REGISTRY_SCHEMA.yaml`
* `services/agent_registry_loader.py`
* `services/agent_context_router.py`
* `services/agent_silence_policy.py`
* `services/agent_throttle.py`
* `services/agent_mesh_directory.py`
* `configs/team_definition.yaml`
* `configs/project_bus_config.yaml`
### 2.2. Зовнішні сервіси
* **LLM Provider / Swapper Service** (NODE1/NODE2)
* **NATS** (або інший event-bus) для:
* ProjectBus,
* Mesh Directory,
* M2M-комунікації між агентами.
* **PostgreSQL / Redis** (опційно) для:
* кешу відповідей,
* logging / traces.
---
## 3. CONFIGURATION
ENV-змінні:
```env
AGENTS_SERVICE_PORT=7002
AGENT_REGISTRY_PATH=configs/AGENT_REGISTRY.yaml
AGENT_REGISTRY_SCHEMA_PATH=configs/AGENT_REGISTRY_SCHEMA.yaml
TEAM_DEFINITION_PATH=configs/team_definition.yaml
PROJECT_BUS_CONFIG_PATH=configs/project_bus_config.yaml
MESH_DIRECTORY_MODE=inprocess # "inprocess" | "nats" | "http"
MESH_DIRECTORY_NATS_SUBJECT_BASE=agent.directory
LLM_PROVIDER_BASE_URL=http://localhost:8890 # або інший super-service/swapper
AGENT_THROTTLE_LIMIT_PER_MINUTE=3
AGENT_THROTTLE_WINDOW_SECONDS=60
```
---
## 4. PUBLIC API (HTTP)
### 4.1. `POST /agents/invoke`
Основний endpoint для DAGI Router та внутрішніх сервісів.
**Request:**
```json
{
"event": {
"event_id": "tg:123",
"source": "telegram",
"chat": { "id": "123", "type": "group" },
"user": { "id": "user1", "username": "alex" },
"team_id": "team-daariandao-core",
"project_id": "proj-daariandao",
"text": "helix, перевір api",
"attachments": {
"images": [],
"docs": [],
"audio": [],
"geo": [],
"tables": []
},
"flags": {
"command": null,
"reply_to": null,
"confidential_mode": "public"
}
},
"options": {
"force_agent_id": null, // якщо заповнено, обійти context router
"allow_panel_mode": true, // дозволити кільком агентам відповісти
"max_agents": 2 // верхня межа для panel-режиму
}
}
```
**Response (успішний сценарій):**
```json
{
"status": "ok",
"replies": [
{
"agent_id": "ag_helix",
"text": "Ось аналіз API ...",
"meta": {
"model": "HELIX_ENGINEER_MODEL",
"tokens_in": 123,
"tokens_out": 256,
"latency_ms": 900
}
}
],
"context": {
"project_id": "proj-daariandao",
"team_id": "team-daariandao-core",
"reply_mode": "panel"
}
}
```
**Response (ніхто не має відповідати):**
```json
{
"status": "silent",
"reason": "no_agent_or_policy",
"context": {
"project_id": "proj-daariandao",
"team_id": "team-daariandao-core"
}
}
```
**Response (throttling):**
```json
{
"status": "throttled",
"reason": "rate_limit",
"agent_id": "ag_helion"
}
```
---
### 4.2. `GET /agents/registry`
Повертає список агентів (тільки для адміністраторів / системних агентів):
**Response:**
```json
{
"agents": [
{
"agent_id": "ag_helion",
"name": "Helion",
"role": "assistant",
"priority": 5,
"model": "HELION_TEXT_MODEL",
"skills": ["допоможи", "поясни"],
"modalities": ["text"],
"description": "Головний асистент DAARION."
}
]
}
```
---
### 4.3. `GET /agents/instances`
Проксі до Mesh Directory (видно інстанси):
```json
{
"instances": [
{
"agent_id": "ag_helion",
"instance_id": "ag_helion@noda1-01",
"node_id": "NODA1",
"status": "online",
"project_ids": ["proj-daariandao"],
"microdao_id": "microdao-root",
"last_seen": 1732450200.123
}
]
}
```
---
## 5. INTERNAL LOGIC
### 5.1. Pipeline для `/agents/invoke`
Покроковий алгоритм:
1. **Parse event**
* прийняти `event` (RouterEvent-сумісний payload),
* витягнути `project_id`, `team_id`, `chat.id`.
2. **Load TeamDefinition**
* знайти команду по `team_id` (або по `project_id` → команди, які працюють у цьому проекті),
* зчитати `reply_mode`:
* `single` / `panel` / `silent`,
* `max_agents_per_message`.
3. **Load AgentRegistry & MeshDirectory**
* завантажити список агентів із registry,
* для кожного, хто в TeamDefinition:
* перевірити, чи є онлайн інстанси (Mesh Directory).
4. **Context Router**
* побудувати `AgentDescriptor` для кожного доступного агента (з skills, priority),
* викликати `select_best_agent(event, descriptors)`:
* для `single`: обрати 1,
* для `panel`: обрати до `max_agents_per_message`,
* для `silent`: можна одразу повернути `status: silent`.
5. **Silence Policy** (per-agent)
Для кожного кандидата:
* `should_agent_reply(agent_id, event)`:
* прямі згадки,
* команди,
* приватні чати,
* контекстна релевантність.
Якщо жоден не проходить → `status: silent`.
6. **Throttling** (per-agent, per-chat)
Для кожного, хто пройшов silence policy:
* `throttle.can_reply(agent_id, chat_id)`:
* якщо ні → позначити `throttled`,
* якщо хоча б один агент може відповідати → продовжуємо.
7. **Invoke agents (LLM Provider)**
Для кожного дозволеного агента:
* сформувати system prompt (на основі `AGENT_REGISTRY`, ролі, skills),
* сформувати user/context prompt (із події),
* відправити в LLM Provider / Swapper Service:
* `POST /llm/invoke` (або NATS subject `llm.invoke`).
8. **Aggregate response**
* зібрати `replies` (до N агентів),
* зібрати `meta` (latency, tokens),
* повернути у DAGI Router HTTP-відповідь.
---
## 6. INTEGRATION WITH DAGI ROUTER
### 6.1. З боку DAGI Router
При текстовій гілці (без мультимодальності):
```python
# dagi_router.py (схематично)
resp = http.post("http://agents-service:7002/agents/invoke", json={
"event": router_event_dict,
"options": {
"force_agent_id": None,
"allow_panel_mode": True,
"max_agents": 2
}
})
```
Router далі:
* бере `resp["replies"]`,
* конвертує в повідомлення для Gateway (Telegram/Web/Matrix),
* застосовує свої policy (наприклад, фільтрацію ненормативу, якщо треба).
---
## 7. NATS / PROJECT BUS INTEGRATION
Agents Service також:
1. Слухає ProjectBus:
* `project.<project_id>.chat.mixed` (через DAGI Router),
* `project.<project_id>.tasks` (можна робити автоматичну обробку задач).
2. Може публікувати події:
* `project.<project_id>.agents` (наприклад, "Helix взяв task t123"),
* `project.<project_id>.m2m.*` (M2M/R2D2 комунікація).
Це дозволяє:
* агентам працювати в командах,
* не тільки як chatbot, а як учасники mesh-процесів.
---
## 8. HEALTHCHECK & METRICS
### 8.1. Healthcheck
`GET /healthz`:
```json
{
"status": "ok",
"registry_loaded": true,
"mesh_directory_mode": "inprocess",
"uptime_seconds": 12345
}
```
### 8.2. Prometheus метрики
* `agents_invocations_total{agent_id, project_id, status}`
* `agents_throttled_total{agent_id}`
* `agents_silent_decisions_total{reason}`
* `agents_llm_latency_ms_bucket{agent_id, le=...}`
---
## 9. LOGGING
Кожен виклик `/agents/invoke` логувати:
* `event_id`, `source`, `chat.id`, `project_id`, `team_id`,
* кандидатів агентів + scores (debug-level),
* остаточно обраних агентів,
* статус: `ok` / `silent` / `throttled` / `error`,
* latency LLM.
Формат: JSON-лог для подальшого аналізу (ELK / Loki / Grafana).
---
## 10. TEST PLAN (SHORT)
Unit-тести (pytest):
1. `test_single_agent_selection()`
* один агент у команді, простий текст, немає throttling → відповідає.
2. `test_panel_mode_two_agents()`
* `reply_mode: panel`, `max_agents_per_message: 2`,
* питання, релевантне Helix і Guardian → відповідають двоє.
3. `test_silence_policy_mentions()`
* повідомлення без згадок і без ключових слів → `status: silent`.
4. `test_throttling_per_agent()`
* 4 виклики поспіль у межах 60 сек,
* `limit_per_minute=3`,
* 4-й → `status: throttled`.
5. `test_team_definition_loading()`
* агрегація команд з `team_definition.yaml`,
* мапінг на project_id.
---
## 11. SUMMARY
Agents Service (7002) — це:
* офіційний текстовий runtime DAGI,
* точка входу для Helion/Helix/Metamorph та інших текстових агентів,
* шар, який:
* "бачить" всю конфігурацію агентів (Registry),
* "бачить" живі інстанси (Mesh Directory),
* враховує TeamDefinition/ProjectBus,
* контролює поведінку агентів у чатах (silence/panel/throttle).
Після реалізації цього сервісу DAGI Router зможе:
* делегувати всю текстову логіку в єдиний, стандартизований компонент,
* який легко масштабувати між НОДА1/НОДА2 і далі.