Briefs & the dispatch lifecycle
A brief is a durable folder for one unit of work. It carries the idea, the
evolving spec, an append-only trace of everything that touched it, and — when
it's ready — the dispatch that hands it to an agent. Briefs live at /briefs.
The lifecycle
idea ─▶ refining ─▶ planned ─▶ dispatched ─▶ in_progress ─▶ complete
│ │ │ │ │ ▲
capture spec is ready to a worker a dispatched rolls up when its
a note refined hand off claims it agent works it dispatch is done
│ │
└▶ in_review ─┘
(optional review gate —
only a PASS completes)
Each brief has a status drawn from that lifecycle (plus blocked,
in_review, deferred, cancelled, abandoned). Status changes, notes, spec
edits, and links are all recorded as events on the brief's trace — nothing is
overwritten silently; a new spec snapshots the prior one first.
Capturing and refining
Capture a thought in the /briefs box and it becomes a draft brief
(origin=note, status idea). From the brief's page you edit the spec (the
canonical plan) and append notes. Every mutating action attaches its actor as a
participant, so the folder records who did what.
Dispatch — handing work to an agent
When a brief is planned, you dispatch it. That renders a dispatch
packet — the brief's title, current spec, key trace, and a recall pointer —
and creates a dispatch_request. The packet is the exact prompt a fresh agent
receives; it's also click-to-copy so you can spawn by hand.
Every commit an agent makes for a brief should carry a
Brief: #<id>git trailer. flower auto-links those commits back to the brief's trace, so the folder grows its own provenance.
Adversarial review — the completion gate
Some worksets shouldn't auto-complete on the worker's own say-so. The
orchestrator can call brief_request_review to hold a finished brief at
in_review instead of letting it roll up to complete. That returns a
review packet (scope + mandate) for an independent reviewer whose job is to
try to refute the work — an adversarial pass, not a rubber stamp.
The reviewer submits a verdict with brief_review:
- PASS — opens the gate; the brief rolls up to
complete. - REQUEST_CHANGES / BLOCK — records the findings and auto-bounces a fix
dispatch back to the original worker.
completestays blocked until a later PASS.
Review is manual, not automatic — nothing fires it when a dispatch finishes.
Pass force: true to make the gate sticky, so every future completion of that
brief needs a fresh PASS. The trace records review_requested, then
review_passed or review_failed.
Relationships — epics and dependency gating
Briefs are first-class relative to each other:
- Epic grouping. A brief can have a parent epic (
parent_brief_id). The/briefslist nests children under their epic with a progress rollup. - Depends-on gating. A brief can depend on other briefs. Dispatch is
server-refused while any dependency is incomplete — you'll see
"blocked by #X". When a blocker reaches
complete(orcancelled), the briefs it just freed are reported as newly unblocked, so the orchestrator can dispatch them in order. - Merging duplicates.
brief_mergecollapses one or more source briefs into a survivor — the sources are cancelled and point at it (merged_into_brief_id), and their links, participants, dependencies, and children re-point to the survivor so no provenance is lost.
The dependency graph is cycle-guarded — flower rejects an edge (or an epic parent) that would create a loop.
Both relations are visible on a brief's page and drive the "dispatchable now" filter (planned + unblocked) on the list.
The MCP surface
Everything above is scriptable by agents through the brief tools — see
Using the flower MCP → Briefs. Read with
recall_brief / recall_briefs / recall_dispatch_queue; write with
brief_create, brief_update_spec, brief_append, brief_dispatch,
brief_claim, brief_dispatch_complete, brief_dispatch_cancel,
brief_request_review, brief_review, brief_set_parent, brief_depend,
brief_merge, and friends (each requires an actor_ref).
Ready for the agents that consume these dispatches? See Daemons & the roster.