SKILL.md 技能文档
能力目标
让 Agent 把 GBrain 切到 Postgres 后端、起 Minions 任务队列的 supervisor,提交 job 并在 worker 硬崩溃(kill -9)后由 supervisor 自动重启、job 恢复执行,验证任务队列的 durability,最后优雅停止。
前置
- Minions 的 supervisor/worker 强制要求 Postgres 后端——PGLite 上起 supervisor 直接报错退出。
- 需要 Docker(起 Postgres 容器)。镜像必须用
pgvector/pgvector:pg16(内置 pgvector)、不能用官方postgres:16(缺 vector extension,init 会报extension 'vector' is not available)。 - shell job 有双层权限护栏:supervisor 端
--allow-shell-jobs(控制 worker 执行权限)+ submit 端GBRAIN_ALLOW_SHELL_JOBS=1(控制提交权限),两者缺一不可。
实操流程
起 Postgres 容器并切后端。切 Postgres 的正确参数是
--supabase(--to postgres不存在,--supabase是内部对 Postgres engine 的映射名):docker run -d --name gbrain-pg -p 5432:5432 \ -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=gbrain pgvector/pgvector:pg16 docker ps mkdir -p "$BRAIN_DIR" && cd "$BRAIN_DIR" gbrain init --supabase --url "postgres://postgres:postgres@localhost:5432/gbrain" cat ~/.gbrain/config.json # 应含 "engine": "postgres"init 一次建好所有 schema,含带 9-status CHECK 约束的
minion_jobs表。启动 supervisor(后台常驻、spawn worker、监控 crash 自动重启):
gbrain jobs supervisor start --detach --json --allow-shell-jobs gbrain jobs supervisor status --json # running=true, crashes_24h=0--detach后台运行、--json输出 JSONL、--allow-shell-jobs允许 worker 执行 shell job。提交一个长跑 shell job。shell job 必须提供绝对路径
cwd(安全护栏,否则报cwd is required and must be an absolute path);--idempotency-key建 UNIQUE 约束、同 key 只入队一次:GBRAIN_ALLOW_SHELL_JOBS=1 gbrain jobs submit shell \ --params '{"cmd":"sleep 120 && echo DONE >> /tmp/job3.txt","cwd":"/tmp"}' \ --idempotency-key "kill-demo-001" sleep 5 # 等 worker claim模拟硬崩溃:kill -9(SIGKILL 内核直接终止、进程无机会清理,模拟 OOM / 断电):
WORKER_PID=$(ps aux | grep "gbrain jobs work" | grep -v grep | awk '{print $2}') kill -9 $WORKER_PID gbrain jobs supervisor status --json # crashes_24h=1, oom_or_external_kill=1, running 仍 truesupervisor 检测到子进程退出后经 backoff 延迟立即 spawn 新 worker(SIGKILL 场景不等 35s drain window,那是 SIGTERM 优雅关闭才有的)。
验证 job 恢复并优雅停止:
docker exec gbrain-pg psql -U postgres -d gbrain -c \ "SELECT id, status, attempts_started FROM minion_jobs WHERE idempotency_key='kill-demo-001';" gbrain jobs stats gbrain jobs supervisor stop # SIGTERM → 35s drain window,worker 跑完当前 job 再退
校验回路
gbrain jobs supervisor status --json起后running=true;kill -9 后crashes_24h+1、crashes_by_cause.oom_or_external_kill+1、running仍 true、max_crashes_exceeded=false。- 崩溃的 job 最终
status=completed、attempts_started=2(旧 worker + 新 worker 各启动过一次)。 - audit log(
~/.gbrain/audit/supervisor-YYYY-Www.jsonl)含worker_exited(SIGKILL)→backoff→worker_spawned时间线。 gbrain jobs stats显示各类型 job 的 done/failed/dead 计数、Queue health无积压。
常见陷阱
- shell job resume 是从头重跑、不是 checkpoint 续跑:kill -9 后
lock_until过期,supervisor 的handleStalled()把 status 从 active 转回 waiting、新 worker 从头 claim。idempotency_key只防同一 job 重复入队、不防已入队 job 重复执行。写文件用追加模式>>(不是覆盖>)能从输出行数看出是否重跑过;job 执行逻辑应尽量幂等。 --allow-shell-jobs加错位置:必须加在 supervisor 启动命令上。加在 submit 端只影响 audit、不给 worker 执行权限——supervisor 没带这个 flag 的话,shell job 被 claim 后立即以UnrecoverableError标 dead。- exponential backoff 曲线:
backoff_ms = base_delay(1000) × 2^(crash_count-1) × (1 + 0.2×random()),理论 cap 60000ms。jitter 20% 随机扰动是为防多 worker 同时 crash 后同时重启形成 thundering herd 冲击 DB。crash 达max_crashes(默认 10)时 supervisor 自身 exit 1、把重启责任交给外层进程管理器。 - 9 status 由 Postgres CHECK 约束强制:waiting / active / completed / failed / delayed / dead / cancelled / waiting-children / paused,任何非法值在 DB 层被拒(比应用层校验可靠)。
- 生产要二层 supervision:supervisor 自身也是用户态进程,用 systemd(Linux)/ launchd(macOS)守护 supervisor,形成 supervisor 守 worker、systemd 守 supervisor 的两层结构。
适用范围与前置条件
- Minions 的 supervisor/worker 强制要求 Postgres 后端——PGLite 上起 supervisor 直接报错退出。
- 需要 Docker(起 Postgres 容器)。镜像必须用
pgvector/pgvector:pg16(内置 pgvector)、不能用官方postgres:16(缺 vector extension,init 会报extension 'vector' is not available)。 - shell job 有双层权限护栏:supervisor 端
--allow-shell-jobs(控制 worker 执行权限)+ submit 端GBRAIN_ALLOW_SHELL_JOBS=1(控制提交权限),两者缺一不可。
怎么使用
使用步骤
起 Postgres 容器并切后端。切 Postgres 的正确参数是
--supabase(--to postgres不存在,--supabase是内部对 Postgres engine 的映射名):docker run -d --name gbrain-pg -p 5432:5432 \ -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=gbrain pgvector/pgvector:pg16 docker ps mkdir -p "$BRAIN_DIR" && cd "$BRAIN_DIR" gbrain init --supabase --url "postgres://postgres:postgres@localhost:5432/gbrain" cat ~/.gbrain/config.json # 应含 "engine": "postgres"init 一次建好所有 schema,含带 9-status CHECK 约束的
minion_jobs表。启动 supervisor(后台常驻、spawn worker、监控 crash 自动重启):
gbrain jobs supervisor start --detach --json --allow-shell-jobs gbrain jobs supervisor status --json # running=true, crashes_24h=0--detach后台运行、--json输出 JSONL、--allow-shell-jobs允许 worker 执行 shell job。提交一个长跑 shell job。shell job 必须提供绝对路径
cwd(安全护栏,否则报cwd is required and must be an absolute path);--idempotency-key建 UNIQUE 约束、同 key 只入队一次:GBRAIN_ALLOW_SHELL_JOBS=1 gbrain jobs submit shell \ --params '{"cmd":"sleep 120 && echo DONE >> /tmp/job3.txt","cwd":"/tmp"}' \ --idempotency-key "kill-demo-001" sleep 5 # 等 worker claim模拟硬崩溃:kill -9(SIGKILL 内核直接终止、进程无机会清理,模拟 OOM / 断电):
WORKER_PID=$(ps aux | grep "gbrain jobs work" | grep -v grep | awk '{print $2}') kill -9 $WORKER_PID gbrain jobs supervisor status --json # crashes_24h=1, oom_or_external_kill=1, running 仍 truesupervisor 检测到子进程退出后经 backoff 延迟立即 spawn 新 worker(SIGKILL 场景不等 35s drain window,那是 SIGTERM 优雅关闭才有的)。
验证 job 恢复并优雅停止:
docker exec gbrain-pg psql -U postgres -d gbrain -c \ "SELECT id, status, attempts_started FROM minion_jobs WHERE idempotency_key='kill-demo-001';" gbrain jobs stats gbrain jobs supervisor stop # SIGTERM → 35s drain window,worker 跑完当前 job 再退