Until now the doc-gardener example was a single monolithic
orchestrator binary writing synthetic messages directly to SQLite.
That's now obsolete: the feature runs as a true multi-agent flow
where the SynapBus reactor fires subprocess runs for every DM, each
agent is its own reactive subprocess invocation, and follow-up DMs
go through the real MessagingService.Send → dispatcher path so the
reactor picks them up.
Changes:
- cmd/synapbus/main.go: gate the three legacy background workers
(expiry, retention, stalemate) behind SYNAPBUS_DISABLE_*_WORKER env
flags. These workers manage the legacy channel task-auction /
message retention features the doc-gardener demo doesn't use, but
they held the single-connection write pool long enough to wedge
the whole server for interactive sessions. All three are disabled
in the example's start.sh.
- cmd/docgardener/agent.go (new): the per-agent subprocess entry the
reactor harness invokes for every reactive trigger. Reads
message.json from the workdir, routes by SYNAPBUS_AGENT to either
coordinator-kickoff, coordinator-completion, or specialist-work
logic. Writes prompt.txt + response.txt for harness capture. Uses
the admin socket (`synapbus messages send`) for follow-up DMs so
the real MessagingService.Send path fires the dispatcher.
- cmd/docgardener/main.go: adds `docgardener agent` subcommand, plus
helpers freshAPIKey / bcryptHash / absPath / selfPath used by the
spawn flow.
- examples/doc-gardener/start.sh: provisions user + coordinator
agent + algis human agent + approvals/requests channels; the
coordinator is created with trigger_mode=reactive,
harness_name=subprocess, local_command pointing to docgardener
agent, and harness_config_json.env carrying SYNAPBUS_AGENT,
SYNAPBUS_BIN, SYNAPBUS_SOCKET. Specialists are spawned
dynamically by the coordinator at runtime (not pre-registered),
so the demo exercises dynamic agent spawning end-to-end.
- examples/doc-gardener/run_task.sh: collapsed to a 3-line kickoff
that just DMs the coordinator and polls algis's inbox for the
coordinator's FINAL: reply. Everything else happens via the
reactor.
Verified end-to-end in Chrome on a fresh instance:
- 4 agents registered (coordinator + 3 specialists dynamically
spawned by the coordinator on receipt of the first DM)
- 7 reactive_runs + 6 harness_runs across the goal lifecycle:
algis → coordinator (kickoff, 624ms, builds goal+tree+spawns)
coordinator → docs-scanner (claim task 2)
coordinator → cli-verifier (claim task 3)
coordinator → drift-reporter (claim task 4)
docs-scanner → coordinator (DONE task=2)
cli-verifier → coordinator (DONE task=3)
drift-reporter → coordinator (DONE task=4, coalesced)
- Web UI Agent Runs page shows all 7 runs with the real
"DM from X" trigger lines and correct sender/receiver chain
- Goal ends at status=completed with all 3 leaf tasks at status=done
- Each specialist run posts a real subprocess artifact to the
goal channel (#finding, #verified, #summary) and appends a real
reputation_evidence row keyed by config_hash.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SynapBus examples
Runnable demos of SynapBus features. Each example is self-contained under its own directory, launches an isolated synapbus instance on a distinct port, and cleans up after itself.
| Example | Feature | Real LLM? | Port |
|---|---|---|---|
cold-topic-explainer/ |
Reactive agent triggers + subprocess harness — three Gemini agents (decomposer → writer → critic) collaborate via DMs to produce a 3-paragraph explainer, with real LLM calls end-to-end. | ✅ yes (gemini CLI) |
18088 |
doc-gardener/ |
Dynamic agent spawning (spec 018) — a coordinator meta-agent decomposes a goal into a task tree, spawns specialists with config_hash-rooted trust + delegation-cap enforcement, runs them through the state machine, generates a rich HTML report. |
❌ v1 is synthetic (primitives demo); real LLM coordinator is a follow-up PR | 18089 |
Quick start
Pick an example, cd into it, and follow its README. In general:
cd examples/<name>
./start.sh # rebuild + launch an isolated synapbus instance
./run_task.sh # drive the demo flow
./report.sh # (where applicable) render an HTML report
./stop.sh # shut down
Both examples use the same layout for consistency:
examples/<name>/
├── start.sh # build & launch
├── run_task.sh # execute the demo flow
├── stop.sh # shut down
├── report.sh # (doc-gardener only) render HTML report
├── bin/
│ ├── synapbus # built from the current checkout
│ └── <helper> # example-specific driver binary
├── configs/ # per-agent JSON configs (harness_config, prompts, etc.)
├── data/ # isolated SQLite DB + attachment store + sockets
├── synapbus.log # server stdout+stderr
└── README.md # example-specific docs
What each example proves
- cold-topic-explainer proves that the SynapBus reactor + subprocess harness can drive a real multi-agent loop with three distinct LLMs, with depth and budget guards, OpenTelemetry tracing, and harness_runs accounting.
- doc-gardener proves that the dynamic-agent-spawning data primitives —
goals,goal_taskswith denormalized ancestry, atomic optimistic-lock claim,config_hash-keyed reputation ledger, delegation-cap enforcement, per-billing-code cost rollup — work end-to-end against real SQLite, and feed a rich HTML report.
The two examples are complementary: cold-topic-explainer exercises the runtime path (reactor → harness → LLM → DMs), doc-gardener exercises the work-tracking path (goals → tasks → trust → report). A future example will combine them into a full LLM-driven coordinator loop.
Global prereqs
- Go 1.25+
sqlite3,curl,jqon$PATH- A free TCP port per example (see table above)
- For
cold-topic-explaineronly:geminiCLI authenticated viagemini auth login
Troubleshooting
- Port already in use: set
SYNAPBUS_PORT=18090 ./start.sh(each example honors the env var). - Web UI is blank: rebuild the embedded Svelte SPA with
make webfrom the repo root once, then re-run./start.sh. - Stale binary: delete the example's
bin/directory and rerun./start.shto force a rebuild.