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

12 KiB
Raw Permalink Blame History

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

[ 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-змінні:

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:

{
  "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 (успішний сценарій):

{
  "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 (ніхто не має відповідати):

{
  "status": "silent",
  "reason": "no_agent_or_policy",
  "context": {
    "project_id": "proj-daariandao",
    "team_id": "team-daariandao-core"
  }
}

Response (throttling):

{
  "status": "throttled",
  "reason": "rate_limit",
  "agent_id": "ag_helion"
}

4.2. GET /agents/registry

Повертає список агентів (тільки для адміністраторів / системних агентів):

Response:

{
  "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 (видно інстанси):

{
  "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

При текстовій гілці (без мультимодальності):

# 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:

{
  "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 і далі.