You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Feature: protocol: "subprocess" for registered workers
Summary
Add a new worker protocol that dispatches work by spawning a subprocess per task, capturing stdout as the response. Removes the need for a separate HTTP bridge shim (e.g., a Python wrapper around opencode run --pure).
Motivation
Today, integrating CLI agents (opencode, Pi, custom scripts) as nullboiler workers requires running a separate HTTP server (webhook bridge) that:
Listens for nullboiler webhook POST
Spawns the CLI agent as subprocess
Captures stdout
Returns it as webhook response JSON
This is extra infrastructure for no architectural value — nullboiler already spawns subprocesses for tracker-managed workflows (tracker.subprocess.command). Extending that to registered workers eliminates the bridge.
Proposal
Add "subprocess" to the Protocol enum (src/worker_protocol.zig). Worker config:
If rc != 0: return failure with stderr in error_text
Respect cwd and env overrides
Use cases
opencode as a graph worker: command: ["opencode", "run", "--pure"]. Already verified via webhook bridge — same semantics, no bridge.
Pi as a graph worker: command: ["pi", "--print"]. Pi has CLI print mode.
Custom scripts as workers: any script that takes prompt-as-arg + writes to stdout. Useful for deterministic transforms (no LLM cost) — regex parsers, API calls, file lookups.
Local LLM scripts: command: ["llama-cli", "-m", "/path/to/model.gguf"] for fully offline workers.
Why this is worth doing
Eliminates infrastructure. One fewer service to run, monitor, debug.
Generic. Any CLI becomes a worker. No per-agent bridge code.
Composable. Subprocess workers can call other tools (curl, file ops) without HTTP intermediation.
Test-friendly. Subprocess dispatch is easy to mock in tests.
Existing precedent
tracker.subprocess.command already exists for nullclaw spawning in tracker-mode workflows. This proposal extends the same pattern to the worker registry.
protocol: "webhook" is essentially "subprocess + HTTP" — a long-running bridge that wraps a subprocess. Direct subprocess dispatch skips the HTTP layer.
Feature:
protocol: "subprocess"for registered workersSummary
Add a new worker protocol that dispatches work by spawning a subprocess per task, capturing stdout as the response. Removes the need for a separate HTTP bridge shim (e.g., a Python wrapper around
opencode run --pure).Motivation
Today, integrating CLI agents (opencode, Pi, custom scripts) as nullboiler workers requires running a separate HTTP server (webhook bridge) that:
This is extra infrastructure for no architectural value — nullboiler already spawns subprocesses for tracker-managed workflows (
tracker.subprocess.command). Extending that to registered workers eliminates the bridge.Proposal
Add
"subprocess"to theProtocolenum (src/worker_protocol.zig). Worker config:{ "id": "opencode-worker", "protocol": "subprocess", "command": ["opencode", "run", "--pure"], "prompt_arg_index": 1, "output_format": "stdout", "cwd": "/optional/working/directory", "env": {"TERM": "dumb"}, "timeout_ms": 600000, "tags": ["implementer"], "max_concurrent": 1 }Engine behavior on dispatch:
commandwith the rendered prompt inserted atprompt_arg_index(or appended ifprompt_arg_indexis null/missing)timeout_ms(already enforced for sync HTTP per finding Migration system re-runs all migrations on every startup (no version tracking) #4 fix){response: stdout}(matches existingworker_response.parseshape)cwdandenvoverridesUse cases
command: ["opencode", "run", "--pure"]. Already verified via webhook bridge — same semantics, no bridge.command: ["pi", "--print"]. Pi has CLI print mode.command: ["llama-cli", "-m", "/path/to/model.gguf"]for fully offline workers.Why this is worth doing
Existing precedent
tracker.subprocess.commandalready exists for nullclaw spawning in tracker-mode workflows. This proposal extends the same pattern to the worker registry.protocol: "webhook"is essentially "subprocess + HTTP" — a long-running bridge that wraps a subprocess. Direct subprocess dispatch skips the HTTP layer.Implementation sketch
In
src/dispatch.zigdispatchStepWithOpts:dispatchSubprocesswould mirrordoFetchTimedshape: spawn child, write prompt to argv, poll for exit, capture stdout/stderr, returnDispatchResult.Config parsing additions to
WorkerConfig(src/config.zig):command: []const []const u8(required for subprocess protocol)prompt_arg_index: ?u32(default = append to argv)output_format: []const u8(default = "stdout")cwd: ?[]const u8env: ?std.json.ValueCompatibility
No breaking changes. Existing protocols unaffected.
subprocessis purely additive.Related