- 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.
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. |
|
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)
.envfile present in the agent's home directory (written bycolibri-vault)colibri-daemonreachable — either on a local Unix socket (osa) or via the TCP bridge over Tailscale (remote hosts)colibribinary 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
.envto/home/clawdie/.envinside 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/runis tmpfs —mkdir -p /var/run/colibribefore connecting
Linux container (debby, domedog)
- The vault writes
.envto~/.env - The socket is a socat bridge at
/tmp/osa-colibri.sockpointing 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.