gbrain discovers subagent definitions from outside this repo via
GBRAIN_PLUGIN_PATH. If you maintain a downstream agent (your OpenClaw
deployment, a workflow host, a private tool) and want to ship custom
subagents alongside it, drop a plugin directory on that env path.
This guide is for plugin authors. The CLI user doesn't need to read it.
/path/to/my-plugin/
├── gbrain.plugin.json
└── subagents/
└── my-summarizer.md
gbrain.plugin.json:
{
"name": "my-plugin",
"version": "1.0.0",
"plugin_version": "gbrain-plugin-v1"
}subagents/my-summarizer.md:
---
name: my-summarizer
model: claude-sonnet-4-6
allowed_tools:
- brain_search
- brain_get_page
---
You are a brain page summarizer. Given a slug, fetch the page and produce
a 3-sentence summary.export GBRAIN_PLUGIN_PATH="/path/to/my-plugin"
gbrain jobs work # worker startup prints the plugin load line
gbrain agent run "summarize meetings/2026-04-20" --subagent-def my-summarizerMultiple plugins: colon-separated, just like $PATH.
export GBRAIN_PLUGIN_PATH="/path/to/plugin-a:/path/to/plugin-b"Path policy. Absolute paths only. Relative paths, ~-prefixed paths,
and URL-style paths (https://, file://) are rejected with a warning.
You control where your plugin lives on disk; gbrain doesn't guess.
Collision policy. If two plugins ship a subagent with the same name,
the one listed FIRST in GBRAIN_PLUGIN_PATH wins. The other is dropped
with a warning naming both sources.
Trust policy. Plugins ship subagent definitions ONLY in v0.15:
- You cannot declare new tools.
- You cannot extend the brain tool allow-list.
- You cannot override any
agentSafeor similar flag. - Your
allowed_tools:frontmatter field MUST subset the derived brain tool registry. Names not in the registry are rejected at plugin load time (worker startup), NOT at subagent dispatch time — so a typo in your plugin gives you a loud startup error, not a silent "tool never fires" at 3am.
v0.16+ may open up plugin-declared tools with a separate contract. Don't expect it.
| field | type | required | notes |
|---|---|---|---|
name |
string | yes | Human-readable plugin id. Shows up in warnings and collision logs. |
version |
string | yes | Your plugin's semver. Informational. |
plugin_version |
string | yes | Contract lock. Must equal "gbrain-plugin-v1" for v0.15. |
subagents |
string | no | Subdir name (default subagents). Escape-attempts are rejected. |
description |
string | no | Shown in future gbrain plugin list. |
Plain markdown with YAML frontmatter. The body is the system prompt. The frontmatter controls runtime behavior.
Recognized frontmatter fields:
| field | type | required | notes |
|---|---|---|---|
name |
string | no | Subagent identifier used as --subagent-def. Defaults to the file basename. |
model |
string | no | Anthropic model id. Defaults to the handler default (sonnet). |
max_turns |
number | no | Cap on assistant turns. Defaults to 20. |
allowed_tools |
string[] | no | Whitelist of tool names. Must subset the derived brain registry. Rejected on mismatch. |
Unknown frontmatter fields are preserved but ignored by the handler. v0.16 may consume more of them.
-
Plugin definitions can't change during a run. The loader reads the disk once at worker startup. Editing a subagent def doesn't re-take effect until you restart the worker. This is deliberate — live reloads would break crash-resumable replay.
-
~/.gbrain/audit/subagent-jobs-*.jsonlis local only. If your worker runs on a different host than thegbrain agent logscaller, the CLI won't see heartbeats from that worker. v0.16 will unify this; for now assume worker + CLI share a filesystem. -
Tool calls always run with
ctx.remote = true. Even on local CLI invocation. Tools that gate onremote=true(file_upload's strict confinement, put_page's namespace check) will apply. Good default; a subagent definition that wants local-filesystem reach beyond the brain can't have it. -
put_pagewrites are namespace-scoped. A subagent with id 42 can only write underwiki/agents/42/.... This is enforced both in the tool schema (the slug pattern shown to the model) AND server-side in theput_pageoperation (fail-closed ifviaSubagent=true). Don't try to route around it; you'll getpermission_denied.
~/your-openclaw/
└── gbrain-plugin/
├── gbrain.plugin.json
└── subagents/
├── meeting-ingestion.md
├── signal-detector.md
└── daily-task-prep.md
~/your-openclaw/gbrain-plugin/gbrain.plugin.json:
{
"name": "your-openclaw",
"version": "2026.4.20",
"plugin_version": "gbrain-plugin-v1",
"description": "Your OpenClaw's personal-brain subagents"
}Environment:
export GBRAIN_PLUGIN_PATH="$HOME/your-openclaw/gbrain-plugin"Then your OpenClaw calls gbrain agent run --subagent-def meeting-ingestion --fanout-by transcript ... and its definitions load automatically.