Plan and Draft Window (starter blueprint)
Slug:
plan-and-draft-windowType:agent_blueprintSource: code-defined; appears in every tenant'sagent_blueprint://listautomatically. Fork viaagents.fork_blueprintto customize. Outputs: the array ofcontent_pieceids planned + drafted, the count of successful drafts, and the total citations attached.
The end-to-end content production blueprint. Plans a window of placeholder pieces AND drafts each one in parallel — both halves run in a single blueprint.
The 2026-04-30 trim inlined what used to be a separate plan-content-window starter directly into this blueprint, so users see ONE end-to-end recipe in the library instead of a planner-only utility they would never run on its own. Drafting still uses draft-piece as a sub-blueprint per piece (one per loop iteration) because that recipe IS independently useful (drafting one specific piece by id).
When to use it
- A founder or marketer wants a complete month of content (planned + drafted) in one invocation.
- The chat panel exposes a "Plan and write content for a month" affordance backed by this blueprint.
- An external MCP client wants the simplest one-shot content production primitive: input the window, output a Calendar full of drafted pieces.
If you want plan-then-review-then-draft as separate user gates, fork this blueprint and split it: keep the inlined planning steps, drop the draft_each loop, then invoke draft-piece per approved piece in a follow-up run.
Reading this blueprint
Per the agent blueprint substrate contract: this is a recipe the calling LLM reads and walks step-by-step. On the MCP tool surface there is no run tool — the calling LLM IS the runner. Treat the step graph as direct instructions for the named primitives. (Platform-initiated runs — manual "Run now", schedule/event/webhook triggers, replay, backtest sweeps — are driven separately by the headless SDK runner; see docs/blueprint-runner-sdk.md. This doc describes the interactive path you walk yourself.)
Validators that travel with content_piece writes (2026-05-12 relaxation)
Two registry validators run on every content_piece write — knowing them shapes how this blueprint works:
-
draftBodyRequired— pieces in statusdrafting | ready | publishedmust carry a non-emptycontent_json.draft_markdown. Placeholder is exempt, which is why this blueprint's planner step is allowed to create pieces atstatus: placeholderwith no body yet. The downstreamdraft-piecesub-blueprint then writes the body in the same patch as the status bump todrafting. -
calendarPlanGate(OPT-IN) — gatesdrafting | ready | publishedtransitions on an approvedcontent_calendar_planparent, but ONLY when the piece carriescontent_json.metadata.requires_approval_gate = true. This blueprint does NOT set the flag, so the planner's placeholder pieces transition todraftingfreely. Editorial teams that want batch approval should fork this starter and addrequires_approval_gate: truetocreate_pieces.args.content_json.metadata, then add an approval pause between plan and draft phases that requires the parent to be an approvedcontent_calendar_plan.
What it produces
Three outputs:
piece_ids(array) — everycontent_pieceartifact created by the inlined planner.draft_count(integer) — how many of those pieces were successfully drafted.total_citations(integer) — sum ofcontent_groundingchildren attached across every drafted piece.
Each piece carries metadata.auto_generated=true and metadata.review_status='pending_review' so the user can review, edit, or reject in the Calendar page.
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
date_range | json | yes | Object { start, end } of ISO dates bounding the window. |
channels | json | yes | Array of channel slugs the planner is allowed to use. |
target_count | integer | yes | How many content_piece artifacts to plan + draft. 1-50. |
pillar_emphasis | json | no | Optional record { <pillar_slug>: <weight> } to bias distribution. |
audience | string | no | Audience lens (free-text persona + segment). |
How it runs
13 top-level steps. The planning steps are inlined; the draft phase fans out via draft-piece as a sub-blueprint.
Plan phase (inlined):
- bootstrap —
blueprint. Runsbootstrap-workspaceto gate on workspace canon (voice + pillars + authors). Halts withbootstrap_requiredcontext if anything is missing. - load_voice —
tool.read_resource voice_profile://list. - load_pillars —
tool.read_resource artifact://list?artifact_type=content_pillar. - load_authors —
tool.read_resource author_profile://list. - gather_evidence —
loop(parallel). Per pillar,data.cluster_searchfor substrate evidence themes. - assert_evidence —
assert. Halts withevidence_missingwhen every pillar returned zero clusters. - distribute —
llm. Distributestarget_countpieces across channels + pillars. Composespillar_selection,cadence_rhythm,theme_variation,channel_budget,audience_scopingfragments. - create_pieces —
loop. Per spec,artifacts.createacontent_piece(auto_generated=true, review_status=pending_review). - extract_piece_ids —
transform. Extracts the bare ids from the loop output.
Draft phase:
- draft_each —
loop(parallel, capped bypolicy.parallelism_max). Perpiece_id, dispatchesdraft-pieceas a sub-blueprint. Each iteration runs the full draft pipeline: load piece + author + voice, gather evidence, write draft, attach citations, update piece. - assert_drafts —
assert. Halts if anydraft-piecesub-run reported failure. The calling LLM surfaces the failure list as a confirm pause; the user can re-run failed pieces, accept the partial result, or abort. - count_drafts —
transform. Count successful drafts. - sum_citations —
transform. Sum citation count across drafted pieces.
Pause types and resume contract
This blueprint can pause on any of the inner blueprints' pauses:
| Pause type | Comes from | Resume requires |
|---|---|---|
bootstrap_required | the inlined bootstrap step | the user provides the missing canon item |
evidence_missing | the inlined assert_evidence step (per-pillar evidence) OR draft-piece (per-piece evidence) | confirm action: continue or stop |
draft_failures | the assert_drafts step | confirm action: continue (accept partial) or stop |
The chat panel widget registry handles each pause type identically whether it surfaces from this composition or from walking the inner blueprints on their own.
Reading and walking it
On this MCP surface there is no run tool — read the recipe and walk its steps yourself. Via MCP from an external Claude Desktop:
read_resource agent_blueprint://plan-and-draft-windowThen gather the inputs and perform each step with your own primitive tools:
date_range: { start: '2026-05-01', end: '2026-05-31' }
channels: ['linkedin', 'blog']
target_count: 12
pillar_emphasis: { 'engineering-velocity': 0.5 }
audience: 'B2B SaaS engineering leaders, 50-500 person org'As you walk it, narrate progress in chat: "Researching engineering-velocity pillar... Found 47 conversations. Authoring piece 1 of 12... Drafting piece 3 of 12..." The user watches it happen.
When you finish walking the steps, the chat shows: "12 pieces planned + drafted for May. Open Calendar to review." The user goes to the Calendar page; every piece appears with an AI badge and shows in the Pending review filter chip.
Forking it
agents.fork_blueprint source=plan-and-draft-window new_slug=<your-fork>Common forks:
- Plan-only variant — drop the
draft_each/assert_drafts/count_drafts/sum_citationssteps to recover the old planner-only behaviour. Useful if you want the user to review placeholders before drafting kicks off. - Approve-then-draft variant — replace the parallel
draft_eachloop with abranchoninputs.auto_draft. When false, only run the planner; when true, run plan + draft. Lets a single blueprint cover both flows. - Per-channel concurrency limits — fork the inner draft loop to chunk by channel and run channels sequentially (when LLM rate limits matter).
- Performance feedback weighting — pre-step that reads published-piece performance edges from prior windows and adjusts
pillar_emphasisbefore thedistributestep. Closes the loop on what's working.
Limits
target_countcapped at 50.parallelism_maxof 4 in policy keeps concurrent LLM calls manageable; bump in a fork if your account has higher rate budgets.- Reads are not cost-bounded server-side in v1.
- Total runtime grows roughly linearly with
target_count(planning is one batched call; drafting isceil(target_count / parallelism_max)rounds of paralleldraft-pieceruns). - The composition is one level deep on this version. A future starter could compose plan + draft + schedule (auto-set
status='scheduled') once the schedule artifact lands; that's deliberately deferred until pilot reveals demand.