Implementation
Build-промпт для AI-кодинг-агента: что именно реализовать для подсистемы Worker, в каком порядке и против каких контрактов. Передай блок ниже агенту; разделы после него — референс, которому он должен следовать.
Эта страница — промпт для агента
У каждого раздела этих доков есть страница Implementation — точная, copy-paste спека задачи, которую агент выполняет. Сначала прочитай Deploy, Use и Destroy; они — источник истины, на который указывает этот промпт.
Промпт
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 поверх WebSocket'а, инициированного worker'ом (обратный транспорт). Worker — это MCP-сервер, worker-gateway в api — это MCP host/client; MCP session id ↔ наш sessionId.
{ "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 (auth через 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, скоуп хранилища.
Пропуск — это файл, а не значение: 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 с, неотличим от срока, который таким и задумали.
Упорядоченные задачи
- v0.3 MVP —
runtime/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. - + Browser — Chromium in-pod, тулы
browser*, Browser-профиль. - + Конкурентность и надёжность — per-team-лимиты, retries/backoff + dead-letter.
- + Heavy / Warm — профили и размещение по нодам.
- + Scheduled — repeatable-джобы для
agent/cron.
Критерии приёмки
- [ ] Турн без тулов никогда ничего не ставит в очередь; турн с тулами ставит один раз для provision.
- [ ] Одна MCP-сессия обслуживает много вызовов
tools/callпо одному обратному WebSocket (sticky cwd + контекст браузера). - [ ] Worker (MCP-сервер) дозванивается назад и аутентифицируется короткоживущим токеном на
initialize; никаких других секретов в поде; MCPsamplingвыключен. - [ ] Control-трафик никогда не появляется в пользовательском чате; только курируемые статусы/артефакты.
- [ ] Idle → reaped по окну профиля; выходные данные синхронизированы в
system/fileдо удаления Job. - [ ]
activeDeadlineSecondsи потолки max-idle принудительно соблюдаются; каждая сессия в аудите.
См. также
- Deploy · Use · Destroy — источник истины.
- Канал инструментов — контракт control-канала целиком, написанный один раз.
- Слоистые слайсы — где сидят
runtime/workerиruntime/task. - Conventions — правила CleanSlice, которым агент должен следовать.