Guides / Brain

Building brain plugins

Shipping agent runs as background jobs that survive a crash and resume where they stopped.

The brain can run an LLM agent as a background job. Each run is a subagent job on the Minions queue: a worker runs the agent loop and saves every message and tool call to the database as it goes. If the worker crashes, restarts or the machine sleeps, the job is picked up again and continues from the saved conversation instead of starting over.

A brain plugin is a folder your host repo ships alongside the brain. It holds a nexusbrain.plugin.json manifest and a set of subagent definitions written as Markdown. Workers find plugins through the NEXUS_BRAIN_PLUGIN_PATH variable. This guide covers running durable agents with nexusbrain agent run and nexusbrain agent logs, then building, installing and debugging a plugin.

Time
30 minutes
For
Developers who ship agent workflows for a brain from their own repo

Before you start

  • A brain on the Postgres engine, so a separate worker process (nexusbrain jobs work or nexusbrain jobs supervisor) can run the jobs.
  • An Anthropic API key in ANTHROPIC_API_KEY or as anthropic_api_key in ~/.nexusbrain/config.json on the worker. To use another provider, see the gateway note in the first section.
  • You know what jobs and workers are. Shell jobs explains the queue.

01Run a durable agent

nexusbrain agent run only submits the job. The agent loop runs in a worker, so start one first. By default the run uses Anthropic directly with the model anthropic:claude-sonnet-4-6.

  1. Start a worker in its own terminal.

    nexusbrain jobs work

    You should seeThe worker starts and keeps running. If plugins are configured, it also prints a [plugin-loader] line for each one.

  2. Submit an agent run and follow it.

    On an interactive terminal --follow is already the default. Follow mode streams the run's events and ends when the job finishes.

    nexusbrain agent run --follow "Summarise this week's meeting notes into a page"

    You should see"submitted: job <id> (subagent)", then "[nexusbrain agent] following job <id> (Ctrl-C to detach)...", event lines as the agent works, and finally "job <id> terminal: completed" with the result as JSON.

  3. Or submit it and return immediately.

    --detach may also come after the prompt. To pass text that looks like a flag as part of the prompt, put -- before it.

    nexusbrain agent run "Summarise this week's meeting notes into a page" --detach

    You should seeThe job ID printed on its own line. The run continues on the worker.

FlagWhat it does
--model <provider:model>Model to use. Non-Anthropic providers need the gateway loop turned on.
--max-turns <n>Maximum assistant turns. Default 20.
--tools a,b,cOnly these brain tools, for example brain_search,brain_get_page (the brain_ prefix is optional).
--timeout-ms <n>Wall-clock limit for the job, in milliseconds.
--fanout-manifest <path>A JSON array of {prompt, input_vars?} objects. Each becomes its own run, and an aggregator job collects the results.
--subagent-def <name>Name of a plugin subagent definition to record on the job. See the plugin sections below.
--follow, --no-follow, --detachWatch the run, or submit and exit.
Note

To run a model from another provider, turn on the provider-neutral loop with nexusbrain config set agent.use_gateway_loop true and give that provider its credentials. The model must support tool calling, or the job is refused when it starts.

02Read the logs of a run

  1. Show everything recorded for a run.

    nexusbrain agent logs <job_id>

    You should seeTime-stamped lines such as [submission], heartbeat events with turn=, tool names, timings and token counts, and [message #n role] lines. For a finished run, the full transcript follows.

  2. Keep watching a run that is still going.

    nexusbrain agent logs <job_id> --follow

    You should seeNew lines appear as they happen, and the command ends with "reached terminal state" when the job finishes.

  3. Show only recent events.

    --since takes an ISO-8601 time or a relative value in s, m, h or d, such as 5m, 1h or 2d.

    nexusbrain agent logs <job_id> --since 15m

    You should seeOnly events from the last 15 minutes.

  4. Check the job itself if it ended badly.

    nexusbrain jobs get <job_id>

    You should seeThe status, attempts and stall count, the error text if any, and the result.

  • The messages come from the database, so they are visible from any machine connected to the brain.
  • The heartbeat and submission events come from ~/.nexusbrain/audit/subagent-jobs-YYYY-Www.jsonl on the worker's machine. Run nexusbrain agent logs on the worker host to see them.

03How a run survives a crash

Every turn is saved before the next one starts, and each tool call is recorded before and after it runs. When a worker dies mid-run, the job's lock expires and the job counts as stalled. Runs submitted by nexusbrain agent run may stall up to 3 times; each time, a worker claims the job again, loads the saved messages and continues from there.

  1. Start a long run in detached mode.

    nexusbrain agent run --detach --max-turns 30 "Build a reading list page from my saved articles"

    You should seeThe job ID.

  2. Stop the worker while the run is in progress, then start it again.

    After the lock runs out, the restarted worker claims the job again.

    nexusbrain jobs work

    You should seenexusbrain jobs get <job_id> shows a stall count above 0, and the run finishes without repeating the turns already saved.

Tip

For production, run workers with nexusbrain jobs supervisor start --detach --json, which restarts a crashed worker automatically with backoff.

04Build a plugin

A plugin contributes subagent definitions only. It cannot add new tools, widen the list of brain tools an agent may use, or change safety settings.

  1. Create the plugin folder with a manifest.

    my-plugin/
      nexusbrain.plugin.json
      subagents/
        meeting-digest.md

    You should seeThe folder exists at an absolute path, for example /opt/my-plugin.

  2. Write nexusbrain.plugin.json.

    name and plugin_version are required, and plugin_version must be exactly nexusbrain-plugin-v1. subagents is the folder of definitions, relative to the plugin, and defaults to subagents. It may not point outside the plugin folder.

    {
      "name": "my-plugin",
      "version": "1.0.0",
      "plugin_version": "nexusbrain-plugin-v1",
      "subagents": "subagents",
      "description": "Meeting workflows for our team"
    }

    You should seeThe file is valid JSON.

  3. Write a subagent definition.

    Every .md file in the subagents folder is one definition. name is optional and defaults to the file name without .md. The Markdown body is the system prompt.

    allowed_tools must use names from the brain's agent tool list: brain_query, brain_search, brain_get_page, brain_list_pages, brain_file_list, brain_file_url, brain_get_backlinks, brain_traverse_graph, brain_list_link_sources, brain_resolve_slugs, brain_get_ingest_log, brain_put_page, brain_add_timeline_entry, brain_get_recent_salience and brain_find_anomalies.

    ---
    name: meeting-digest
    allowed_tools:
      - brain_search
      - brain_get_page
      - brain_put_page
    ---
    You read meeting notes in the brain and write a short weekly digest page.

    You should seeOne Markdown file per subagent in the subagents folder.

05Install and debug a plugin

  1. Point the worker at the plugin and start it.

    List several plugins separated by colons, like PATH: /opt/my-plugin:/opt/other-plugin. Each entry must be an absolute path. Because colons separate entries, a Windows path with a drive letter such as C:\plugins does not work here.

    NEXUS_BRAIN_PLUGIN_PATH=/opt/my-plugin nexusbrain jobs work

    You should see"[plugin-loader] loaded 'my-plugin' v1.0.0 (1 subagents)" among the worker's startup lines.

  2. Read any [plugin-loader] warnings.

    Problems never stop the worker. The plugin, or the path, is skipped and a warning explains why. The troubleshooting list below has every message.

    You should seeNo warnings, or a warning naming the file and the problem.

  3. Submit a run that names the definition.

    nexusbrain agent run --subagent-def meeting-digest --tools brain_search,brain_get_page,brain_put_page "Write this week's digest"

    You should seeThe job is submitted, and nexusbrain jobs get <job_id> shows "subagent_def":"meeting-digest" in its Data line.

  • If two plugins define a subagent with the same name, the one listed first in NEXUS_BRAIN_PLUGIN_PATH wins and the other is skipped with a collision warning.
  • Plugins are loaded when the worker starts. Restart the worker after changing a plugin.
Note

In this release the worker loads and checks plugin definitions at startup, and --subagent-def records the name on the job, but the agent runner does not yet apply the definition's prompt or allowed_tools to the run. Until it does, set the tools for each run with --tools and put the instructions in the prompt.

06Troubleshooting

[plugin-loader] rejected <path>: missing nexusbrain.plugin.json

The path must be the plugin folder itself, the one that contains nexusbrain.plugin.json, not its parent.

[plugin-loader] rejected <path>: unsupported plugin_version

Set "plugin_version": "nexusbrain-plugin-v1" in the manifest.

[plugin-loader] rejected <path>: manifest missing required "name" field

Add a non-empty name to nexusbrain.plugin.json.

[plugin-loader] rejected <path>: invalid manifest JSON

Fix the JSON syntax in the manifest, for example a trailing comma or a missing quote.

[plugin-loader] rejected <path>: subagent '<name>' allowed_tools references unknown tools

Use only the brain_ tool names listed in "Build a plugin". One bad name rejects the whole plugin.

[plugin-loader] rejected <path>: subagents path escapes plugin root

The manifest's subagents value must be a folder inside the plugin, such as subagents. Remove any ../.

[plugin-loader] relative path rejected, ~-prefixed path rejected (expand explicitly), or remote URL rejected

Use full absolute paths in NEXUS_BRAIN_PLUGIN_PATH, such as /opt/my-plugin. ~, relative paths and URLs are not allowed.

[plugin-loader] path does not exist, skipping

Check the spelling of the path, and that the plugin folder exists on the worker machine, not only where you submit jobs.

The run fails with "subagent allowed_tools references unknown tool".

A name in --tools is not an agent tool. The error lists the known names; use those.

The run is refused because the model is non-Anthropic but agent.use_gateway_loop is not enabled.

Run nexusbrain config set agent.use_gateway_loop true and configure that provider's credentials, or use an anthropic: model.

nexusbrain agent run --follow stops with "[nexusbrain agent] timeout after <n>ms" and exit code 3.

Only the watching stopped. The job keeps running on the worker. Check it with nexusbrain jobs get <job_id> or nexusbrain agent logs <job_id> --follow.

nexusbrain agent logs shows messages but no heartbeat events.

Heartbeat events are stored on the worker's machine. Run the command on the worker host.

A submitted run never starts.

No worker is running. Start nexusbrain jobs work or nexusbrain jobs supervisor start --detach --json on a Postgres brain.