PHASE A COMPLETE: каждый агент теперь может жить в отдельном Docker Swarm контейнере как автономная единица.
- HTTP-сервер агента: GET /health, GET /info, POST /chat, POST /task, GET /tasks, GET /tasks/{id}, GET /memory
- Загружает конфиг из shared DB по AGENT_ID env var (model, systemPrompt, allowedTools)
- 4 горутины-воркера для параллельной обработки задач
- In-memory task queue (buffered channel, depth=100) + ring buffer последних 50 задач
- Callback URL: POST результата при завершении async задачи
- Sliding window памяти: загружает последние 20 сообщений из DB при каждом запросе
- Изолированные инструменты: агент получает только allowedTools из своей конфигурации
- Агент сам вызывает LLM напрямую через LLM_BASE_URL (не через Gateway)
- Graceful shutdown с таймаутом 15s
- 20 unit-тестов: все PASS
- Покрытие: инициализация, task queue, /health, /info, /task, /tasks, /memory, инструменты, lifecycle
- Multi-stage Go build: golang:1.23-alpine → alpine:3.21
- EXPOSE 8001, HEALTHCHECK на /health каждые 15s
- Агенты деплоятся динамически Swarm (не статический сервис в stack)
- Новые поля в таблице agents: serviceName, servicePort, containerImage, containerStatus
- SQL migration: drizzle/migrations/0006_agent_container_fields.sql
- AgentConfig + AgentRow: новые поля serviceName, servicePort, containerImage, containerStatus
- UpdateContainerStatus() — обновление статуса при деплое/остановке
- GetAgentHistory() — sliding window памяти агента из DB
- SaveHistory() — сохранение диалога агента в DB
- delegate_to_agent: реальный HTTP POST к контейнеру агента через overlay DNS
- sync: POST /chat (ждёт ответ)
- async: POST /task (возвращает task_id)
- fallback: если агент не запущен — информативное сообщение
- SetDatabase() — инжекция DB для резолва адресов живых агентов
- Orchestrator инжектирует DB в Executor через SetDatabase() при инициализации
14 KiB
14 KiB
GoClaw — TODO
Целевая архитектура
┌─────────────────────────────────────────────────────────────┐
│ Docker Swarm overlay net │
│ │
│ [Web Panel :3000] [Orchestrator :18789] [Agent-1 :8001] │
│ │ │ │ │
│ └────────────────────┴────────────────────┘ │
│ goclaw-net │
│ │
│ Каждый агент = отдельный Docker Swarm service: │
│ • своя LLM модель + systemPrompt из DB │
│ • своя память (conversation history в shared DB) │
│ • HTTP API: POST /task, POST /chat, GET /health, GET /mem │
│ • принимает параллельные задачи от любых источников │
│ • автодеплой при создании агента через Web Panel │
│ │
│ Orchestrator = мозг экосистемы: │
│ • маршрутизирует задачи между агентами │
│ • tool: delegate_to_agent → HTTP к agent-N:8001/task │
│ • знает topology: какой агент где живёт │
│ │
│ Web Panel = панель управления и мониторинга: │
│ • создать/удалить агента → автодеплой контейнера │
│ • видеть статус контейнеров в реальном времени │
│ • логи, метрики, история задач │
└─────────────────────────────────────────────────────────────┘
✅ ЗАВЕРШЕНО (фундамент)
- Basic Dashboard layout (Mission Control theme)
- Docker Stack integration (docker-stack.yml, docker-compose.yml)
- Go Gateway — отдельный контейнер-оркестратор (:18789)
- Web Panel — отдельный контейнер (:3000)
- Overlay network
goclaw-net(attachable) - MySQL shared DB (агенты, метрики, история)
- tRPC API: agents CRUD, metrics, history
- Go Gateway: LLM client (OpenAI-compatible), tool executor
- Go Gateway: tool loop (shell_exec, file_read/write, http_request, docker_exec)
- Go Gateway: DockerClient.CreateAgentServiceFull() — готов к деплою агентов
- Nodes page: реальные данные из Docker API (Swarm nodes, containers)
- Seed: 6 системных агентов в DB при старте
- SSE streaming chat (Phase 18, remote branch)
- Persistent chat sessions в DB (Phase 20, remote branch)
- Workflows: визуальный конструктор граф-воркфлоу (remote branch)
- Real Docker Swarm management: live nodes/services/tasks (Phase 21, remote branch)
🔥 PHASE A: Agent Worker Container (КРИТИЧЕСКИЙ ПУТЬ)
Цель: каждый агент живёт в своём контейнере с HTTP API. Orchestrator обращается к нему по имени в overlay сети.
A1: agent-worker binary (Go)
- Создать
gateway/cmd/agent-worker/main.go— HTTP-сервер агента - Загружает конфиг из DB по
AGENT_IDenv var (model, systemPrompt, allowedTools) GET /health— liveness/readiness probeGET /info— конфиг агента (name, model, allowedTools)POST /task— принять задачу от Orchestrator/другого агента (async, возвращает task_id)POST /chat— синхронный чат (LLM loop с инструментами агента)GET /memory— последние N сообщений из conversation history (sliding window)- Агент сам вызывает LLM через
LLM_BASE_URL(не через Gateway) - 4 горутины-воркера на агента — параллельная обработка задач
- Переиспользует
internal/llm,internal/db,internal/tools
A2: Task Queue внутри агента
- In-memory очередь задач (buffered channel, depth=100)
- 4 worker goroutines: берут задачи из очереди, выполняют LLM loop
GET /tasks+GET /tasks/{id}— список задач и статус конкретной- Callback URL: агент POST результат на
callback_urlкогда задача готова - Timeout per task (из запроса, default 120s)
- Recent ring buffer (последние 50 задач)
A3: DB schema — agent container fields
- Добавить в
drizzle/schema.ts:serviceName,servicePort,containerImage,containerStatus - SQL migration
drizzle/migrations/0006_agent_container_fields.sql gateway/internal/db/db.go:AgentConfig+AgentRowс новыми полямиUpdateContainerStatus()— обновление статуса при деплое/остановкеGetAgentHistory()+SaveHistory()— память агента в DB
A4: Auto-deploy при создании агента
- Gateway:
POST /api/agents— создаёт агента в DB + деплоит Swarm service CreateAgentServiceFull()с параметрами:- image:
goclaw-agent-worker:latest - name:
goclaw-agent-{agentId} - env:
AGENT_ID,DATABASE_URL,LLM_BASE_URL,LLM_API_KEY - network:
goclaw-net - port: назначить из пула (8001+)
- image:
- Записать
serviceName,servicePort,containerStatus=runningв DB - Gateway:
DELETE /api/agents/{id}— удалить Swarm service + запись в DB - Gateway:
POST /api/agents/{id}/scale— масштабировать реплики агента
A5: delegate_to_agent tool (Orchestrator → Agent HTTP)
- Обновить
gateway/internal/tools/executor.go:- tool
delegate_to_agent: args:{agentId, task, callbackUrl?, async?} - Получить
serviceName+servicePortагента из DB - HTTP POST к
http://goclaw-agent-{id}:{port}/chat(sync) или/task(async) - Fallback: если агент не запущен — информативное сообщение
- tool
Executor.SetDatabase()— инжекция DB для резолва адресов агентов- Orchestrator инжектирует DB в Executor при инициализации
A6: Dockerfile.agent-worker
- Создать
docker/Dockerfile.agent-worker(multi-stage Go build) - Stage 1:
golang:1.23-alpine— build agent-worker binary - Stage 2:
alpine:3.21— минимальный runtime (ca-certificates, tzdata) - EXPOSE 8001 + HEALTHCHECK на /health
- Агенты деплоятся динамически (не статический сервис в stack)
A7: Тесты и верификация
go build ./cmd/agent-worker/...— компилируется (11MB binary)go build ./cmd/gateway/...— не сломан (11MB binary)go build ./...— все пакеты компилируются- 20 unit-тестов: /health, /task, /tasks, /memory, task queue, tools, lifecycle — все PASS
- Docker build:
docker build -f docker/Dockerfile.agent-worker -t goclaw-agent-worker .(нужен Docker daemon) - Интеграционный тест: Gateway
delegate_to_agent→ agent-worker/task(нужна живая DB)
🟡 PHASE B: Web Panel — управление живыми агентами
Цель: Web Panel показывает реальный статус контейнеров и позволяет деплоить/останавливать.
/agentsстраница: колонкаContainer Status(running/stopped/deploying/error)/agentsстраница: кнопкаDeploy— вызываетPOST /api/agents/{id}/deploy/agentsстраница: кнопкаStop/Scaleдля запущенных агентов/agentsстраница: live polling статуса контейнера (10s)- tRPC:
agents.deploy,agents.stop,agents.scale→ Gateway REST - Dashboard: topology карта — агенты как узлы, стрелки = делегирование задач
/agents/{id}detail: вкладкаTasks— активные задачи агента в реальном времени/agents/{id}detail: вкладкаMemory— последние N сообщений агента
🟡 PHASE C: Межагентная коммуникация
Цель: агенты могут обращаться друг к другу параллельно, с разных мест.
- Стандарт сообщения agent-to-agent:
{ "task_id": "uuid", "from_agent_id": 1, "task": "...", "callback_url": "http://...", "priority": "normal", "timeout_secs": 120 } - Service Discovery: агент получает список других агентов из DB (GET /api/agents)
- Orchestrator: параллельный fanout — отправить задачу нескольким агентам одновременно
- Rate limiting: агент принимает не более N параллельных задач (configurable)
- Dead letter: если агент недоступен — Orchestrator автоматически рестартует сервис
🟡 PHASE D: Память агента
Цель: каждый агент имеет изолированную персистентную память.
- Sliding window: агент загружает последние 20 сообщений своей истории при каждом запросе
- История привязана к
agentId(уже естьagentHistoryв DB) GET /memory?limit=20— endpoint агента отдаёт свою историю- Опционально: summary compression — если история > N токенов, сжать через LLM
🟢 PHASE E: Специализированные образы агентов
Цель: разные типы агентов с разными возможностями.
goclaw-agent-browser— образ с Chromium + Puppeteer (или playwright-go)goclaw-agent-coder— образ с git, node, python, gogoclaw-agent-researcher— образ с curl + базовый HTTP scraping- Agent Compiler: из ТЗ → config в DB → auto-deploy нужного образа
- Tool Builder: динамическая регистрация инструментов через API агента
🟢 PHASE F: Observability & Production
- Centralized logging: агенты пишут структурированные логи в shared volume / Loki
- Metrics endpoint:
GET /metrics(Prometheus-compatible) на каждом агенте - Alert: Orchestrator получает webhook при падении агента (Docker healthcheck)
- Traefik reverse proxy: раскомментировать в docker-stack.yml + TLS
- Auth: JWT для межагентного API (если выйдет за периметр Swarm сети)
- Go unit tests:
gateway/internal/tools/executor_test.go - Go integration test: Orchestrator chat loop end-to-end
🚫 ОТБРОШЕНО (не соответствует архитектуре)
Эти задачи противоречат концепции "агент = контейнер" или дублируют существующее.
Browser Agent как Puppeteer в Node.js→ заменяется специализированным образомgoclaw-agent-browserserver/browser-agent.ts→ логика переезжает в отдельный Go binaryserver/tool-builder.ts / server/agent-compiler.ts→ реализуются как агент-контейнеры (Phase E)BrowserAgent.tsx / ToolBuilder.tsx / AgentCompiler.tsx как отдельные страницы→ управляются через стандартный/agentsс типом/skills страница→ заменяетсяallowedToolsper-agent-containerserver/web-research.ts→ реализуется как задача для агента-researcher черезdelegate_to_agentserver/chat-resilience.ts (Node.js retry)→ retry логика в Go agent-workerWeb Research Panel→ задача через Orchestrator chatPhase 19 commit to Gitea (NW)→ история перезаписана целевой архитектурой