Write an article with an editor check before the draft

Drafting first and fixing later produces articles with the wrong angle and unsourced facts. This graph settles the angle, outline, facts and reader in parallel, then an editor in a fresh context checks that every fact has a source and the plan fits the brief before anything is written.

7 steps in 4 stages · 7 subagents · a kit of 12 files

Free. Built in your browser; nothing is uploaded. No API key, no account.

How it runs

Steps in the same stage start at the same time. Each subagent gets only what its incoming edges carry, and a step in a fresh context never sees the reasoning of the steps before it. A gate decides whether the work passes, and a failed gate re-runs the work it checks.

  1. Stage 1
    • Split · Planner

      sonnet · Read

  2. Stage 24 in parallel
    • Angle & Headline · Worker

      haiku · Read, WebSearch, WebFetch

    • Outline · Worker

      haiku · Read, WebSearch, WebFetch

    • Facts & Quotes · Worker

      haiku · Read, WebSearch, WebFetch

    • Reader · Worker

      haiku · Read, WebSearch, WebFetch

  3. Stage 3
    • VERIFIER (Fresh Context) · Checker

      opus · Read, Grep, Glob · fresh context

      Gate: Every fact kept has a source, and the angle and outline match the brief's audience and length.

  4. Stage 4
    • Final answer · Writer

      sonnet · Read

Use it when

  • You write posts, articles or newsletters with Claude.
  • Drafts come back generic or off-brief.
  • Facts in drafts need sources.

Change these first

  • Put your style guide in the writer's prompt.
  • Add the audience and length to the brief the planner reads.

Need a workflow built for your team? Fixed-price packages

What you get

An orchestrating SKILL.md, one Claude Code subagent per step with its own tools and model, and the same skill as a Cursor rule. Your agent runs it with its own subagents; nothing on this site calls a model.

write-an-article-skill-kit.zip12 files
  • .claude/skills/write-an-article/SKILL.mdorchestrator
  • .claude/skills/write-an-article/graph.skill.mdgraph source
  • .claude/agents/write-an-article-splitter.mdsubagent
  • .claude/agents/write-an-article-angle.mdsubagent
  • .claude/agents/write-an-article-outline.mdsubagent
  • .claude/agents/write-an-article-facts.mdsubagent
  • .skill-graph/.gitignoresupport
  • .cursor/rules/write-an-article.mdcCursor rule
  • README.mdreadme
  • + 3 more subagents
.claude/skills/write-an-article/SKILL.md
---
name: write-an-article
description: "Plans an article, post or newsletter from four angles in parallel, has an editor check the notes in a fresh context, and writes the draft."
---

# write-an-article

Plans an article, post or newsletter from four angles in parallel, has an editor check the notes in a fresh context, and writes the draft.

This skill is a graph: each step has its own prompt and context, and only the payloads named below move between steps.

## Plan

Run the stages in order. Every model step runs in its own subagent; do not do a step's work yourself. Only command steps and approvals are yours to run. Steps in the same stage do not depend on each other: start them together, in one message with several subagent calls.

The input (`goal`) is the user's goal: their request, word for word, handed on under `### goal`. Ask for it if the user has not given one.

### Stage 1 · 1 step

- **SPLIT** (`splitter`) → subagent `write-an-article-splitter`
  - Hand it: the user's goal.
  - Expect: `subtask_json` (json).
  - Contract check (`subtask_json`): save its output to `.skill-graph/write-an-article/splitter.json`, then run `node -e "const fs=require('fs');const d=JSON.parse(fs.readFileSync(process.argv[1],'utf8'));const k=['angle','outline','facts','reader'];const ok=d!==null&&typeof d==='object'&&Array.isArray(d)===false;const m=ok?k.filter((x)=>Object.hasOwn(d,x)===false):k;if(m.length>0){console.error('Missing keys: '+m.join(', '));process.exit(1)}" .skill-graph/write-an-article/splitter.json` with Bash. Exit code 0 passes.
  - If a contract check fails: re-run this step once with its previous answer and the error output. If it fails again, stop and show the user the output.

### Stage 2 · 4 steps in parallel

- **Angle & Headline** (`angle`) → subagent `write-an-article-angle`
  - Hand it: only the `angle` value from the JSON of SPLIT (`splitter`).
  - Expect: `content_notes` (markdown).
- **Outline** (`outline`) → subagent `write-an-article-outline`
  - Hand it: only the `outline` value from the JSON of SPLIT (`splitter`).
  - Expect: `content_notes` (markdown).
- **Facts & Quotes** (`facts`) → subagent `write-an-article-facts`
  - Hand it: only the `facts` value from the JSON of SPLIT (`splitter`).
  - Expect: `content_notes` (markdown).
- **Reader** (`reader`) → subagent `write-an-article-reader`
  - Hand it: only the `reader` value from the JSON of SPLIT (`splitter`).
  - Expect: `content_notes` (markdown).


… 37 more lines in the kit

Or let Claude adapt it

Add Skill Graph to Claude Code as a connector, then ask. Claude loads this starter, changes it for your project, checks it and hands you the kit.

Set up the connector

Ask Claude

Use Skill Graph: get the write-an-article template, adapt it to this project, validate it until it has no errors, and compile it for Claude Code.

The graph file

The whole workflow is one Markdown file, graph.skill.md: the steps and edges in the frontmatter, one prompt per step below it. The guide explains every field.

graph.skill.md · 150 lines
---
name: write-an-article
description: Plans an article, post or newsletter from four angles in parallel, has an editor check the notes in a fresh context, and writes the draft.
spec: skill-graph/1
topology:
  nodes:
    - id: goal
      type: input
      label: BRIEF (topic, audience, length, voice)
    - id: splitter
      type: orchestrator
      label: SPLIT
      model: sonnet
      tools:
        - Read
    - id: angle
      type: worker
      label: Angle & Headline
      model: haiku
      tools:
        - Read
        - WebSearch
        - WebFetch
    - id: outline
      type: worker
      label: Outline
      model: haiku
      tools:
        - Read
        - WebSearch
        - WebFetch
    - id: facts
      type: worker
      label: Facts & Quotes
      model: haiku
      tools:
        - Read
        - WebSearch
        - WebFetch
    - id: reader
      type: worker
      label: Reader
      model: haiku
      tools:
        - Read
        - WebSearch
        - WebFetch
    - id: verifier
      type: verifier
      label: VERIFIER (Fresh Context)
      isolated_context: true
      model: opus
      tools:
        - Read
        - Grep
        - Glob
      gate: Every fact kept has a source, and the angle and outline match the brief's audience and length.
      on_fail: retry
      max_retries: 1
    - id: merger
      type: synthesizer
      label: FINAL ANSWER
      model: sonnet
      tools:
        - Read
  edges:
    - from: goal
      to: splitter
    - from: splitter
      to:
        - angle
        - outline
        - facts
        - reader
      contract: subtask_json
    - from:
        - angle
        - outline
        - facts
        - reader
      to: verifier
      contract: content_notes
    - from: verifier
      to: merger
      contract: approved_notes
contracts:
  subtask_json:
    format: json
    description: One key per worker id; each value is that worker's task.
  content_notes:
    format: markdown
    description: A numbered list of notes, each marked with its source or as opinion.
  approved_notes:
    format: markdown
    description: The notes that passed the edit, then the cut ones with the reason.
---

# Node Prompts & Edge Contracts

## @node: splitter
You are the managing editor. Read the brief and give each writer the part of the piece they prepare, with the audience and length in mind.

Input:
{{goal}}

Output strictly as JSON with one key per worker: `angle`, `outline`, `facts`, `reader`. Each value is the exact task for that worker.

## @node: angle
Work ONLY on the angle: three possible headlines with a hook for each, and which one fits the audience best and why.

Your task: {{splitter.angle}}

Return your notes as a numbered list. Mark each note with the source it rests on, or with "opinion" when it rests on none.

## @node: outline
Write ONLY the outline: the sections in order, the point of each one, and where examples go.

Your task: {{splitter.outline}}

Return your notes as a numbered list. Mark each note with the source it rests on, or with "opinion" when it rests on none.

## @node: facts
Gather ONLY the facts the piece needs: claims, figures and quotes, each with its source.

Your task: {{splitter.facts}}

Return your notes as a numbered list. Mark each note with the source it rests on, or with "opinion" when it rests on none.

## @node: reader
Think ONLY about the reader: what they already know, the questions they will ask, and the jargon to avoid.

Your task: {{splitter.reader}}

Return your notes as a numbered list. Mark each note with the source it rests on, or with "opinion" when it rests on none.

## @node: verifier
You are the editor. Check each note for accuracy and for fit with the brief.

You only see the raw worker outputs below, not their reasoning. Cut every factual note without a source and every note off the brief, merge duplicates, and list what you cut and why.

Original input: {{goal}}

Worker outputs:
{{workers.output}}

## @node: merger
Write the piece from the approved notes: the headline, a hook paragraph, the sections of the outline, and a closing line. Use only facts from the notes, in the voice and length the brief asks for.

{{verifier.output}}