11 KiB
11 KiB
date, type, tags
| date | type | tags | ||||||
|---|---|---|---|---|---|---|---|---|
| 2026-06-08 | decision |
|
SwarmClaw — оркестратор-надстройка над openclaw (LXC 135)
Контекст
Олег искал «аналог openclaw — оркестратор + удобный + самообучение». По ходу выяснилось:
- У openclaw самообучение уже работает (Dreaming, embeddings ready, recall с concept-tagging + spaced repetition — см. правку openclaw). Менять движок не нужно.
- SwarmClaw (github.com/swarmclawai/swarmclaw) — это не замена, а control-plane НАД openclaw: рой агентов, делегирование, расписания, дашборд, и подключение существующих openclaw-gateway. Ровно «оркестратор» из запроса, без миграции стека.
Решение: поставить SwarmClaw на Proxmox (не Mac-app — тот умирает с ноутом) как постоянный дирижёр над Антошкой.
Где живёт
| Параметр | Значение |
|---|---|
| Proxmox LXC | 135 (hostname swarmclaw) |
| IP | 10.0.0.135/24, gw 10.0.0.1 |
| ОС | Debian 12, unprivileged + nesting=1,keyctl=1 |
| Ресурсы | 2 vCPU / 4 GB RAM / 16 GB (rootfs на work) |
| Рантайм | Docker 29.5 + compose, образ ghcr.io/swarmclawai/swarmclaw:latest |
| Каталог | /opt/swarmclaw (репо), данные volume ./data:/app/data |
| Доступ | pct exec 135 -- bash; dashboard http://10.0.0.135:3456 |
Доступ к UI/API
- URL:
http://10.0.0.135:3456(LAN/NetBird), слушает0.0.0.0:3456-3457. - ACCESS_KEY:
4613e7d05f51229a96d7b1a0dd34b24e— он же cookiesc_authдля API. - Auth:
POST /api/auth {"key":"..."}→ cookie, либо headerCookie: sc_auth=<KEY>.getAccessKey()=process.env.ACCESS_KEY,validateAccessKeyсравнивает строкой.
Что настроено
- Провайдер OmniRoute (
custom, OpenAI-compatible):baseUrl=http://10.0.0.179:20128/v1,requiresApiKey:false(внутренний, отдаёт каталог без ключа).- Каталог 58 моделей; инференс
cc/claude-opus-4-8подтверждён (stream chat.completions).
- Агент «Dirizhyor» (id
0d388a87) — provideromniroute, modelcc/claude-opus-4-8. - openclaw-gateway как control-plane:
- credential
cred_62caf5d0f0de(provideropenclaw, зашифрованный gateway-token). - gateway profile
gateway-0eaf65b0«Antoshka (openclaw 137)», endpointhttp://10.0.0.239:18789,isDefault:true. - openclaw gateway token:
20bfbdfed25b87b211a6faa60db3ab8fac75fb5100958ac8(gateway.auth.mode=tokenна LXC 137). - device спарен и approved на openclaw (
openclaw devices→ 10.0.0.135,operator.admin). - connect
ok:true.
- credential
Грабли (важно для будущего)
- ACCESS_KEY жил только в
/app/.env.localвнутри контейнера (не в volume). Пересоздание/обновление образа → новый ключ → запертый вход. Фикс: скопировалACCESS_KEY(+CREDENTIAL_SECRETесли будет) в хостовый/opt/swarmclaw/.env.local(онenv_fileв compose) → ключ постоянен через пересоздания.CREDENTIAL_SECRETдополнительно лежит в volumedata/credential-secret. - Auth rate-limit: 5 неудачных попыток с IP → лок 15 мин (
authRateLimitMap, in-memory). Перебор форматов auth (Bearer/x-api-key — оба неверные) триггерит. Правильный auth — только cookiesc_auth. Сброс лока —docker compose up -d --force-recreate(in-memory обнуляется, ключ из env_file сохраняется). - Подключение openclaw требует approve device-pairing. SwarmClaw
manualConnectхардкодитuseDeviceAuth=true(протокол v4,auth:{token}+ device-signature). openclaw в token-mode создаёт pending pairing → пока не сделатьopenclaw devices approve <requestId>на LXC 137, connect молча{"ok":false}. Token-only handshake (proto4,auth.token, scopesoperator.admin) проверен рабочим. После approve — connectok:true, device в Paired. /api/openclaw/doctor→spawn openclaw ENOENT— в контейнере нет bundledopenclawCLI; связь идёт по WS, не через CLI. Безвредно.- DNS-FakeIP не словили (в отличие от LXC 137): github/docker.com резолвятся честно через
1.1.1.1/8.8.8.8даже без NetBird на 135. NetBird не ставил. - Локаль в LXC не настроена (
locale: Cannot set LC_*) — косметика, при желанииlocale-gen en_US.UTF-8. - Агент отвечал
Error: Missing credentials … OPENAI_API_KEYхотя OmniRoute ключ не требует. Причина: OpenAI-совместимый клиент внутри SwarmClaw отказывается слать запрос без непустогоapiKey. Фикс: создать dummy-credential (POST /api/credentials {provider:omniroute, apiKey:"omniroute-noauth-dummy"}→cred_0d2feda42f7b) и привязать к провайдеру (requiresApiKey:true+credentialId) И к агенту (PUT /api/agents/<id>— PATCH даёт 405). OmniRoute ключ игнорирует. После — агент Dirizhyor отвечает на Opus 4.8 (проверено: «работает», + сам диагностировал второй агент через tools). - UI «No agents yet» + циклический логин в Chrome = браузер держал старый JS-бандл (в логах
Failed to find Server Action), ломались Server Actions (вход и загрузка). Сервер исправен (REST API через NPM HTTPS отдаёт auth+agents). Лечится чистым браузером (Yandex/инкогнито сработали сразу) или Clear site data в Chrome. SW/PWA нет, контейнер стабилен (0 рестартов). - Дефолтный агент Assistant/«Ассистент» упорно падал
Claude CLI not found. Корень в коде:agent-runtime-config.ts→provider = seed.provider || 'claude-cli'(хардкод-фоллбек). У default слетал/пустел provider → фоллбек на claude-cli (в контейнере нет).POST /api/agentsне даёт задать фиксированныйid,PUT /api/agents/defaultдля пустого не помог. Фикс: прямойINSERT OR REPLACE INTO agentsвdata/swarmclaw.db— id=default, data = копия Dirizhyor (omniroute/opus/cred). App подхватывает без рестарта (loadAgents читает свежо). Теперь оба агента на OmniRoute/Opus. - «Session not found» при тесте через curl — нельзя слать в произвольный
agent-chat-*ID; сессия создаётся UI/отдельно. Не баг агента — артефакт диагностики. Реальные сессии (созданные в UI) работают (completed). - Gateway health «не обновлялась 30 мин / статус неизвестно» — у RPC
/api/openclaw/gatewayесть только connect/disconnect/reload-mode; health-поле профиля (status,lastCheckedAt) обновляет фоновый probe, не RPC.gateway.connect{profileId}→ok:true(связь рабочая), но индикатор остаётсяunknown. Косметика мониторинга, на работу не влияет.
Схема API (для будущих правок headless)
POST /api/providers→{id,name,baseUrl,models[],requiresApiKey,isEnabled}(type всегдаcustom), хранит JSON в таблицеprovider_configs.POST /api/agents→ zodAgentCreateSchema; обяз.name,provider;ollamaModeтолькоlocal|cloud|null(неoff).POST /api/credentials→{provider,name,apiKey}.POST /api/gateways→{name,endpoint,credentialId,isDefault}.POST /api/openclaw/gateway→ RPC{method:"gateway.connect",params:{url,token}|{profileId}}.- БД:
/opt/swarmclaw/data/swarmclaw.db(sqlite, таблицы*_configs/profiles/agents/credentialsкакid+data JSON),memory.db,logs.db.
Домен swarm.dttb.ru (2026-06-08)
- NPM proxy host #32 (LXC 103, 10.0.0.195):
swarm.dttb.ru→10.0.0.135:3456, WSS on, block_exploits. - DNS: wildcard
*.dttb.ruесть только во внутреннем DNS (роутер) — http в LAN/NetBird заработал сразу. Публично wildcard НЕТ (каждый поддомен = отдельная A-запись в SpaceWeb). Добавилswarm A 176.62.183.186через ../snippets/spaceweb-dns-api (add-a, один вызов — зона сверена до/после, 23→24 записи, ничего не задето; бэкап/tmp/dttb_zone_before.txt). - HTTPS/LE — ГОТОВО: DNS пропагировался за ~90 сек, LE cert выпущен (NPM cert id 118, до 2026-09-06),
ssl_forcedon, провереноhttps://swarm.dttb.ru/api/healthz → 200. Грабля NPM API: LE cert принимает толькоmeta:{}(с полями → "additional properties"); email/agree NPM подставляет сам. Challenge падал, пока DNS не пропагировался — не из-за meta. - Итог доступа:
https://swarm.dttb.ru(публично, за NPM+auth) иhttp://swarm.dttb.ru(LAN/NetBird). Вход — cookiesc_auth/ ACCESS_KEY.
TODO / опционально
- Снести Mac-app
SwarmClaw.app(или оставить как клиент). - Маппинг openclaw starter-агентов на gateway (роли/теги) — через UI.
- Самообучение SwarmClaw (
conversation-to-skill) — полуручное (draft→approve), не автономное; для настоящего автообучения остаётся openclaw Dreaming.
Связано
- openclaw — основной бот (LXC 137), теперь под управлением SwarmClaw
- 2026-05-06-openclaw-opus-4-7-via-max-cliproxy