layered-soul/skills/mother/SKILL.md
Sam & Claude c62bbd3d7e feat(mother): draft genesis skill — join-the-hive sequence
- Resolve identity: hostname, OS, capability probe
- Verify vault: .env exists + contains API key
- Register agent: idempotent, safe to re-run
- Heartbeat + poll loop: stay alive on the board

Platform-specific paths for FreeBSD jail vs Linux
container, security invariant documented, cross-linked
with HIVE-ONBOARDING and CAPABILITY-ROUTING.
2026-06-19 21:48:48 +02:00

5.8 KiB

name description triggers
mother Genesis sequence for a new agent joining the Clawdie hive — resolve identity, verify vault provision, register capabilities on the Colibri board, and start the heartbeat/poll loop. Idempotent — safe to re-run on an already-provisioned agent.
join the hive
mother skill
genesis sequence
onboard this agent
register with colibri
first boot
new agent setup
provision agent

Mother Skill — Agent Genesis

Trigger: the agent wakes up in a freshly-provisioned jail (or container) and needs to join the hive. The vault has already written a .env into the jail root by the time this skill runs — the agent's job is to verify, register, and start polling.

Prerequisites (must already exist before this skill runs)

  • .env file present in the agent's home directory (written by colibri-vault)
  • colibri-daemon reachable — either on a local Unix socket (osa) or via the TCP bridge over Tailscale (remote hosts)
  • colibri binary in PATH (or at a known location)
  • The agent knows its own hostname and OS (hostname, uname)

Genesis Sequence

Run these steps in order. The skill is idempotent — if an agent already has an agent_id and is registered, skip the registration step and go straight to polling.

1. Resolve identity

Determine what this agent IS before registering:

HOST=$(hostname)
OS=$(uname -s | tr '[:upper:]' '[:lower:]')

Capability tags are derived from what's actually installed and reachable on this host. Use the Host Matrix as reference (docs/HOST-MATRIX.md in layered-soul), but the ground truth is scripts/verify_facts_probe.py.

Minimum base tags every agent should carry:

Tag Source
freebsd or linux uname -s
shell always present
hermes if Hermes Agent is installed
tailscale if tailscale status succeeds

Additional tags per the Capability Vocabulary in docs/CAPABILITY-ROUTING.md: jail isolation (freebsd-jail), hardware (zfs, gpu), runtimes (python3.12, rust, node24), media (ffmpeg, image-render).

2. Verify vault provision

Confirm the vault did its job — the .env must contain at least one valid API key:

test -f ~/.env && grep -q '_API_KEY=' ~/.env && echo "vault: provisioned" || echo "vault: MISSING — .env absent or empty"

If missing, this agent cannot authenticate to any provider. Report the error and halt — a human operator must re-run colibri-vault provision.

3. Register with Colibri

Check if already registered (by name, not UUID — the daemon enforces UNIQUE on names):

# Check if agent already exists
colibri --socket $COLIBRI_SOCKET list-agents | grep -q "\"$AGENT_NAME\""

If NOT registered, register with capabilities derived from Step 1:

colibri --socket $COLIBRI_SOCKET register-agent "$AGENT_NAME" \
  --capabilities freebsd,shell,hermes,tailscale,rc.d,pf,zfs

The COLIBRI_SOCKET path depends on the host:

Host Socket path
osa (FreeBSD, local daemon) /var/run/colibri/colibri.sock
Remote hosts (via socat bridge) /tmp/osa-colibri.sock

If registration fails (e.g., name collision), log the error and continue — the agent may already be registered under a different name, or the board may be unreachable. The poller will surface this on its next tick.

4. Start heartbeat and poll loop

The agent is now a member of the hive. Two recurring jobs keep it alive:

Heartbeat (every 5 min): update agent status on the board so the scheduler knows this agent is still alive and can receive tasks.

colibri --socket $COLIBRI_SOCKET set-agent-status "$AGENT_NAME" active

Poll loop (every 2 min): check the board for tasks assigned to this agent. On osa and debby, this runs inside Hermes' internal scheduler — see colibri/packaging/freebsd/colibri-agent-loop.md for the Hermes cronjob setup.

For a bare agent without Hermes cron, a minimal poll loop:

while true; do
  colibri --socket $COLIBRI_SOCKET list-tasks --status started \
    | colibri_poll.py   # filters by agent UUID, outputs JSON
  sleep 120
done

Platform-specific notes

FreeBSD jail (osa)

  • The vault writes .env to /home/clawdie/.env inside the jail
  • The daemon socket is at /var/run/colibri/colibri.sock (mounted or shared)
  • Capabilities include freebsd-jail, zfs (if zpool is visible), rc.d
  • The jail's /var/run is tmpfs — mkdir -p /var/run/colibri before connecting

Linux container (debby, domedog)

  • The vault writes .env to ~/.env
  • The socket is a socat bridge at /tmp/osa-colibri.sock pointing to osa:9190
  • Capabilities include docker (if Docker socket is mounted), image-render (if Pillow/FFmpeg are installed)
  • Start the socat shim before the poll loop:
    socat UNIX-LISTEN:/tmp/osa-colibri.sock,fork TCP:${OSA_TS_IP}:9190 &
    

Idempotency contract

This skill can be re-run at any time without breaking a live agent:

Step Re-run behavior
Resolve identity Safe — hostname and OS don't change
Verify vault Safe — checks file existence, no side effects
Register agent Name collision = benign error (already registered)
Heartbeat/poll Safe — daemon ignores duplicate status updates

Security invariant

The .env file is 0600 (written by colibri-vault with Permissions::from_mode(0o600)). It contains the agent's ONE provider key — never the Vaultwarden org service-account credential. A compromised jail can use its own key but cannot reach another tenant's collection or the vault bootstrap credential.

See docs/HIVE-ONBOARDING.md for the full onboarding vision, docs/CAPABILITY-ROUTING.md for the routing layer, and colibri/packaging/freebsd/colibri-agent-loop.md for the Hermes cronjob setup.