Aller au contenu
Hermès Skills
← Retour au catalogue

autonomous-deployment-mission

Execute multi-phase service deployments autonomously with safety guards, journaling, and a morning report — Phase 0 diagnostics, sequential deployment, anti-gaspillage budgets, escalation policy.

Quand l'utiliser (Trigger)

Déclenchement standard selon le contexte de l'écosystème Hermès.

Mode d'emploi (Usage)

Mode d'emploi standard via l'agent Hermès.

Autonomous Deployment Mission

When to Use

You are acting as a senior DevOps engineer in autonomous overnight mode. The user has given you a multi-component deployment mission and expects you to execute it unattended with full safety, tracking, and a morning report.

Use this skill when:

  • You are deploying 2+ interconnected services (observability + orchestration + agents, etc.)
  • The session is expected to run unattended (user asleep, working other tasks)
  • The user has given explicit security constraints and budgets
  • There is a deliverable (morning report) expected at the end

Mission Structure

A deployment mission follows an invariant 8-phase structure:

Phase 0 — Diagnostics     (system state, prerequisites, constraints)
Phase 1..N — Deploy       (one service at a time, verify each)
Phase N+1 — Integrate      (wire services together)
Phase N+2 — Operate       (test end-to-end, verify traces/propagation)
Phase Final — Report       (RAPPORT.md handoff)

Rule: Never skip Phase 0. Never skip Phase Final. Never deploy service N+1 before service N is verified healthy.

Phase 0 — Diagnostics (Mandatory First Step)

Before any action, establish the system baseline:

# OS + resources
cat /etc/os-release | head -3
uname -a
free -h
df -h /

# Docker/Compose availability
docker --version
docker compose version 2>/dev/null || echo "compose plugin missing"
groups $USER | grep docker && echo "user in docker group" || echo "sudo needed"

# Node/nvm/pnpm
node -v 2>/dev/null || echo "node missing"
pnpm -v 2>/dev/null || echo "pnpm missing"
which nvm && nvm ls 2>/dev/null

# Port availability — check if target ports are free
ss -tlnp | grep -E ':(3000|3100|8080|5173)\b' || echo "target ports free"

# Current directory structure
ls ~/agent-stack/ 2>/dev/null || echo "~/agent-stack/ does not exist"

Output the diagnostic summary to the user. Do not proceed beyond Phase 0 without user stepping in to approve or give further direction, unless the user has explicitly stated they are asleep and to proceed independently.

Phase 1..N — Sequential Service Deployment

Core Principle: One Phase at a Time

START → Diagnostics → Deploy Svc 1 → Verify → Deploy Svc 2 → Verify → Integrate → Operate → Report

NEVER deploy two services in parallel. NEVER start deploy of Svc N+1 until Svc N’s health check passes.

Per-Service Template

For each service, follow this sub-pattern:

  1. Source: Get official Docker Compose file or install docs. Do NOT guess compose structure.
  2. Secrets: Generate with openssl rand -hex 32, store in .env with chmod 600.
  3. Deploy: docker compose up -d (or equivalent install command).
  4. Health Wait: Loop until all containers healthy (30-60s typical).
  5. API Verify: curl -s -o /dev/null -w "%{http_code}" http://localhost:<port> → expect 200.
  6. Credentials Capture: Admin email/password (auto-provisioned or generated).
  7. Key Capture: API keys, tokens, OTel endpoints — store paths in PROGRESS.md.
  8. Patch Config: Any config needed for remote access (Tailscale, etc.).

Safety Contract (Non-Negotiable)

These rules must be in the mission brief and followed without exception:

Absolute Rules

  1. No destructive commands outside project dir: rm -rf only within ~/agent-stack/ or service directory. Never system paths, never existing data volumes without explicit approval.
  2. Secrets in .env chmod 600: Never displayed in logs, reports, or skill files. Mask as pk-***, sk-***.
  3. Ports on localhost only: Unless remote access is explicitly needed (Tailscale, reverse proxy), bind to 127.0.0.1.
  4. No unnecessary network access: Don’t install packages not needed for the deployment.

Anti-Gaspillage Budgets

  1. Max 5 attempts per step: If a step fails 5 times, stop that step, log the blocker, and move to what is achievable.
  2. Max 3 hours total: If the mission exceeds 3 hours, save state and stop. Do not start new phases.
  3. Loop detection: If a sub-agent repeats the same error 3 times, kill it and fall back to manual approach.
  4. Token budget awareness: Before each delegation, ask “can I do this myself in <5 attempts?” If yes, don’t delegate.

Escalation Policy

  • Do NOT wake the user for anything short of irrecoverable destruction
  • Log every blocker in PROGRESS.md with: what was attempted, what failed, what was tried
  • If ALL progress is blocked (no safe alternative path) → secure containers, write final RAPPORT.md, and stop

Progress Journal (PROGRESS.md)

Created at ~/agent-stack/PROGRESS.md at the start of the mission. Updated after every phase completion (not every tool call — keep it to state transitions).

Format

# Agent Stack — Progress Journal

## [YYYY-MM-DD HH:MM] Phase N — Phase Name
- **Action**: What was done
- **Result**: ✅ / ❌ / ⏸
- **Agent**: self / claude / codex / gemini
- **Tokens**: ~N (estimated)
- **Decisions**: Key choices made
- **Blockers**: What stopped or was skipped (if any)

What to log

  • Phase boundaries only (start/end of each Phase 0, 1, 2, etc.)
  • Blocker entries (what failed + what was attempted)
  • Key credentials captured (file paths where they’re stored, not the values)
  • Config changes (file paths, what was changed, why)

What NOT to log

  • Every curl or docker ps call
  • Intermediate debug output
  • Versions/dates that are obvious from context

Delegation Rules (Budget-Aware)

Follow the 5-attempt rule for both self-execution and delegation:

Can I do this in <5 attempts myself?
  ├─ YES → Do it directly (save tokens)
  └─ NO → Delegate with a MINIMAL context prompt:
           • Only the file paths and error messages needed
           • Never the full conversation history
           • One task per delegation
TypeDelegation TargetWhen
Debugging complex Docker/networking errorsClaude CodeUnusual compose failures, ClickHouse tuning
Script generation, refactoringCodex CLIRepetitive code tasks, adapter generation
Large doc reading, synthesisGemini CLITracking down upstream docs, understanding API surfaces

Multi-Session Resume Protocol

When the user returns mid-mission with “continue” / “continuer la tâche en cours” / “resume” / “next” — do NOT assume fresh start. Follow this protocol:

Step 1 — State Reconstruction

Run all of these in parallel (they’re independent):

# A — Search conversation history for the last session's state
# (use session_search with the project name or "PROGRESS" as query)

# B — Check service health (services may still be running from last session)
docker ps --format "table {{.Names}}\t{{.Status}}"
curl -s http://localhost:3000/api/public/health 2>/dev/null || echo "Langfuse down"
curl -s http://localhost:3100/api/health 2>/dev/null || echo "Paperclip down"

# C — Read the progress journal
cat ~/agent-stack/PROGRESS.md

# D — Check shared cross-machine log (if applicable on multi-machine setups)
cat ~/shared_log.md 2>/dev/null | tail -20

Step 2 — Compare Expected vs Actual State

Build a picture of what SHOULD be running vs what IS running:

ServiceShould BeActually IsAction
Langfuse (Docker)6 containers healthy?Start if down
Paperclip (process)Running on :3100?Start if down

Pitfall: A service may appear healthy but its config may have changed. Always re-read the .env and config files to check for required next-step modifications.

Step 3 — Update PROGRESS.md to Reality

The PROGRESS.md from the previous session was written in plan format (future tense, “Phase 1 — Deploy X”). Now transform it into status format (past tense, “Phase 1 ✅ — deployed with 6 containers”). This gives the user accurate context and avoids confusion about what was actually done vs planned.

Step 4 — Identify Decision Points

Multi-phase deployments often have multiple valid next steps. Present a prioritized menu when the user returns mid-mission:

Currently running: Langfuse ✅, Paperclip ✅
Next available steps:
  1. Configure provider LLM ← enables agent task execution
  2. Connect observability (Paperclip → Langfuse)
  3. Add more agents (Codex, Gemini)
  4. Test E2E

Ask the user for priority — don’t guess which step they want next.

Morning Report (RAPPORT.md)

Written at ~/agent-stack/RAPPORT.md at mission end (success or stop). It is the single deliverable the user reads over coffee.

Report Template

# Rapport du Matin — Agent Stack

Date: YYYY-MM-DD

## 1. STATUT GLOBAL
✅ / ⏸ / ❌

## 2. Ce qui fonctionne (avec URLs)
- Service A: [URL](http://x.x.x.x:PORT) — description
- Service B: [URL](http://x.x.x.x:PORT) — description
- Intégration: trace E2E visible dans Langfuse ✅

## 3. Ce qui a bloqué
- Blocage 1: Ce qui s'est passé, pourquoi, ce qui a été tenté
- Blocage 2: ...

## 4. Décisions qui t'attendent
- Action irréversible X dont tu n'as pas voulu (ex: drop DB volume)
- Configuration Y à valider

## 5. Coût estimé (tokens)
| Phase | Hermes | Claude | Codex | Gemini |
|-------|--------|--------|-------|--------|
| 0     | ~2K    | —      | —     | —      |
| 1     | ~N     | ~N     | ~N    | ~N     |
| Total | ~N     | ~N     | ~N    | ~N     |

## 6. Prochaines étapes
- Migration VPS sous Coolify
- Ajout service X
- ...

## 7. Runbook
### Démarrer
```bash
cd ~/agent-stack/<service> && docker compose up -d

Arrêter

cd ~/agent-stack/<service> && docker compose down

Vérifier l’état

docker compose -f ~/agent-stack/<service>/docker-compose.yml ps

Sauvegarder

# Which volumes to back up
docker volume ls --filter label=com.docker.compose.project=<project>

Dépanner

  • Symptôme X → Cause Y → Solution Z

8. Actions humaines restantes

  • Action 1 (à faire par toi)
  • Action 2 (à faire par toi)

## Reference Files

This skill ships with detailed deployment references for specific services:

| File | Covers |
|------|--------|
| `references/langfuse-deployment.md` | Full Langfuse Docker Compose flow, API key recovery, OTel endpoint, auth, NEXTAUTH_URL gotcha, port safety, pitfalls |
| `references/paperclip-deployment.md` | Paperclip pnpm-based install, mode switching (local_trusted/authenticated), hostname restriction fix, Better-Auth gotchas, restart sequence, Langfuse integration |
| `references/hermes-credential-pool-keys.md` | How Hermes credential_pool manages API keys at runtime (env: sourcing, HERMES_REDACT_SECRETS masking), discovery protocol when keys are needed for external services, when to ask the user vs keep documenting |
| `references/paperclip-local-adapters.md` | Paperclip built-in adapter types for local CLI subscriptions (claude_local, codex_local, gemini_local, hermes_local), architecture pattern (API key orchestrator + local CLI agents), CLI auth commands, trade-offs vs cloud APIs |

Load these when deploying the respective service.

## Docker Compose Technical Reference

For the low-level Docker Compose mechanics used in deployments — binary installation (sudo-less), secret generation, .env security, health verification, port binding patterns, volume management, and remote access via Tailscale — see `references/docker-compose-deployment.md`. Specific service deployment references are also listed in the table above.

## Service Interdependency Patterns

### Observability Pattern (Langfuse + Orchestrator + Agents)

Langfuse (traces storage) ↑ Paperclip (orchestrator) ←→ Agent A (Claude Code) ↑ Agent B (Codex CLI) ↑ Agent C (Gemini CLI) └── Hermes (meta-orchestrator, writes PROGRESS.md)


**Key integration points:**
- Paperclip project `.env` contains `LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, `LANGFUSE_BASE_URL`
- Agents push OTel traces to Langfuse endpoint at `/api/public/otel/v1/traces`
- Auth: `Authorization: Basic <base64(pk:sk)>`
- Each agent's span should include the Paperclip `trace_id` for cross-service correlation

### Remote Access Pattern (Docker + Tailscale + No Reverse Proxy)

[User Windows] — Tailscale — [Linux Server] │ │ │ http://100.x.x.x:3000 ──────► Langfuse (0.0.0.0:3000) │ http://100.x.x.x:3100 ──────► Paperclip (0.0.0.0:3100)


**No reverse proxy needed** when services bind to `0.0.0.0` and Tailscale routes traffic directly to the server's network interface. The Tailscale IP (`100.x.x.x`) behaves like any other network IP — any service listening on `0.0.0.0` is reachable.

Exception: services that enforce loopback binding (like Paperclip's `local_trusted` mode). These require mode-switching or SSH tunnels.

## Pitfalls

- **Deploying two services at once**: You lose the ability to isolate which failure belongs to which service. One phase at a time, always.
- **Skipping diagnostics**: 80% of "mysterious failures" are uncovered in Phase 0 (wrong node version, port already in use, disk full).
- **Logging secrets in PROGRESS.md**: The journal must contain file paths to secrets, not the secrets themselves. If the journal leaks, keys must be rotated.
- **Running 3+ hours without checkpoint**: If the mission exceeds 3 hours, future-you will thank present-you for saving state. Write RAPPORT.md even mid-mission.
- **Trusting "obvious" error messages**: A `connection refused` on Tailscale IP is usually a loopback bind issue, not a service failure.
- **Forgetting the morning report**: The user doesn't read your terminal history. RAPPORT.md is the only deliverable that matters.
- **Config fix applied but restart blocked by safety**: After patching a config file (`.env`, etc.), the service must reload to pick it up. The `docker compose restart` command is often blocked by terminal safety because it's classified as service-disruption. Don't retry with different syntaxes — present the blocker clearly to the user: state what was changed, confirm the operation is safe (no data loss, no volume drop, clean config reload), and ask for explicit approval. This is a natural human-in-the-loop checkpoint, not a failure.