Skip to content

Implementation

Build-prompt для AI-агента-кодера: що саме реалізувати для підсистеми Worker, у якому порядку й проти яких контрактів. Передай блок нижче агенту; секції після нього — це референс, якого він має триматися.

Ця сторінка — agent-prompt

Кожна секція цих доків має сторінку Implementation — точну, copy-paste специфікацію задачі, яку виконує агент. Спершу прочитай Deploy, Use і Destroy; вони — джерело істини, на яке вказує цей prompt.

Prompt

text
ROLE: You are implementing the Worker subsystem of Agentfy.ai 2.0 (NestJS + Prisma + CleanSlice).

GOAL: An agent's "hands" — an on-demand worker (bash / fs / browser) that runs one obligation as an
ephemeral k8s Job, streams progress back to the brain over a WebSocket, persists outputs, and
disappears. The brain (api) keeps the LLM loop; the worker has NO LLM.

DELIVERABLES
1) `worker` app (the worker image): an agent-less, LLM-less **MCP server**.
   - Embeds an MCP server; dials CONTROL_URL over a WebSocket (reverse transport) and runs the MCP
     `initialize` handshake with WORKER_TOKEN, then signals `ready`.
   - Advertises via `tools/list` ONLY the TOOL_ALLOWLIST tools: exec, process_exec, file, unzip,
     browser, browser_screenshot, browser_play, http, web_fetch, pdf_analyze. Executes `tools/call`.
   - Sticky session state: cwd, browser context (Playwright, per-tenant --user-data-dir), env,
     background procs — the MCP server instance is stateful for the session.
   - Large outputs → object storage via system/file, returned as an MCP `resource_link` (never inline).
   - MCP `sampling` DISABLED. Heartbeats; self-terminate on idle-timeout or lost control connection.
2) `api` → `runtime/worker` slice (the manager / dispatcher): sessions · k8s (manifest builder +
   create/delete) · browser (in-pod Chromium lifecycle) · idle (reaper) · profiles.
3) `api` → `runtime/task` slice (the queue): BullMQ on Redis; standard, delayed, repeatable jobs.

CONTRACTS: implement exactly the schemas, profiles, frames and job kinds in the reference below.
Follow CleanSlice conventions (gateway pattern, `I`-prefixed DI tokens, singular slice folders, `#`
aliases, no `any`).

SECURITY (non-negotiable): no long-lived secrets in the pod; short-lived per-session token only; KEK
never leaves api; NetworkPolicy default-deny + egress allowlist; read-only root fs, drop ALL caps,
non-root, automountServiceAccountToken:false; activeDeadlineSeconds hard cap; audit every session.

ACCEPTANCE: see the checklist at the bottom. Start at the v0.3 MVP scope.

Референс — контракти до реалізації

Рядок сесії

AgentRuntimeSession { agentId, taskId?, status, runtimeType, cpu/mem/storageLimit, ttlSeconds, k8sJobName, namespace, workerUrl, logsUrl, startedAt, lastActivityAt, stoppedAt } зі станами pending → starting → running → idle → stopping → stopped (+ failed). Див. Destroy.

Runtime-профілі

Каталог пресетів → RuntimeProfile { mode, cpu, mem, storage, maxExecSeconds, idleSeconds } для None / Light / Browser / Heavy / Warm. Збирач маніфесту читає його. Див. Deploy → режими рантайму.

Control-канал = MCP (канал 3)

MCP поверх ініційованого worker'ом WebSocket (реверсний транспорт). Worker — це MCP сервер, worker-gateway api — це MCP host/client; MCP session id ↔ наш sessionId.

jsonc
{ "method": "tools/list" }                                                      // host → worker (discover, allowlist-gated)
{ "method": "tools/call", "params": { "name": "browser.click",
    "arguments": { "selector": "#buy" } } }                                     // host → worker
{ "method": "notifications/progress", "params": { "progressToken": "c12",
    "message": "navigated to /cart" } }                                         // worker → host

Плюс handshake initialize (автентифікація через WORKER_TOKEN), ready, heartbeat, release. MCP sampling вимкнено. Канал у загальних рисах описано в Use → протокол; нормативний контракт дроту — хто шле кожен кадр, що вважається відповіддю, що відбувається при мовчанні і правило версій — це Канал інструментів, і реалізовувати треба його.

Задачі черги

task dispatch (standard) · idle timer (delayed) · scheduled (repeatable) · ingestion (budgeted). Споживач = dispatcher, який створює k8s Job. Див. Deploy → черга.

Bootstrap-env

SESSION_ID, CONTROL_URL, WORKER_TOKEN_FILE, TOOL_ALLOWLIST, storage-scope.

Перепустка — це файл, а не значення: WORKER_TOKEN_FILE називає шлях, за яким змонтовано projected Secret (/var/run/agentfy/token), і воркер читає його звідти. WORKER_TOKEN в оточенні лишається — щоб запускати воркер поза Kubernetes, — а виставити обидві змінні не можна: маніфест, наполовину переведений на том, інакше тихо лишив би перепустку в оточенні (006 T104).

MAX_EXEC_SECONDS та IDLE_SECONDS несуть два терміни цієї сесії, просто з її профілю. Воркер зводить перший таймер раніше, ніж з'являється керівний канал, тож без них він відкочувався до таблиці профілю Light — 900 с і 90 с — на будь-якому профілі: важкій сесії казали чверть тієї години, яку вона має, а збирач забирав под на тридцять секунд раніше, ніж под очікував (AGNT2-237). Кадр initialize несе ту саму пару, і воркер слухається меншого з двох — тому одним кадром це було не полагодити: 900 менше за 3600. Обидві змінні необов'язкові: їхня відсутність означає таблицю Light, на що спирається кожен стенд, який запускає воркер руками, — але значення, що стоїть і не читається, відхиляється: термін, який тихо став 900 с, не відрізнити від терміну, який таким і задумали.

Впорядковані задачі

  1. v0.3 MVPruntime/task (dispatch + delayed idle-timer) · runtime/worker (sessions, k8s create/delete, Light-профіль) · образ worker (MCP-сервер: initialize + tools/list + exec/file) · реверсний WS MCP-транспорт + реєстрація на боці host'а · idle-reaper. Доводить message → Job → MCP attach → tools/call → result → reap.
  2. + Browser — in-pod Chromium, browser*-тули, Browser-профіль.
  3. + Конкурентність і надійність — per-team-ліміти, retries/backoff + dead-letter.
  4. + Heavy / Warm — профілі й розміщення на нодах.
  5. + Scheduled — repeatable-задачі для agent/cron.

Критерії приймання

  • [ ] Турн без тулів ніколи нічого не кладе в чергу; турн із тулами кладе раз для провіжену.
  • [ ] Одна MCP-сесія обслуговує багато tools/call через єдиний реверсний WebSocket (sticky cwd + контекст браузера).
  • [ ] Worker (MCP-сервер) дзвонить назад і автентифікується короткоживучим токеном на initialize; жодних інших секретів у поді; MCP sampling вимкнено.
  • [ ] Control-трафік ніколи не з'являється в чаті користувача; лише курований статус/артефакти.
  • [ ] Idle → reaped після вікна профілю; виходи синхронізовані в system/file до видалення Job.
  • [ ] activeDeadlineSeconds і стелі max-idle забезпечені; кожна сесія в аудиті.

Дивіться також