Draft Piece (starter workflow)
Slug:
draft-pieceType:agent_blueprintSource: code-defined; appears in every tenant'sagent_blueprint://listautomatically. Fork viaagents.fork_blueprintto customize. Outputs: the new draft version number on the piece + the count ofcontent_groundingchildren attached.
The single-piece drafter. Loads a content_piece, chases its FK references to pull author + voice + pillar, gathers substrate grounding evidence, writes the draft inline via prompt-fragment composition, attaches citation children, and writes the new draft as a new version on the piece. Drafts live as versions on the piece rather than as separate draft records.
When to use it
- A user wants the AI to produce a full draft for a
content_pieceplaceholder created byplan_and_draft_window(which inlines the planner) or byartifacts.createdirectly. - You want a single-shot LinkedIn post / blog draft / newsletter section grounded in your voice + pillar + substrate evidence.
- You're invoking it as a sub-blueprint from
plan_and_draft_windowto back-fill drafts after the planner lands.
Reading this workflow
On the MCP tool surface you run this workflow interactively: the calling LLM reads this recipe and makes the tool calls itself (see how a workflow runs). Each step description below is written as an instruction you can act on directly via the named primitives. (The platform can also run this workflow headlessly — Run now, scheduled cron — set up over REST + the Anthropic tool surface; see Workflows over the API. A standard MCP customer key cannot one-shot-run or schedule it: those actions need the workflows:delegate scope it doesn't carry.)
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 workflow works:
-
draftBodyRequired— pieces in statusdrafting | ready | publishedmust carry a non-emptycontent_json.draft_markdown. Placeholder + archived are exempt. This workflow's terminalupdate_piecestep writes the body in the SAME patch as the status bump, so the rule is satisfied structurally; there is no intermediate state where the piece exists in drafting status with an empty body. -
calendarPlanGate(OPT-IN) — gatesdrafting | ready | publishedtransitions on an approvedcontent_calendar_planparent, but ONLY when the piece carriescontent_json.metadata.requires_approval_gate = true. Default behavior (flag missing or false): pass-through. This workflow never opts in; agent-driven / ad-hoc drafting is the default path. Editorial flows that want batch approval should fork this starter and add the flag to theupdate_piecestep's metadata.
What it produces
The workflow writes a new version of the supplied content_piece artifact with:
content_json.draft_markdown— the full body in markdown.content_json.status— bumped to'drafting'.metadata.auto_generated—true.metadata.review_status—'pending_review'.metadata.variant_key— set to the inputvariant_keyif supplied.
It also attaches one or more content_grounding children to the piece (parent_artifact_id = piece_id). Each citation child carries:
{
"schema_version": "1.0.0",
"quote": "<the quoted line>",
"speaker": "<who said it>",
"company": "<company name or null>",
"source": "<conversation id / cluster id>",
}The Calendar page detail panel renders citations beneath the draft body so the reader can see what the AI grounded each claim against.
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
piece_id | artifact_ref(content_piece) | yes | The piece to draft. Must already exist; create via plan_and_draft_window (which inlines the planner) or artifacts.create. |
variant_key | string | no | Optional variant key tagged on the new draft version. Useful for producing multiple variants of the same piece (long, short, punchy). |
How it runs
8 top-level steps:
- load_piece —
tool.read_resource artifact://<piece_id>. The read returns an envelope withreferencesresolved sopillar_idandauthor_idarrive as{ id, title, artifact_type, status }envelopes alongside the raw uuids. - load_author —
tool.read_resource author_profile://<piece.author_id>. The author profile carriesvoice_profile_id. - load_voice —
tool.read_resource voice_profile://<author.voice_profile_id>. The voice rules embed into the draft prompt so the body matches workspace voice. - gather_evidence —
tool.data.cluster_searchkeyed onpiece.content_json.topic. Returns conversation themes the draft can quote and cite. - assert_evidence —
assert. Halts withevidence_missingpause when zero clusters returned. The calling LLM surfaces a confirm pause: proceed without grounding (mark draftmetadata.grounding_status='ungrounded') or pause until the substrate has data. - write_draft —
llm. Authors the draft body inline. Composesprompt://content_writer/grounding_rules,audience_scoping,channel_budget,cta_synthesis,hook_patterns. Outputsdraft_markdownplus a citations array. - attach_citations —
loop. Per cited evidence chunk, attaches acontent_groundingchild to the piece viaartifacts.create_child. - update_piece —
tool.artifacts.updatewrites the new draft body intocontent_json.draft_markdown. The update appends a new version row inplatform_artifact_versionsand bumpscurrent_versionautomatically.
Pause types and resume contract
| Pause type | Triggered by | Resume requires |
|---|---|---|
evidence_missing | assert_evidence step (zero clusters) | confirm action: continue (proceed without grounding) or stop |
When evidence_missing fires, the chat panel offers two buttons: "Proceed without grounding" (resumes with action='continue'; the resulting draft is marked metadata.grounding_status='ungrounded' so reviewers know it's an opinion piece) and "Pause until data ingestion catches up" (resumes with action='stop' to abort).
Reading and walking it
Via MCP from an external Claude Desktop, read the recipe and walk its steps yourself (the interactive path):
read_resource agent_blueprint://draft-pieceThen gather the inputs (piece_id: '5b2a...8e1d', variant_key: 'long') and perform each step with your own primitive tools. For variant production: walk the recipe once per variant key with the same piece_id and a different variant_key. Each walk appends a new version, so the piece's version history is the variant history.
Forking it
agents.fork_blueprint source=draft-piece new_slug=<your-fork>Common forks:
- Channel-specific drafting — fork to a Twitter-only or LinkedIn-only variant with hardcoded channel + tighter word budgets.
- Skip research by default — drop
gather_evidenceandassert_evidencefor opinion-heavy publishing. - Custom evidence layer — extend
gather_evidenceto call your CRM tool, intercom search, or other tenant-specific source before the synthesis step. - Multi-source citations — replace the single
data.cluster_searchwith a parallel fan-out to substrate + KB + a custom index, then merge before the draft step.
Limits
- Reads are not cost-bounded server-side in v1.
- The piece, author, and voice references all resolve within the calling API key's workspace; cross-tenant references fail at the operation registry boundary.
- The drafter expects the piece to already have
pillar_idandauthor_idpopulated (placeholder pieces created byplan_and_draft_window's inlined planner always do; pieces created manually viaartifacts.createmay not — the workflow will halt atload_authorifauthor_idis null). - Each invocation produces ONE draft. For variant generation, run the workflow multiple times with different
variant_keyinputs.