v0.11.0
skills/migrations/v0.11.0.md
version: 0.11.0 feature_pitch: headline: "GBrain Minions — durable background agents" description: "Turn any long-running agent task into a durable job that survives gateway restarts, streams progress, and can be paused, resumed, or steered mid-flight. Postgres-native, zero infra beyond your existing brain. Replaces flaky subagent spawns for multi-step work, parallel fan-out, and anything the user might ask about later." recipe: null tiers: null
v0.11.0 Migration: Minions — host-agent instruction manual
Audience: host agents (OpenClaw deployments, future
hosts) reading this AFTER gbrain apply-migrations has run its
mechanical phases. The orchestrator in
src/commands/migrations/v0_11_0.ts is the runtime source of truth for
the mechanical work (schema, smoke, prefs, built-in cron rewrites,
autopilot install). This file tells the host agent how to finish the
host-specific work that can't be done host-agnostically.
Check what gbrain left you
cat ~/.gbrain/migrations/pending-host-work.jsonl
Empty? You're done. The migration is complete; nothing for you to do.
Non-empty? Each line is a TODO. Each type routes to a section below.
type: cron-handler-needs-host-registration
Gbrain rewrites cron entries whose handler name matches a gbrain
builtin (sync, embed, lint, import, extract, backlinks,
autopilot-cycle). For host-specific handlers (e.g. ea-inbox-sweep,
frameio-scan, x-dm-triage, calendar-sync on your OpenClaw), gbrain
leaves the manifest alone and emits a TODO with shape:
{
"type": "cron-handler-needs-host-registration",
"handler": "ea-inbox-sweep",
"cron_schedule": "0 */30 * * *",
"manifest_path": "/path/to/cron/jobs.json",
"current_cmd": "agentTurn ea-inbox-sweep",
"recommendation": "Add a handler registration for ...",
"status": "pending"
}
Each TODO is a full skillify, not a drive-by handler add. A properly
migrated cron meets every one of these gates before its JSONL row gets
marked complete:
(a) Plugin contract
Read docs/guides/plugin-handlers.md. Add a worker.register() call
in your host's worker bootstrap:
import { MinionQueue, MinionWorker } from 'gbrain/minions';
const worker = new MinionWorker(engine, { queue: 'default' });
worker.register('ea-inbox-sweep', async (ctx) => {
// Host-specific agent turn.
});
// ...register every TODO handler...
await worker.start();
(b) Ship the bootstrap in your host repo
Autopilot already spawns gbrain jobs work as a child. Configure it to
spawn your custom worker binary (e.g. your-openclaw-worker) instead, or
register handlers as a side-effect module that the stock worker loads on
startup. Either path is documented in plugin-handlers.md.
(c) Unit tests for the handler body
Mock the LLM. Assert the happy path, the empty-input path, the network-timeout path, the LLM-failure path. Every branch of the handler's deterministic logic has a unit test.
(d) Integration tests
Submit a real Minion job against your test environment. Assert:
- The job completes (not dead-lettered).
- The side effects happen (brain pages written, external API called).
- The result shape matches what your cron consumers expect.
(e) LLM evals
Whatever prompt the handler runs, add a case in your eval suite. At minimum: one happy case, one edge case, one adversarial case. If the handler's job is "sweep the EA inbox," the eval asserts urgent items surface and routine items don't.
(f) Resolver trigger update
The host's AGENTS.md dispatcher used to reference the skill name
(ea-inbox-sweep) as an agentTurn route. Rewrite that route to
submit_job with the same trigger phrases — the user-facing language
doesn't change; the execution path does.
(g) Resolver trigger eval
Add a test: feed each trigger phrase to the resolver, assert it routes
to the new submit_job path, not the old agentTurn. Without this
test, your router can silently keep old behavior and nobody notices
until the cron quietly breaks.
(h) E2E smoke
One test that exercises the full pipeline: scheduler → gbrain jobs submit → worker claim → handler body → side effect. Gated by your
host's E2E DB fixture.
(i) Brain filing
If the handler writes brain pages, brain/RESOLVER.md needs an entry
for the directory. Orphaned brain pages are worse than no brain pages —
nobody can find them on read.
(j) check-resolvable
Run gbrain check-resolvable. It validates reachability (is the skill
mentioned from RESOLVER.md?), MECE overlap, DRY, gap detection. If it
fails, fix the skill or extend an existing one instead of creating a
duplicate.
Finalize
When all ten gates are green for a handler:
gbrain apply-migrations --yes
The orchestrator detects the newly-registerable handler, rewrites the
cron entry from agentTurn ea-inbox-sweep to gbrain jobs submit ...
with the right engine-aware form (PGLite uses --follow; Postgres uses
fire-and-forget + --idempotency-key), and marks the JSONL row
status: "complete".
Iron rule: scripts/skillify-check.ts <handler-code-path> must
return 10/10 before you mark a handler migrated. No partial-credit
"we'll add tests later." See skills/skillify/SKILL.md for the meta.
type: agents-md-dispatcher-needs-host-review
Gbrain injects a marker into each AGENTS.md pointing to
skills/conventions/subagent-routing.md. But if your dispatcher has
inline sessions_spawn routing logic (custom branching on tool names
or intent patterns), that's not a mechanical rewrite — it involves host
judgment about which routes should flip to submit_job and which should
stay on sessions_spawn for real-time tasks.
Read skills/conventions/subagent-routing.md. Walk your dispatcher's
sessions_spawn blocks. For each one, decide:
- Brain-write, multi-step, user will ask later → route through
submit_job(Minions). - Real-time, user waiting, < 30s → keep on
sessions_spawn. - Somewhere in between →
minion_mode: pain_triggeredis the right default; let the convention's pain signals decide.
Mark the JSONL row status: "complete" by appending a new line with
the same shape + updated status. Or: edit the dispatcher, rerun
gbrain apply-migrations, and let gbrain re-detect + update
automatically (it dedupes on file path, so no duplicate rows).
When every TODO clears
gbrain apply-migrations --list
Should show v0.11.0 as applied. Your host is fully migrated to
Minions. Autopilot is dispatching through the queue, cron jobs are
durable, and every handler you registered appears in
worker.registeredNames on next worker startup.
Related
skills/migrations/index.ts(code, not file) — the TS registry the runtime consults;apply-migrations --listreads from here, not from this markdown file.skills/conventions/cron-via-minions.md— the rewrite pattern gbrain applies for builtins + the one your host ships for custom handlers.skills/conventions/subagent-routing.md— runtime dispatcher rules (native subagent vs Minion) that AGENTS.md should reference.docs/guides/plugin-handlers.md— the plugin contract for host handler registration.skills/skillify/SKILL.md— the 10-item checklist every handler must pass before its JSONL row clears.scripts/skillify-check.ts— machine-readable version of the checklist; use with--jsonin CI.docs/guides/minions-fix.md— user-facing troubleshooting for broken-v0.11.0 installs that never ran the migration at all.