Add headless dispatch arbiter - #409
Conversation
Implementation Plan — Stage 2Problem and approachStage 2 adds the actual Dispatch Arbiter: a fully headless background decision-maker that runs in the existing subagent background lifecycle after the parent requests a child but before any child process is spawned. It consumes the routing guide and thinking metadata delivered by stage 1, then may change only the selected agent type, canonical provider/model, and thinking level. The implementation will stay close to the existing tab/session-title setter rather than introducing a general routing framework. A small The launch path will split today's routing into three clear phases inside the shared
Single and parallel tasks already converge on External prior art reinforces the narrow design: RouteLLM treats routing as a quality/cost choice between adequate and stronger models, while official OpenAI and Anthropic guidance emphasizes schema-constrained outputs. Because dreb's generic provider layer does not expose one uniform native structured-output API, the host will accept only a strict JSON object, validate every field itself, optionally retry malformed output once, and never treat model text as executable policy. Deliverables1. Global-only arbiter configurationAdd
2. Deterministic routing-guide loading and validationAdd a small parser/validator for the stage 1 guide contract.
3. Fully headless Dispatch ArbiterCreate a mode-independent For each attempted dispatch it will build a structured, explicitly untrusted package containing:
The task passed to the real child remains byte-for-byte unchanged. Before remote inference, the serialized arbiter package is secret-scrubbed with the existing built-in and configured extra patterns. Optional conversation and git context receive deterministic bounds and truncation markers; required task, guide, scope, and agent metadata are never silently dropped. If required content cannot fit the defined safety bounds, arbitration fails before inference. The arbiter call will:
Injected completion and clock/timeout dependencies will keep all automated tests offline. 4. Fail-closed pre-spawn integrationIntegrate arbitration in the common subagent execution path.
5. Typed arbitration observability and identity updatesAdd one host-generated arbitration event for every enabled attempt, including unchanged decisions and failures. The event will include an agent/operation ID, optional chain step, status, proposed tuple, nullable final tuple, changed-field list, and a bounded host error code/message. It will never contain model-authored explanations or raw inference data.
6. DocumentationDocument:
Files to create
Files to modify
If implementation shows an existing adjacent test or UI file is a clearer home, cases may be consolidated there, but no behavior or affected documentation layer above may be dropped. Acceptance criteria
Testing approach
Risks and boundaries
No blocking design question remains. The implementation should prefer the title setter's small dependency-injected pattern and the existing subagent convergence point over new orchestration abstractions. Plan created by mach6 |
Acceptance Gap — Arbiter User ControlsThe current implementation exposes the global Dispatch Arbiter policy through This is a hard acceptance criterion, not optional follow-up work. Before this implementation is pushed as complete, both control surfaces must expose:
Required surfaces:
The controls must write the global-only policy. Project settings must remain unable to enable, disable, or reconfigure arbitration. Acceptance gap tracked by mach6 |
Closes #394
Stage 2 builds on the routing guide and thinking metadata from stage 1 to add the fully headless, fail-closed Dispatch Arbiter before every subagent spawn, with typed observability across dreb's interfaces.
This is a stacked PR based on stage 1 (PR 405). Implementation plan posted as a comment below.