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.
This commit is contained in:
parent
21a630cd93
commit
c62bbd3d7e
1 changed files with 163 additions and 0 deletions
163
skills/mother/SKILL.md
Normal file
163
skills/mother/SKILL.md
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
---
|
||||||
|
name: mother
|
||||||
|
description: 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.
|
||||||
|
triggers:
|
||||||
|
- "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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
```bash
|
||||||
|
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._
|
||||||
Loading…
Add table
Reference in a new issue