Manual de Deploy — VEGA

📅 Última actualización: 2026-04-13 🐋 Docker + Coolify v4 📦 OpenClaw 2026.4.11 🟢 Node.js 24 slim

Este manual explica paso a paso qué pasa cuando se deploya VEGA: desde que Coolify toma el commit de GitHub hasta que Jarvis responde el primer mensaje en Telegram. Está pensado para entender los logs, diagnosticar errores y saber qué toca cuando se quiere agregar algo nuevo.

Arquitectura general

VEGA corre completamente en un VPS Contabo dentro de contenedores Docker orquestados por Coolify. Hay dos redes Docker aisladas: ide-internal (el IDE donde se escribe código) y vega-internal (donde viven los agentes).

┌─────────────────────────────────────────────────────────────┐ VPS Contabo · 185.237.252.125 ide-internal vega-internal ────────────── ────────────────── code-server (IDE) vega-openclaw ←── Telegram ├── claude CLI vega-redis ├── gemini CLI └── opencode CLI Supabase Cloud (externo) GitHub (rulords/vega) ──────→ Coolify v4 ──────→ Docker └─────────────────────────────────────────────────────────────┘

El código vive en GitHub. Cuando se hace git push, Coolify detecta el nuevo commit, construye la imagen Docker y reinicia el contenedor vega-openclaw. El contenedor arranca el entrypoint.sh, que configura todo y luego lanza openclaw gateway.

Flujo completo de deploy

#PasoQuién lo haceQué pasa
1 git push origin main Vos / Jarvis El código nuevo llega a GitHub
2 Webhook GitHub → Coolify GitHub automático Coolify recibe aviso de nuevo commit
3 docker build Coolify Construye la imagen capa por capa (usa caché)
4 docker stop + docker run Coolify Reemplaza el contenedor viejo por el nuevo
5 entrypoint.sh El contenedor nuevo 8 stages de configuración (ver más abajo)
6 exec openclaw gateway entrypoint.sh OpenClaw arranca y conecta a Telegram
7 Jarvis responde OpenClaw + GPT-5.4 El sistema está operativo

📦 El Dockerfile — Capas de construcción

El Dockerfile está dividido en 5 capas ordenadas de la que cambia menos a la que cambia más. Docker cachea cada capa por separado: si una capa no cambió, la reutiliza sin reconstruir. Esto es lo que hace que los deploys normales sean rápidos (~30 segundos) en lugar de 8 minutos.

📐 Regla de oro del Dockerfile

Lo que cambia menos va arriba. Lo que cambia más va abajo. Una capa modificada invalida todas las capas que están debajo de ella.

Capa 1 — Sistema operativo y herramientas base

NUNCA cambia · Tiempo: ~3 min · Siempre cacheada después del primer build

FROM node:24-slim

RUN apt-get update && apt-get install -y \
    git ca-certificates \
    chromium fonts-liberation libatk-bridge2.0-0 ... \
    && rm -rf /var/lib/apt/lists/*

ENV CHROME_BIN=/usr/bin/chromium
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true

¿Qué instala y para qué?

PaquetePara qué sirve
gitJarvis puede hacer pull/push al repo desde dentro del contenedor
ca-certificatesCertificados SSL para que HTTPS funcione (Supabase, Telegram, ElevenLabs)
chromiumBrowser headless para el tool de navegación web de Jarvis
fonts-liberation + libatk + libgbm + ...Dependencias de sistema que Chromium necesita para correr en modo headless

PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true le dice a Puppeteer que no descargue su propio Chromium porque ya instalamos el del sistema. Sin esto, el build fallaría o descargaría un Chromium duplicado.

Capa 2 — OpenClaw

Cambia con versiones de OpenClaw · Tiempo: ~4 min · Cacheada hasta el próximo update

RUN npm install --no-audit --no-fund openclaw@2026.4.11 && \
    ln -s /app/node_modules/.bin/openclaw /usr/local/bin/openclaw

¿Qué es OpenClaw?

OpenClaw es el runtime de agentes. Es el framework que maneja todo lo que Jarvis necesita para existir: conectarse a Telegram, recibir mensajes, llamar al modelo de IA, ejecutar plugins, manejar sesiones y turnos de conversación. Sin OpenClaw, habría que programar todo eso desde cero.

El ln -s crea un symlink para que el comando openclaw esté disponible en cualquier directorio del sistema (en lugar de tener que escribir /app/node_modules/.bin/openclaw cada vez).

--no-audit --no-fund: desactiva chequeos de seguridad en red y mensajes de donaciones de npm para acelerar el install.

Capa 3 — grammY (SDK de Telegram)

Rara vez cambia · Tiempo: ~2 min · Cacheada casi siempre

RUN npm install --no-audit --no-fund \
    grammy \
    @grammyjs/runner \
    @grammyjs/transformer-throttler \
    @grammyjs/conversations \
    @grammyjs/menu \
    @grammyjs/hydrate \
    @grammyjs/parse-mode \
    @grammyjs/ratelimiter

¿Qué es grammY y por qué está separado?

grammY es la librería de Node.js para bots de Telegram. OpenClaw la usa internamente para conectarse a la API de Telegram. Está separada en su propia capa porque es un conjunto estable de paquetes que casi nunca necesita actualizarse.

Plugin grammYFuncionalidad
grammyCore: recibir y enviar mensajes, fotos, audio
@grammyjs/runnerProcesar múltiples mensajes en paralelo sin bloquear
@grammyjs/transformer-throttlerRespetar los rate limits de Telegram automáticamente
@grammyjs/conversationsManejar conversaciones con estado (flujos multi-turno)
@grammyjs/menuBotones interactivos en los mensajes (zona 🔴 aprobaciones)
@grammyjs/hydrateAgregar métodos helper a los objetos de mensaje
@grammyjs/parse-modeMarkdown/HTML en respuestas (bold, code, links)
@grammyjs/ratelimiterLimitar mensajes por usuario para evitar spam

Capa 4 — Dependencias de plugins

Cambia al agregar integraciones · Tiempo: ~1 min

RUN npm install --no-audit --no-fund \
    redis \
    @supabase/supabase-js

¿Para qué sirve cada una?

PaqueteUsada porPara qué
redis Plugin vega-context Conectarse a Redis para leer/escribir el rolling context de cada sesión (memoria de corto plazo, TTL 24hs)
@supabase/supabase-js Plugin vega-context Persistir conversaciones y snapshots de memoria en Supabase (memoria de largo plazo)

Estas librerías están en la imagen base (en /app/node_modules/) y también se instalan localmente en cada extensión durante el Stage 6b del entrypoint. La razón: Node resuelve módulos locales primero — si la extensión tiene su propio node_modules/ incompleto, ignoraría los de la imagen base.

Capa 5 — Entrypoint

Cambia frecuentemente · Tiempo: <1 segundo · Solo copia 1 archivo

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

EXPOSE 18789
ENTRYPOINT ["/entrypoint.sh"]

Esta capa solo copia el script de arranque. Es la más liviana — no descarga nada. Gracias a las capas separadas anteriores, cambiar el entrypoint no invalida ninguna otra capa y el rebuild tarda segundos.

EXPOSE 18789 documenta que el gateway de OpenClaw escucha en ese puerto (aunque en producción el acceso es solo interno, mapeado a 127.0.0.1:18789).

ENTRYPOINT ["/entrypoint.sh"]: cuando el contenedor arranca, lo primero que ejecuta es este script. No hay un CMD separado — el entrypoint es el proceso principal (PID 1 via exec openclaw gateway).

🚀 El Entrypoint — 8 Stages de arranque

El entrypoint.sh es el script que corre cuando el contenedor arranca. Hace toda la preparación necesaria antes de lanzar OpenClaw. Está dividido en stages numerados para facilitar el diagnóstico: si algo falla, el log dice exactamente en qué stage y por qué.

⚠️ Por qué no usamos set -e

set -e termina el script ante cualquier error, incluso los opcionales. Preferimos manejar errores manualmente con dos helpers: exit_critical (falla fatal — aborta el boot) y boot_error (falla no fatal — registra el error y continúa). Así, si Redis no está disponible, Jarvis arranca igual sin memoria de sesión en lugar de no arrancar.

1
Directorios base
Crea la estructura de carpetas que OpenClaw necesita
mkdir -p "$CONFIG_DIR/agents" "$CONFIG_DIR/workspace" "$CONFIG_DIR/extensions" "$CONFIG_DIR/logs"

Todo lo que OpenClaw necesita vive en /root/.openclaw/. Este stage crea las 4 carpetas fundamentales. Si falla (disco lleno, permisos rotos), es un error crítico — no se puede continuar.

CarpetaContenido
/root/.openclaw/agents/Character files de cada agente (jarvis, financiero, inversiones, bienestar)
/root/.openclaw/workspace/Archivos de identidad de Jarvis (SOUL.md, IDENTITY.md, USER.md, AGENTS.md)
/root/.openclaw/extensions/Plugins externos (vega-context y futuros)
/root/.openclaw/logs/Logs internos de OpenClaw
2
Agentes
Copia los character files desde el repo montado como volumen
( cd /app/vega/.openclaw/agents && cp -r . "$CONFIG_DIR/agents/" ) 2>/dev/null

Los agentes no están dentro de la imagen Docker — viven en el repositorio (/app/vega/.openclaw/agents/) que se monta como volumen en el contenedor. Este stage los copia al directorio que OpenClaw espera leer.

¿Por qué subshell + cd en lugar de cp -r path/*? En sh (no bash), si el directorio está vacío, el glob * se pasa literalmente como string y cp falla. El patrón ( cd src && cp -r . dest/ ) funciona incluso con directorios vacíos.

Si este stage falla, Jarvis arranca sin agentes — no puede responder con personalidad pero OpenClaw inicia igual.

3
Workspace (identity, soul, tools)
Carga la identidad y el alma de Jarvis
( cd /app/vega/.openclaw/workspace && cp -r . "$CONFIG_DIR/workspace/" ) 2>/dev/null

El workspace contiene los archivos que definen quién es Jarvis:

ArchivoContenido
SOUL.mdEl system prompt real de Jarvis — su personalidad, valores, forma de hablar
IDENTITY.mdDatos de identidad: nombre, rol, quién es Rodrigo y Maria
USER.mdContexto del usuario: gustos, proyectos, cómo Jarvis debe tratarte
AGENTS.mdMapa del swarm: qué agentes existen y cuándo delegar a cada uno
4
Extensiones / Plugins externos
Carga plugins no-bundled como vega-context
( cd /app/vega/.openclaw/extensions && cp -r . "$CONFIG_DIR/extensions/" ) 2>/dev/null

OpenClaw tiene dos tipos de plugins:

TipoEjemplosConfianzaCómo se habilitan
Bundled groq, elevenlabs, firecrawl Auto-trusted "enabled": true en plugins.entries
Externos vega-context Requiere allowlist Debe estar en plugins.allow además de entries

vega-context es el plugin que conecta OpenClaw con Redis y Supabase. Lo desarrollamos nosotros — vive en .openclaw/extensions/vega-context/ del repo.

5
Git config + sync
Configura git y sincroniza el repo para que Jarvis pueda pushear
git config --global user.name "Jarvis Vega"
git config --global user.email "jarvisvegaia@gmail.com"
git config --global url."https://${VEGA_GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"
git -C /app/vega pull --rebase origin main

Jarvis puede modificar archivos del repo (su character, skills, wikis) y pushearlos a GitHub sin intervención humana. Para eso necesita que git esté configurado con credenciales válidas.

safe.directory: git 2.35+ requiere que cada directorio sea marcado como seguro explícitamente (medida de seguridad para evitar que procesos de otros usuarios accedan a repos ajenos).

El pull --rebase al arrancar sincroniza el repo local con GitHub por si hubo cambios entre el deploy anterior y este arranque. El stash antes del pull protege cambios locales que Jarvis haya hecho.

Si VEGA_GITHUB_TOKEN no está seteado, este stage emite un warning pero no falla — Jarvis arranca sin capacidad de push.

6
Gateway token
Genera o valida el token de autenticación del gateway
# Caso 1: token configurado en Coolify (recomendado)
GATEWAY_TOKEN="$OPENCLAW_GATEWAY_TOKEN"

# Caso 2: fallback — token aleatorio efímero
GATEWAY_TOKEN=$(tr -dc 'a-f0-9' < /dev/urandom | head -c 64)
if [ -z "$GATEWAY_TOKEN" ]; then
  exit_critical "No se pudo generar gateway token"
fi

El gateway token es la contraseña que protege la API HTTP interna de OpenClaw (puerto 18789). Sin él, cualquiera en la red Docker podría enviarle instrucciones directas a los agentes.

EscenarioResultado
OPENCLAW_GATEWAY_TOKEN seteado en CoolifySe usa ese token — persiste entre restarts
No seteadoSe genera uno nuevo con /dev/urandom — se pierde al reiniciar
⚠️ Por qué usamos /dev/urandom y no openssl rand La imagen base node:24-slim no incluye OpenSSL. Intentar usarlo crashea el contenedor. /dev/urandom es igual de seguro para este uso.
6b
Dependencias de extensiones
npm install para cada plugin externo con package.json
for ext_dir in "$CONFIG_DIR/extensions"/*/; do
  if [ -f "$ext_dir/package.json" ]; then
    npm_output=$(npm install --prefix "$ext_dir" --no-audit --no-fund 2>&1)
    # muestra últimas 5 líneas del error si falla
  fi
done

Los plugins externos (como vega-context) tienen sus propias dependencias (redis, @supabase/supabase-js). Node.js resuelve módulos locales primero: si la carpeta node_modules/ del plugin existe pero está incompleta, ignorará los paquetes de la imagen base.

Este stage garantiza que cada extensión tenga sus deps actualizadas en cada arranque. Si falla, el log muestra las últimas 5 líneas del error de npm para poder diagnosticar.

7
Generar openclaw.json
Escribe el archivo de configuración principal + valida que sea JSON válido
cat > "$CONFIG_FILE" <<EOF
{ ... configuración completa con variables de entorno ... }
EOF

# Validación post-escritura
node -e "JSON.parse(require('fs').readFileSync('$CONFIG_FILE','utf8'))"

El archivo /root/.openclaw/openclaw.json es la configuración central de OpenClaw — le dice al gateway quiénes son los agentes, cómo conectarse a Telegram, qué plugins activar y cómo comportarse.

Las variables de entorno (${TELEGRAM_BOT_TOKEN}, ${GATEWAY_TOKEN}, etc.) se inyectan dentro del JSON durante la generación. Por eso la validación con node -e JSON.parse() es crítica: si una variable contiene comillas o caracteres especiales, el JSON quedaría inválido y OpenClaw no arrancaría.

8
Variables de entorno
Verifica que todas las variables necesarias estén presentes
[VEGA] ✅ TELEGRAM_BOT_TOKEN — OK (82 chars) [VEGA] ✅ OPENCLAW_GATEWAY_TOKEN — OK (64 chars) [VEGA] ✅ GROQ_API_KEY — OK (56 chars) [VEGA] ⚠️ REDIS_URL — no definida — sin memoria de sesión [VEGA] ❌ TELEGRAM_BOT_TOKEN — FALTA — bot no arranca

Cada variable tiene una criticidad:

EstadoSignificadoConsecuencia
✅ OKLa variable está seteadaLa funcionalidad asociada está activa
⚠️ no definidaVariable opcional ausenteEsa funcionalidad está desactivada, pero Jarvis arranca
❌ FALTAVariable crítica ausenteCuenta como boot_error — OpenClaw puede no funcionar

⚙️ openclaw.json — Sección por sección

gateway

{
  "gateway": {
    "mode": "local",
    "auth": {
      "mode": "token",
      "token": "${GATEWAY_TOKEN}"
    }
  }
}

El gateway es la API HTTP interna que recibe mensajes de los canales (Telegram, futuros) y los distribuye a los agentes. mode: "local" significa que corre en el mismo proceso que los agentes. auth.mode: "token" requiere que todo cliente que llame a la API presente el token correcto en el header.

agents

{
  "agents": {
    "defaults": {
      "workspace": "/root/.openclaw/workspace",
      "model": { "primary": "openai-codex/gpt-5.4" }
    },
    "list": [
      { "id": "jarvis",      "default": true, "agentDir": "..." },
      { "id": "financiero",                   "agentDir": "..." },
      { "id": "inversiones",                  "agentDir": "..." },
      { "id": "bienestar",                    "agentDir": "..." }
    ]
  }
}
CampoQué hace
defaults.workspaceDirectorio compartido que todos los agentes pueden leer (SOUL.md, IDENTITY.md, etc.)
defaults.model.primaryModelo LLM por defecto para todos los agentes
list[].idIdentificador único del agente — se usa en bindings y logs
list[].default: trueAgente que responde si ningún binding coincide (Jarvis)
list[].agentDirDirectorio con el character.md y skills del agente

bindings

{
  "bindings": [
    { "agentId": "jarvis",     "match": { "channel": "telegram", "peer": { "kind": "group", "id": "-1003976110854:topic:1" } } },
    { "agentId": "financiero", "match": { "channel": "telegram", "peer": { "kind": "group", "id": "-1003976110854:topic:2" } } },
    ...
  ]
}

Los bindings son las reglas de routing: qué agente responde a qué mensaje. Cuando llega un mensaje de Telegram, OpenClaw busca el binding que coincida con el canal y el peer (grupo + topic) y le asigna el agente correspondiente.

Topic IDAgenteRol
1JarvisGeneral — orquestador, temas variados
2FinancieroGastos, transacciones, presupuesto
6InversionesCartera, CEDEARs, MEP, portfolio
7BienestarSalud, hábitos, sueño
8JarvisAprobaciones zona 🔴

El ID -1003976110854:topic:2 es el ID interno de Telegram del grupo (-1003976110854) combinado con el número de topic (2).

channels

{
  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "${TELEGRAM_BOT_TOKEN}",
      "dmPolicy": "allowlist",
      "allowFrom": ["601102393"],
      "groups": {
        "-1003976110854": {
          "requireMention": false,
          "allowFrom": ["601102393"]
        }
      }
    }
  }
}
CampoQué hace
botTokenToken del bot (@vega_jarvis_bot) — obtenido de @BotFather
dmPolicy: "allowlist"Solo usuarios en la lista pueden mandar DMs al bot
allowFrom: ["601102393"]Chat ID de Rodrigo — único autorizado (por ahora)
requireMention: falseJarvis responde sin necesidad de escribir @vega_jarvis_bot

plugins

{
  "plugins": {
    "enabled": true,
    "allow": ["vega-context"],
    "slots": { "contextEngine": "vega-context" },
    "entries": {
      "groq":       { "enabled": true },
      "elevenlabs": { "enabled": true },
      "firecrawl":  { "enabled": true },
      "vega-context": { "enabled": true }
    }
  }
}
🔴 Regla crítica — plugins.allow Solo van en allow los plugins externos (no-bundled). Los plugins bundled (groq, elevenlabs, firecrawl) son auto-trusted y NO deben ir en allow — ponerlos ahí rompe el canal de Telegram.
BUNDLED

groq

Transcripción de audio a texto (STT). Cuando mandás un audio de voz a Jarvis, Groq lo transcribe con whisper-large-v3 antes de enviarlo al LLM.

BUNDLED

elevenlabs

Texto a voz (TTS). Convierte las respuestas de Jarvis a audio con la voz personalizada. Solo respuestas cortas (≤280 chars).

BUNDLED

firecrawl

Web fetch. Cuando le mandás una URL a Jarvis, Firecrawl extrae el contenido limpio (sin HTML) para que el LLM lo procese.

EXTERNO

vega-context

Rolling context. Antes de cada respuesta lee el contexto de Redis. Después de cada respuesta lo actualiza en Redis + persiste en Supabase.

slots.contextEngine: "vega-context" le dice a OpenClaw que este plugin es el motor de contexto — se llama automáticamente en cada turno.

tools

{
  "tools": {
    "web": {
      "search": { "enabled": true, "openaiCodex": { "enabled": true, "mode": "live" } },
      "fetch":  { "enabled": true, "provider": "firecrawl" }
    },
    "media": {
      "audio": { "enabled": true, "language": "es", "models": [{ "provider": "groq", "model": "whisper-large-v3" }] },
      "image": { "enabled": true }
    }
  }
}
ToolCapacidad que le da a Jarvis
web.search vía CodexBuscar en internet nativamente (GPT-5.4 tiene búsqueda integrada, sin API key extra)
web.fetch vía FirecrawlLeer el contenido de una URL y procesarlo
media.audio vía GroqEscuchar y transcribir mensajes de voz en español
media.imageRecibir y procesar imágenes enviadas por Telegram

messages.tts

{
  "messages": {
    "tts": {
      "auto": "inbound",
      "provider": "elevenlabs",
      "maxTextLength": 280,
      "providers": {
        "elevenlabs": {
          "voiceId": "3cBYXsbKACmcb0rHwMjm",
          "modelId": "eleven_multilingual_v2",
          "voiceSettings": {
            "stability": 0.64,
            "similarityBoost": 0.80,
            "style": 0.12,
            "useSpeakerBoost": true,
            "speed": 1.18
          }
        }
      }
    }
  }
}
ParámetroValorQué hace
auto: "inbound"inboundSolo convierte a voz las respuestas a mensajes de voz entrantes
maxTextLength: 280280 charsRespuestas más largas no se convierten (evita audios interminables)
voiceId3cBYXsbKACmcb0rHwMjmVoz personalizada de Jarvis — creada en ElevenLabs (porteño ejecutivo)
stability: 0.64Consistencia de la voz (más alto = más monótona)
similarityBoost: 0.80Qué tan fiel al sample original (más alto = más parecida)
style: 0.12Expresividad emocional (bajo = profesional, no dramatizado)
speed: 1.18Velocidad de habla (1.0 = normal, 1.18 = levemente más rápido)
useSpeakerBoost: trueMejora la nitidez de la voz del speaker

📋 Variables de entorno — Referencia completa

VariableCriticidadQué activa
TELEGRAM_BOT_TOKEN CRÍTICA Sin esto el bot no arranca. Se obtiene de @BotFather en Telegram.
OPENCLAW_GATEWAY_TOKEN Recomendada Seguridad de la API interna. Si no está, se genera uno efímero (se regenera en cada restart).
GROQ_API_KEY Opcional STT — transcripción de audios de voz. Sin esto Jarvis no entiende mensajes de voz.
ELEVENLABS_API_KEY Opcional TTS — respuestas de voz. Sin esto Jarvis responde solo con texto.
FIRECRAWL_API_KEY Opcional Web fetch limpio. Sin esto el fetch de URLs funciona con el fallback nativo (menos preciso).
REDIS_URL Opcional Memoria de corto plazo (rolling context TTL 24hs). Sin esto vega-context no puede guardar el contexto de sesión.
SUPABASE_URL Opcional Persistencia en DB. Sin esto las conversaciones no se guardan a largo plazo.
SUPABASE_SERVICE_KEY Opcional Necesaria junto con SUPABASE_URL. Es la clave con permisos de escritura (service role, bypasea RLS).
VEGA_GITHUB_TOKEN Opcional Permite a Jarvis hacer git push al repo desde dentro del contenedor (para actualizar sus propios archivos).

🔴 Errores comunes y diagnóstico

❌ CRÍTICO — entrypoint abortado · Causa: openclaw.json inválido

Cuándo aparece: Una variable de entorno contiene comillas, saltos de línea u otros caracteres especiales que rompen el JSON.

Fix: Revisar en Coolify las env vars. Las más problemáticas son tokens que contienen " o \n. Regenerar el token si es necesario.

❌ ERROR STAGE [N]: npm install falló en vega-context

Cuándo aparece: Falla de red durante el Stage 6b, o package.json con un paquete inexistente.

Fix: Revisar las últimas 5 líneas del error que imprime el Stage 6b. Si es red, el próximo restart suele resolver. Si es paquete, revisar el package.json de la extensión.

⚠️ git pull --rebase falló — continuando con código local

Cuándo aparece: Conflicto de merge, red sin conectividad, o token de GitHub vencido.

Consecuencia: Jarvis arranca con el código del último deploy exitoso. No es crítico pero puede tener código desactualizado.

⚠️ Boot con N error(es) — OpenClaw arranca igual

Cuándo aparece: Uno o más stages no-críticos fallaron (Redis no disponible, agentes no encontrados, etc.).

Fix: Buscar arriba en los logs las líneas con ❌ ERROR STAGE para identificar exactamente qué falló.

Telegram inicializado pero Jarvis no responde

Cuándo aparece: El log muestra todo verde pero los mensajes en Telegram no tienen respuesta.

Causas posibles:

  • El chat ID del que escribe no está en allowFrom
  • El topic ID del mensaje no está en bindings
  • plugins.allow tiene plugins bundled (rompe la inicialización interna)
  • Bug de versión de OpenClaw (ocurrió con 2026.4.2 — actualizar a 2026.4.11+)

Diagnóstico: Revisar el log completo de OpenClaw en /tmp/openclaw/openclaw-YYYY-MM-DD.log dentro del contenedor.

🔄 Force deploy vs Deploy normal

Coolify cachea las capas del Dockerfile. Cuando una capa no cambió, la reutiliza sin reconstruir. Pero a veces se necesita forzar la reconstrucción desde cero.

Qué cambióTipo de deployTiempo estimado
Solo entrypoint.sh Normal ~30 segundos (solo capa 5)
Archivos en .openclaw/ (agentes, extensions) Normal <5 segundos (son volúmenes, no imagen)
Versión de OpenClaw en el Dockerfile Force deploy ~6-8 minutos (capas 2-4 se reconstruyen)
Nuevo npm install en cualquier capa Force deploy ~6-8 minutos
Nuevo paquete en apt-get install Force deploy ~10+ minutos (todas las capas)
💡 Cómo hacer Force deploy en Coolify En el panel de Coolify → servicio vega-openclaw → botón "Deploy" → activar "Force rebuild" (o el toggle "Without cache") antes de hacer click en Deploy.