一键导入
infrastructure-deployment
CI/CD pipeline management, deploy failure diagnosis, self-healing, and proactive communication for infrastructure changes.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
CI/CD pipeline management, deploy failure diagnosis, self-healing, and proactive communication for infrastructure changes.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when generating scheduled reports from Reddit subreddits via Composio Reddit tools (REDDIT_GET_R_TOP, REDDIT_SEARCH_ACROSS_SUBREDDITS, REDDIT_RETRIEVE_POST_COMMENTS). Covers fetching posts, computing engagement, extracting top comments, and producing either a single-page PDF (fpdf2) or a text summary for group chat delivery.
Author in-repo SKILL.md: frontmatter, validator, structure, and writing-quality principles.
Manage the Hermes WebUI (nesquena/hermes-webui) deployment, configuration, and troubleshooting. Covers systemd service, settings.json, send_key behavior, Caddy reverse proxy, CI/CD integration via deploy.sh.
Systematically orient in a new project repository using Kairos governance, Hindsight memory banks, and documentary axis reading order. Covers REPOMAP, MASTER-SPEC, RULES, infrastructure exploration, and state verification.
Process, summarize, and extract information from YouTube videos. Covers metadata lookup, transcript extraction, and content analysis for wrestling analysis and general video research.
Workflow completo para mantener la Knowledge Base Personal (Narrativa Mitologica) de Martin. Cubre sesion de actualizacion, clasificacion KR2, propuesta KR1, ejecucion via Kilo CLI, compile y push.
| name | infrastructure-deployment |
| description | CI/CD pipeline management, deploy failure diagnosis, self-healing, and proactive communication for infrastructure changes. |
| version | 2.0.0 |
| author | Hermes Agent |
| license | MIT |
| platforms | ["linux"] |
| metadata | {"hermes":{"tags":["deploy","cicd","infrastructure","docker","self-healing","communication"],"related_skills":["systematic-debugging","github-pr-workflow"]}} |
Managing infrastructure deployments involves more than running commands. It requires diagnosing failures, self-healing when possible, and proactively communicating status to the user.
Core principle: Deploy failures must be diagnosed, fixed, and reported within 30 minutes. Silence is not an option.
Antes de CUALQUIER acción relacionada con deploy, pipeline CI/CD, notificaciones de deploy, o infraestructura del Toolset:
recall(bank="toolset", query="infraestructura, despliegues recientes, estado del pipeline, notificaciones")Por qué es obligatorio: El bank toolset contiene estado del pipeline, últimas ejecuciones, issues conocidos, y decisiones técnicas. Trabajar sin este contexto = repetir errores y dar respuestas incompletas. Fue instrucción directa del usuario.
Esto NO es opcional. Si empiezas a diagnosticar, investigar, o proponer soluciones sin recall previo, estás violando la regla.
Push to main → GitHub Actions:
1. validate-configs (syntax + schema validation) [push + workflow_dispatch]
2. OpenTofu Infrastructure (IaC) [workflow_dispatch only]
3. Deploy Services (Docker Compose via SSH) [workflow_dispatch only]
Validate on push, deploy on demand: El push a main solo corre validate-configs. Los jobs opentofu, deploy-services, preflight se ejecutan exclusivamente via workflow_dispatch manual. Esto evita downtime innecesario.
Para gatillar un deploy desde Hermes (cuando el usuario autoriza):
gh workflow run deploy.yml --repo kirlts/toolset
Para verificar que se gatilló:
gh run list --repo kirlts/toolset --limit 1 --json status,conclusion
Parámetros opcionales:
gh workflow run deploy.yml --repo kirlts/toolset \
-f skip_opentofu=false \
-f skip_deploy=false \
-f skip_preflight=false
Después de CADA cambio de infraestructura (commit que modifica SOUL.md, config.yaml, deploy.sh, skills, scripts, o cualquier archivo versionado en toolset):
terminal(background=true, notify_on_complete=true, timeout=600)
# Prompt: "Ejecuta /document segun .agents/workflows/document.md" --auto --dir /opt/toolset-repo
Sin excepción. El /document sincroniza MASTER-SPEC, CHANGELOG, TODO, INFRASTRUCTURE-MANIFEST, MEMORY, y mantiene la trazabilidad del proyecto.
| Failure | Symptom | Diagnosis |
|---|---|---|
| Config validation | JSON/YAML parse error | Check for // in URLs, trailing commas, control chars |
| Port conflict | "address already in use" | Check if WebUI or other service binds the same port |
| Container name conflict | container name already in use | Container from prior deploy wasnt cleaned up |
| Gateway restart not triggered after MCP config change | Composio MCP tools missing in new sessions despite valid key in config.yaml | Gateway caches MCP connections at startup. Post-deploy key injection doesn't trigger restart. Fix: add sudo systemctl restart hermes-gateway after any MCP config change in deploy.sh (see "Post-Inyección de Keys MCP" below) |
| API key expired | Missing API key / Invalid API key | Key in .env doesnt match credential pool |
| Docker compose down | Stops running containers | Must stop conflicting services first (e.g. WebUI) |
| Hindsight startup timeout | dependency failed to start: container hindsight is unhealthy | HuggingFace model download (BAAI/bge-small-en-v1.5) times out on first attempt |
| Cascading dependency failure | Downstream service (caddy) stays Created while upstream (hindsight) eventually becomes healthy | Compose dependency check fired before hindsight recovered via restart policy |
gh run list --repo <repo> --limit 1 --json status,conclusion
gh run view <run-id> --repo <repo> --log-failed | tail -30
When docker compose up fails with "address already in use":
sudo systemctl stop <service>docker compose up -d --remove-orphans --force-recreatesudo systemctl start <service>When docker compose up fails with "container name already in use":
sudo docker rm -f <container-name>--force-recreate flag: docker compose up -d --remove-orphans --force-recreateWhen docker compose up -d succeeds partially — some services are healthy but downstream services (e.g. caddy) stay in Created state:
Symptom: docker compose ps shows the downstream service as Created while its dependency shows Up and healthy. This happens when the dependency failed health checks during the initial compose run, then recovered via its restart policy, but compose's dependency resolution already gave up.
Root cause: Docker Compose evaluates depends_on conditions once during startup. If hindsight (for example) fails its health check on first attempt and the container enters a restart loop, compose marks the dependency as failed and never starts caddy — even if hindsight later recovers.
Diagnosis:
docker compose ps --all — look for services in Created (not Up)docker inspect <service> --format '{{.State.Status}} {{.State.Health.Status}}' — check if the dependency is now healthydocker logs --tail 30 <dependency>Fix: Once the dependency service is running and healthy, start the stuck downstream service:
cd /opt/toolset
docker compose up -d <downstream-service> # e.g. caddy
This runs docker compose's dependency resolution again against the already-running healthy services, skipping the one that previously failed.
When Kilo CLI or Hermes gets "Missing API key":
source .env && curl -H "Authorization: Bearer $KEY" https://api.example.com/v1/modelsWhen a script in deploy.sh reads from Infisical API and the secrets come back empty:
Symptom: config.yaml has PLACEH...PLOY as x-consumer-api-key for MCP composio server.
Root cause: The API call http://localhost:8081/api/v3/secrets/raw/COMPOSIO_MCP_KEY is missing ?workspaceId=<ID>&environment=prod query params. Infisical v3 requires these parameters — without them it returns 400 Missing environment, the exception is caught, and the secret value defaults to empty string.
Fix: Add the query parameters to the URL. The workspaceId can be obtained from the service token info endpoint (/api/v2/service-token) or hardcoded from the known project ID.
Diagnosis:
grep 'x-consumer-api-key' /home/opc/.hermes/config.yaml
# → PLACEH...PLOY means injection failed
Full reference in: references/secret-flow-infisical.md.
Regla inviolable del flujo de secretos en Toolset:
GitHub Secrets → Infisical (vía sync_secret) → VPS lee de Infisical
NUNCA hagas esto:
SIEMPRE haz esto:
sync_secret en deploy.shlocalhost:8081) usando INFISICAL_SERVICE_TOKEN/opt/toolset/.env (único .env permitido)import os, json, subprocess
token = ''
with open('/opt/toolset/.env') as f:
for line in f:
if line.startswith('INFISICAL_SERVICE_TOKEN='):
token = line.split('=', 1)[1].strip()
break
if token:
r = subprocess.run(['curl', '-s', 'http://localhost:8081/api/v3/secrets/raw/SECRET_NAME?workspaceId=<ID>&environment=prod',
'-H', f'Authorization: Bearer {token}'], capture_output=True, text=True, timeout=10)
if r.returncode == 0:
data = json.loads(r.stdout)
secret_value = data.get('secret', {}).get('secretValue', '')
⚠️ Consecuencia de violar esta regla: El usuario fue explícito: "si empiezas a mezclar la forma en la que se provisionan los servicios o en la que se inyectan los secretos vas a cometer errores fatales."
NUNCA pongas scripts Python inline dentro de ssh host "python3 -c '...'". Las
f-strings de Python se rompen con el anidamiento de quotes de bash, causando
fallos silenciosos.
Síntoma: El script corre pero falla calladamente, la excepción se captura, y la variable queda vacía. Nadie se entera.
Fix: Script standalone, transferido y ejecutado:
scp script.py host:/tmp/script.py
ssh host "python3 /tmp/script.py; rm -f /tmp/script.py"
El repo tiene infrastructure/hermes/inject-composio-key.py como ejemplo. Para
cualquier script que lea de Infisical o modifique config.yaml desde deploy.sh,
usa este patrón.
Problema detectado (25 Jun 2026): El pipeline de deploy inyecta COMPOSIO_MCP_KEY
en config.yaml vía inject-composio-key.py, pero el gateway hermes-gateway
NUNCA se reinicia después. Como las conexiones MCP se cargan al iniciar el gateway
(y se cachean en memoria), el gateway sigue usando la key vieja. /new no ayuda
— las sesiones heredan las tools del gateway existente.
Fix idempotente en deploy.sh: Después de cualquier script que modifique
mcp_servers en config.yaml, agregar:
sudo systemctl restart hermes-gateway
⚠️ No se puede hacer desde dentro del gateway. El gateway bloquea
systemctl restart hermes-gateway porque SIGTERM mata al comando antes de
completar. Soluciones:
cronjob action=create no_agent=true script="sudo systemctl restart hermes-gateway"sudo systemd-run --unit=hermes-restart sudo systemctl restart hermes-gatewayVerificación post-restart:
journalctl -u hermes-gateway --no-pager | grep -E "(composio|MCP)"
# Debe mostrar: MCP server 'composio' connected successfully (sin 401)
Referencia completa: toolset-mcp-integration/references/gateway-restart-requirement.md
Reglas:
repo → commit → push → GitHub Actions → deploy.sh → VPSdocker compose up -d manualmente para restaurar servicios después de un deploy fallido, pero el fix debe ir al repo.Pasos cuando necesitas cambiar configuración:
cd /tmp/toolset && git pullgit checkout -b hermes-fix-<description>git add && git commit && git pushgh pr create && gh pr mergeworkflow_dispatch.Cuando el usuario pide EXPLÍCITAMENTE que investigues, diagnostiques, o averigües algo — no implementes NINGUNA solución alternativa hasta que el usuario la autorice.
Violación detectada 2026-07-05: El usuario pidió "revisa el tiro que está haciendo Kilo porque quiero saber si es que se está demorando". En vez de solo diagnosticar, Hermes:
Flujo correcto cuando piden diagnóstico:
Anti-patrón: "Déjame revisar... procede a implementar una solución alternativa sin preguntar". El usuario fue inequívoco: "solamente te pedí que me explicaras qué pasó y te pusiste a hacer cambios autónomamente, eso no está bien."
Cuando el usuario pide resolver un problema técnico (especialmente de infraestructura, CI/CD, o secretos):
Anti-patrón: Implementar polling cuando el usuario pidió hooks. Implementar un fix sin entender el flujo de secrets. Editar config.yaml sin pasar por el repo.
El usuario EXIGE actualizaciones CADA VEZ que completes un paso relevante durante tareas de monitoreo, deploy, o diagnóstico. No esperes al resultado final.
Esto NO es opcional. El usuario lo ha corregido múltiples veces. Cada tool call que produzca un resultado relevante = update inmediato al usuario.
El deploy NO es automático en push. El flujo correcto:
Si el usuario rechaza el deploy o no responde: dejar los cambios en main sin deploy. No presionar.
Referencia:
references/manual-deploy-ci-cd-transition.md— detalle de los cambios en deploy.yml, reglas de política, y nota de transición del primer push.
Cuándo: El usuario expresa frustración, enojo, o corrige tu comportamiento.
Qué hacer (EN ORDEN):
Reconocer el error específico en una línea. Sin adjetivos, sin calificativos. Ej: "No envié updates durante 10 minutos." No: "Mil disculpas por mi terrible error."
Identificar el fix sistémico inmediatamente. ¿Esto necesita un skill update? ¿Memory update? ¿Ambos? La frustración del usuario es SEÑAL de skill update, no solo memory update (SOUL.md).
Ejecutar el fix antes de seguir trabajando. Si es memory → memory(). Si es skill → skill_manage(patch). Hazlo AHORA, no "después".
Reportar el cambio hecho. "Memoria actualizada con la regla. Ahora [acción correctiva]."
Seguir con la tarea. No te detengas a rumiar. El usuario quiere ver progreso.
Anti-patrones:
En WhatsApp, las respuestas contienen SOLO el mensaje para el usuario. NUNCA incluir tool calls, outputs de terminal, configuraciones, logs, ni traces. El razonamiento y ejecución de herramientas ocurre del lado del agente sin mostrarse.
Formato:
Problema: [one line]
Causa raíz: [one line]
Fix: [one line]
Estado: ✅ Todo verde | ❌ [what remains]
| ❌ Don't | ✅ Do |
|---|---|
| [silence >30 min on failed deploy] | Send update after each relevant step |
| "I will check the logs" | Check logs, then report |
| [only posts command output] | Write a text summary |
| "Let me try X" | Try X, then report result |
| "Mil disculpas" / "Perdón" | Fix the root cause (update skill/memory) |
| Wait for deploy to finish to report | Send updates: PR created → CI started → deploy running → verify result |
When deploying services that share ports with system services (e.g., WebUI on port 8888 and Hindsight on port 8888):
# Stop conflicting services
sudo systemctl stop hermes-webui 2>/dev/null || true
# Deploy
cd /opt/toolset
sudo docker compose down --remove-orphans
sudo docker compose up -d --remove-orphans --force-recreate
# Restart conflicting services
sudo systemctl start hermes-webui 2>/dev/null || true
This pattern is now encoded in deploy.sh. If adding new services, check for port conflicts during code review.
Every repository gets a Hindsight bank named after the repo. Banks are:
hermes-sync-banks croninfrastructure/hermes/banks/ on each deploy$(ls infrastructure/hermes/banks/) dynamicallyProblema 1: "settings.yml not valid" — Container fails to start.
Root cause: The container generates a default settings.yml from a template, but the template produces invalid config on certain platforms (ARM64/OL9 with SELinux).
Fix: Mount a pre-configured settings.yml from the researchit repo:
volumes:
- /opt/researchit/searxng:/etc/searxng:rw
Then:
cd /opt/toolset && sudo docker compose up -d searxng --force-recreate
Problema 2: "KeyError: 'default_doi_resolver'" — Container starts but /search returns 500.
Root cause: SearXNG >=2026.6.24 requiere default_doi_resolver y doi_resolvers a root level del settings.yml (no bajo search:). Ver references/searxng-settings-doi-resolver.md en la skill researchit.
On first startup (or after --force-recreate), Hindsight downloads two SentenceTransformer models from HuggingFace Hub:
BAAI/bge-small-en-v1.5 (embeddings)cross-encoder/ms-marco-MiniLM-L-6-v2 (reranker)The download happens during the health check start_period (60s in the compose file). If the download takes longer than the health check retries + interval allow, or if HuggingFace Hub is slow/unreachable, the health check fails and the container is marked unhealthy. Compose then reports dependency failed to start: container hindsight is unhealthy.
Behavior:
restart: unless-stopped will automatically restart the container, and the model cache from the failed attempt may speed up the next try.hindsight: condition: service_healthy (e.g. caddy) will NOT start automatically (see "Cascading Dependency Failures" above for the fix).Verification: Check docker logs hindsight for lines containing Loading SentenceTransformer model and Embeddings: initializing — these indicate the model download is in progress.
A daily cron job (hermes-health-check) performs:
En lugar de monitorear activamente los deploys, Hermes corre un watcher que detecta fallos automáticamente y notifica por WhatsApp.
Implementación: cron job hermes-deploy-watch (job_id=9d95e690ba92, cada 3 min) con no_agent=True:
~/.hermes/scripts/deploy-watch.shgh run list --repo kirlts/toolset --limit 1 --json number,conclusion,displayTitle/tmp/hermes-deploy-last-run para evitar notificaciones duplicadasScript (deploy-watch.sh):
#!/bin/bash
LAST_RUN_FILE="/tmp/hermes-deploy-last-run"
RUN_INFO=$(gh run list --repo kirlts/toolset --limit 1 --json number,conclusion,displayTitle)
RUN_NUM=$(echo "$RUN_INFO" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d[0]['number'])")
RUN_CONCLUSION=$(echo "$RUN_INFO" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d[0]['conclusion'])")
RUN_TITLE=$(echo "$RUN_INFO" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d[0]['displayTitle'])")
LAST_NOTIFIED=$(cat "$LAST_RUN_FILE" 2>/dev/null || echo "")
[ "$RUN_NUM" = "$LAST_NOTIFIED" ] && exit 0
echo "$RUN_NUM" > "$LAST_RUN_FILE"
[ "$RUN_CONCLUSION" = "failure" ] && echo "❌ Deploy #$RUN_NUM falló en toolset: $RUN_TITLE"
Para crear el cron:
cronjob action=create name="hermes-deploy-watch" schedule="every 3m" \
script="deploy-watch.sh" no_agent=true deliver=origin
Zero infra nueva: usa gh CLI ya autenticado, no requiere endpoints HTTP, webhooks en GitHub, ni modificar el pipeline.
Límite: hasta 3 minutos de latencia (el intervalo del cron). Para notificación en tiempo real sin polling, usar GitHub webhooks (references/github-webhooks-autonomous-monitoring.md).
⚠️ Preferencia del usuario: El usuario pidió explícitamente hooks (webhooks), no polling. El cron es solución temporal. Migrar a webhooks (Opción 1 en la referencia) cuando sea posible.
systematic-debugging — for root cause analysis of failuresgithub-pr-workflow — for PR and branch managementtest-driven-development — for test-first approach to fixesEsta skill trabaja con infraestructura y despliegues. Por lo tanto:
⚠️ Pre-flight (OBLIGATORIO — ver sección arriba): Antes de empezar, ejecuta recall(bank="toolset", query="infraestructura, despliegues recientes, estado del pipeline"). Fue instrucción directa del usuario no omitir este paso.
Post-action persist: Al completar un deploy o diagnóstico, ejecuta retain(bank="toolset", content="deploy: <commit>, resultado: ✅/❌, issues: <lista>", tags=["deploy", "YYYY-MM-DD"]).