Files
microdao-daarion/docs/tasks/PHASE3_MASTER_TASK.md
Apple fca48b3eb0 feat(node2): Complete NODE2 setup - guardian, agents, swapper models
- Node-guardian running on MacBook and updating metrics
- NODE2 agents (Atlas, Greeter, Oracle, Builder Bot) assigned to node-2-macbook-m4max
- Swapper models displaying correctly (8 models)
- DAGI Router agents showing with correct status (3 active, 1 stale)
- Router health check using node_cache for remote nodes
2025-12-02 07:07:58 -08:00

14 KiB
Raw Blame History

TASK: PHASE 3 — LLM PROXY + MEMORY ORCHESTRATOR + TOOLCORE

Goal: Зробити агентів DAARION по-справжньому розумними та інструментальними:

  • єдиний LLM Proxy з підтримкою кількох провайдерів і локальних моделей;
  • Memory Orchestrator, який дає єдиний API для памʼяті агентів;
  • Toolcore — реєстр інструментів і безпечне виконання tools для агентів.

PHASE 3 = інфраструктура мислення й дії для Agent Runtime.

Existing (assume from Phase 12):

  • messaging-service, matrix-gateway, Messenger UI.
  • agent-filter, DAGI Router (router.invoke.agent).
  • agent-runtime (використовує /internal/llm/proxy та /internal/agent-memory/*, але поки можуть бути stubs).
  • базова БД (users, microdaos, agents, channels, messages, etc.).
  • NATS JetStream, PostgreSQL, docker-compose.

Deliverables:

  1. services/llm-proxy/ — LLM Router + Providers + Logging.
  2. services/memory-orchestrator/ — єдиний API для памʼяті агентів.
  3. services/toolcore/ — registry + execution engine для tools.
  4. Інтеграція з agent-runtime.
  5. Оновлення docker-compose та docs.

1) SERVICE: LLM PROXY (services/llm-proxy)

Create folder:

services/llm-proxy/
  main.py
  models.py
  router.py
  providers/
    __init__.py
    openai_provider.py
    deepseek_provider.py
    local_provider.py
  config.yaml
  middlewares.py
  logging_middleware.py
  Dockerfile
  requirements.txt
  README.md

1.1 API

Base URL (internal-only):

  • POST /internal/llm/proxy

Request (v1):

{
  "model": "gpt-4.1-mini",
  "messages": [
    { "role": "system", "content": "..." },
    { "role": "user", "content": "..." }
  ],
  "metadata": {
    "agent_id": "agent:sofia",
    "microdao_id": "microdao:7",
    "channel_id": "..."
  }
}

Response:

{
  "content": "текст відповіді",
  "usage": {
    "prompt_tokens": 123,
    "completion_tokens": 45,
    "total_tokens": 168
  },
  "provider": "openai",
  "model_resolved": "gpt-4.1-mini"
}

Optional (stub for later):

  • /internal/llm/batch
  • /internal/llm/stream (можна залишити TODO)

1.2 Model routing (router.py)

Створити модуль:

def route_model(logical_model: str) -> ProviderConfig:
    # Читає зі структури в config.yaml
    # Напр.:
    #  - gpt-4.1-mini → OpenAI (gpt-4.1-mini)
    #  - deepseek-r1 → DeepSeek API
    #  - dagi-local-8b → Local provider (Ollama / vllm)

config.yaml (приклад):

providers:
  openai:
    base_url: "https://api.openai.com/v1"
    api_key_env: "OPENAI_API_KEY"
  deepseek:
    base_url: "https://api.deepseek.com/v1"
    api_key_env: "DEEPSEEK_API_KEY"
  local:
    base_url: "http://local-llm:8000"

models:
  gpt-4.1-mini:
    provider: "openai"
    name: "gpt-4.1-mini"
  deepseek-r1:
    provider: "deepseek"
    name: "deepseek-r1"
  dagi-local-8b:
    provider: "local"
    name: "qwen2.5-8b-instruct"

1.3 Providers (providers/*.py)

Кожен провайдер:

class BaseProvider(Protocol):
    async def chat(self, messages: list[ChatMessage], model_name: str, **kwargs) -> LLMResponse: ...

Файли:

  • providers/openai_provider.py
  • providers/deepseek_provider.py
  • providers/local_provider.py

Вони:

  • отримують normalized messages,
  • викликають відповідний API/endpoint,
  • повертають LLMResponse (контент + usage).

Local provider:

  • для Phase 3 можна зробити простий HTTP-запит до існуючого локального сервісу (Ollama/vLLM), або stub.

1.4 Logging & limits (middlewares.py, logging_middleware.py)

Добавити:

  • простий rate limit per-agent (стабово, через in-memory або Redis stub).
  • логування викликів:
    • agent_id, microdao_id, model, latency, tokens.
  • TODO hooks для Billing/Usage Engine (на майбутнє).

1.5 README.md

Описати:

  • підтримувані моделі та мапінг,
  • як додати нового провайдера,
  • як викликати /internal/llm/proxy з інших сервісів (особливо agent-runtime).

2) SERVICE: MEMORY ORCHESTRATOR (services/memory-orchestrator)

Goal: Єдиний API для роботи з памʼяттю:

  • short-term (канальний контекст / event log),
  • mid-term (agent memory / RAG embedding store),
  • long-term (knowledge base, docs, roadmaps).

Create folder:

services/memory-orchestrator/
  main.py
  models.py
  router.py
  backends/
    __init__.py
    short_term_pg.py
    vector_store_pg.py
    kb_filesystem.py
  embedding_client.py
  config.yaml
  Dockerfile
  requirements.txt
  README.md

2.1 API

Base URL:

  • POST /internal/agent-memory/query
  • POST /internal/agent-memory/store
  • POST /internal/agent-memory/summarize (optional v1)

Request /query:

{
  "agent_id": "agent:sofia",
  "microdao_id": "microdao:7",
  "channel_id": "optional",
  "query": "коротко, які були останні зміни в цьому microDAO?",
  "limit": 5
}

Response:

{
  "items": [
    {
      "id": "mem-123",
      "kind": "conversation | kb | task | dao-event",
      "score": 0.87,
      "content": "Текст фрагменту памʼяті",
      "meta": {
        "source": "channel:...",
        "timestamp": "..."
      }
    }
  ]
}

Request /store:

{
  "agent_id": "agent:sofia",
  "microdao_id": "microdao:7",
  "channel_id": "optional",
  "kind": "conversation | kb | task | dao-event",
  "content": {
    "user_message": "...",
    "agent_reply": "..."
  }
}

Response:

{ "ok": true, "id": "mem-123" }

2.2 Backends

backends/short_term_pg.py:

  • зберігає сирі events (або посилання на messages) в PostgreSQL, якщо треба окремо від messenger.

backends/vector_store_pg.py:

  • використовує embeddings (через embedding_client.py) і зберігає в таблиці:
    agent_memories (id, agent_id, microdao_id, embedding vector, content, meta)
    
  • простий cosine similarity пошук.

backends/kb_filesystem.py:

  • stub для long-term знань (roadmaps, docs), можна залишити TODO.

2.3 Embedding client (embedding_client.py)

  • Простий клієнт до існуючої embedding-моделі (наприклад, BGE-M3 чи інша) через /internal/embedding/proxy або безпосередньо.
  • Якщо embedding-сервіс не описаний — зробити stub + TODO.

2.4 Integration points

agent-runtime:

  • замінити прямі виклики agent-memory на:
    • POST /internal/agent-memory/query
    • POST /internal/agent-memory/store

Надалі можна буде підʼєднати:

  • microDAO knowledge,
  • DAO events,
  • roadmaps.

3) SERVICE: TOOLCORE (services/toolcore)

Goal: Єдина точка для:

  • реєстрації tools (інструментів агентів),
  • перевірки дозволів,
  • виконання tools та повернення результату агенту.

Create folder:

services/toolcore/
  main.py
  models.py
  router.py
  registry.py
  executors/
    __init__.py
    http_executor.py
    python_executor.py (optional)
  config.yaml
  Dockerfile
  requirements.txt
  README.md

3.1 Data model

models.py:

class ToolDefinition(BaseModel):
    id: str                # "projects.list"
    name: str
    description: str
    input_schema: dict     # JSON Schema
    output_schema: dict    # JSON Schema
    executor: Literal["http", "python"]
    target: str            # HTTP URL or python path
    allowed_agents: list[str] | None

class ToolCallRequest(BaseModel):
    tool_id: str
    agent_id: str
    microdao_id: str
    args: dict
    context: dict | None = None

class ToolCallResult(BaseModel):
    ok: bool
    result: dict | None = None
    error: str | None = None

3.2 API

HTTP (internal):

  • GET /internal/tools → список доступних tools

  • POST /internal/tools/call Body: ToolCallRequest Behavior:

    • перевірити, чи agent_id має право на tool_id (allowed_agents).
    • знайти ToolDefinition.
    • виконати через відповідний executor.
    • повернути ToolCallResult.

3.3 Executors

executors/http_executor.py:

  • викликає target як HTTP endpoint (POST з args + context).
  • хендлінг помилок та таймаутів.

executors/python_executor.py (optional):

  • allows direct call of internal python functions (у v1 можна залишити TODO або мінімальний stub).

3.4 Registry (registry.py)

Початок — з config.yaml (static registry):

config.yaml:

tools:
  - id: "projects.list"
    name: "List projects"
    description: "Повертає список проєктів microDAO."
    input_schema:
      type: "object"
      properties:
        microdao_id: { type: "string" }
      required: ["microdao_id"]
    output_schema:
      type: "array"
      items: { type: "object" }
    executor: "http"
    target: "http://projects-service:8000/internal/tools/projects.list"
    allowed_agents: ["agent:sofia", "agent:pm", "agent:cto"]

Registry API:

  • load from config.yaml at startup
  • later можна зробити DB-backed registry.

3.5 NATS (optional для Phase 3)

Можна додати:

  • subject: tool.request
  • subject: tool.response

Але для Phase 3 достатньо HTTP-контракту, який викликає agent-runtime.


4) INTEGRATION: agent-runtime + LLM Proxy + Memory + Toolcore

Update agent-runtime:

4.1 Використовувати LLM Proxy

Замість прямого виклику будь-яких LLM:

  • завжди викликати:
    POST /internal/llm/proxy
    {
      "model": "<logical model from agent blueprint>",
      "messages": [...],
      "metadata": {
        "agent_id": ...,
        "microdao_id": ...,
        "channel_id": ...
      }
    }
    

4.2 Використовувати Memory Orchestrator

При channel_message:

  • контекст: GET /internal/messaging/channels/{channelId}/messages?limit=50
  • памʼять: POST /internal/agent-memory/query
  • запис: POST /internal/agent-memory/store після відповіді.

4.3 Виклик tools

Якщо в blueprint агента передбачені tools:

  • парсити вихід LLM (JSON/structured) або через simple convention (наприклад, спеціальний формат "TOOL: projects.list {...}").
  • для кожного tool call:
    POST /internal/tools/call
    {
      "tool_id": "...",
      "agent_id": "...",
      "microdao_id": "...",
      "args": {...}
    }
    
  • включати результати tools у наступний LLM виклик як контекст.
  • (На Phase 3 можна реалізувати один-два прості tools: projects.list, followups.create.)

5) DOCKER + DOCS

5.1 docker-compose

Додати new services:

  • llm-proxy
  • memory-orchestrator
  • toolcore

Переконатися, що:

  • вони в тій же мережі, що agent-runtime, messaging-service, NATS, DB;
  • є healthcheck-и (GET /health).

5.2 Документація

Додати/оновити:

  • docs/LLM_PROXY_SPEC.md
  • docs/MEMORY_ORCHESTRATOR_SPEC.md
  • docs/TOOLCORE_SPEC.md
  • оновити docs/INDEX.md (додати посилання на ці три сервіси).
  • в PHASE2_READY.md або окремому PHASE3_READY.md описати нову архітектуру agent pipeline.

6) ACCEPTANCE CRITERIA

1) LLM Proxy:

  • /internal/llm/proxy приймає запити, повертає відповіді.
  • Принаймні 2 логічні моделі працюють (наприклад, один remote, один local.stub).
  • Логуються виклики per-agent.

2) Memory Orchestrator:

  • /internal/agent-memory/query повертає релевантні фрагменти (можна з простим vector search або stub).
  • /internal/agent-memory/store зберігає нові entries.
  • agent-runtime успішно використовує його при відповіді.

3) Toolcore:

  • /internal/tools повертає список інструментів.
  • /internal/tools/call виконує хоча б один реальний tool (HTTP executor).
  • agent-runtime може викликати хоча б один tool впродовж свого pipeline.

4) End-to-end:

  • Агент у Messenger:
    • читає контекст (messages + memory),
    • викликає LLM через LLM Proxy,
    • за потреби викликає tool через Toolcore,
    • повертає відповідь у канал.
  • Для одного демо-агента (наприклад, Sofia-Prime) цей ланцюг стабільно працює.

END OF TASK

Estimated Time: 6-8 weeks
Priority: High
Dependencies: Phase 2 complete
Version: 1.0.0
Date: 2025-11-24