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() при инициализации
204 lines
14 KiB
Markdown
204 lines
14 KiB
Markdown
# 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 = панель управления и мониторинга: │
|
||
│ • создать/удалить агента → автодеплой контейнера │
|
||
│ • видеть статус контейнеров в реальном времени │
|
||
│ • логи, метрики, история задач │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ ЗАВЕРШЕНО (фундамент)
|
||
|
||
- [x] Basic Dashboard layout (Mission Control theme)
|
||
- [x] Docker Stack integration (docker-stack.yml, docker-compose.yml)
|
||
- [x] Go Gateway — отдельный контейнер-оркестратор (:18789)
|
||
- [x] Web Panel — отдельный контейнер (:3000)
|
||
- [x] Overlay network `goclaw-net` (attachable)
|
||
- [x] MySQL shared DB (агенты, метрики, история)
|
||
- [x] tRPC API: agents CRUD, metrics, history
|
||
- [x] Go Gateway: LLM client (OpenAI-compatible), tool executor
|
||
- [x] Go Gateway: tool loop (shell_exec, file_read/write, http_request, docker_exec)
|
||
- [x] Go Gateway: DockerClient.CreateAgentServiceFull() — готов к деплою агентов
|
||
- [x] Nodes page: реальные данные из Docker API (Swarm nodes, containers)
|
||
- [x] Seed: 6 системных агентов в DB при старте
|
||
- [x] SSE streaming chat (Phase 18, remote branch)
|
||
- [x] Persistent chat sessions в DB (Phase 20, remote branch)
|
||
- [x] Workflows: визуальный конструктор граф-воркфлоу (remote branch)
|
||
- [x] 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)
|
||
- [x] Создать `gateway/cmd/agent-worker/main.go` — HTTP-сервер агента
|
||
- [x] Загружает конфиг из DB по `AGENT_ID` env var (model, systemPrompt, allowedTools)
|
||
- [x] `GET /health` — liveness/readiness probe
|
||
- [x] `GET /info` — конфиг агента (name, model, allowedTools)
|
||
- [x] `POST /task` — принять задачу от Orchestrator/другого агента (async, возвращает task_id)
|
||
- [x] `POST /chat` — синхронный чат (LLM loop с инструментами агента)
|
||
- [x] `GET /memory` — последние N сообщений из conversation history (sliding window)
|
||
- [x] Агент сам вызывает LLM через `LLM_BASE_URL` (не через Gateway)
|
||
- [x] 4 горутины-воркера на агента — параллельная обработка задач
|
||
- [x] Переиспользует `internal/llm`, `internal/db`, `internal/tools`
|
||
|
||
### A2: Task Queue внутри агента
|
||
- [x] In-memory очередь задач (buffered channel, depth=100)
|
||
- [x] 4 worker goroutines: берут задачи из очереди, выполняют LLM loop
|
||
- [x] `GET /tasks` + `GET /tasks/{id}` — список задач и статус конкретной
|
||
- [x] Callback URL: агент POST результат на `callback_url` когда задача готова
|
||
- [x] Timeout per task (из запроса, default 120s)
|
||
- [x] Recent ring buffer (последние 50 задач)
|
||
|
||
### A3: DB schema — agent container fields
|
||
- [x] Добавить в `drizzle/schema.ts`: `serviceName`, `servicePort`, `containerImage`, `containerStatus`
|
||
- [x] SQL migration `drizzle/migrations/0006_agent_container_fields.sql`
|
||
- [x] `gateway/internal/db/db.go`: `AgentConfig` + `AgentRow` с новыми полями
|
||
- [x] `UpdateContainerStatus()` — обновление статуса при деплое/остановке
|
||
- [x] `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+)
|
||
- [ ] Записать `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)
|
||
- [x] Обновить `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: если агент не запущен — информативное сообщение
|
||
- [x] `Executor.SetDatabase()` — инжекция DB для резолва адресов агентов
|
||
- [x] Orchestrator инжектирует DB в Executor при инициализации
|
||
|
||
### A6: Dockerfile.agent-worker
|
||
- [x] Создать `docker/Dockerfile.agent-worker` (multi-stage Go build)
|
||
- [x] Stage 1: `golang:1.23-alpine` — build agent-worker binary
|
||
- [x] Stage 2: `alpine:3.21` — минимальный runtime (ca-certificates, tzdata)
|
||
- [x] EXPOSE 8001 + HEALTHCHECK на /health
|
||
- [x] Агенты деплоятся динамически (не статический сервис в stack)
|
||
|
||
### A7: Тесты и верификация
|
||
- [x] `go build ./cmd/agent-worker/...` — компилируется (11MB binary)
|
||
- [x] `go build ./cmd/gateway/...` — не сломан (11MB binary)
|
||
- [x] `go build ./...` — все пакеты компилируются
|
||
- [x] 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:
|
||
```json
|
||
{ "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, go
|
||
- [ ] `goclaw-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-browser`
|
||
- ~~server/browser-agent.ts~~ → логика переезжает в отдельный Go binary
|
||
- ~~server/tool-builder.ts / server/agent-compiler.ts~~ → реализуются как агент-контейнеры (Phase E)
|
||
- ~~BrowserAgent.tsx / ToolBuilder.tsx / AgentCompiler.tsx как отдельные страницы~~ → управляются через стандартный `/agents` с типом
|
||
- ~~/skills страница~~ → заменяется `allowedTools` per-agent-container
|
||
- ~~server/web-research.ts~~ → реализуется как задача для агента-researcher через `delegate_to_agent`
|
||
- ~~server/chat-resilience.ts (Node.js retry)~~ → retry логика в Go agent-worker
|
||
- ~~Web Research Panel~~ → задача через Orchestrator chat
|
||
- ~~Phase 19 commit to Gitea (NW)~~ → история перезаписана целевой архитектурой
|