{
  "jimothyPipeline": 1,
  "name": "Blog post from a brief",
  "description": "Researches a brief, offers three angles to pick from, writes and edits the post, and sends the approved draft on.",
  "icon": "sparkles",
  "color": "#ec4899",
  "repo": {
    "mode": "scratch"
  },
  "concurrency": 2,
  "variables": {
    "company": "Acme, a reporting tool for finance teams",
    "audience": "Controllers and finance managers at companies of 50 to 500 people",
    "voice": "Plain, specific and a little dry. Short paragraphs. Concrete examples over adjectives. No hype words, no exclamation marks, no \"in today’s fast-paced world\".",
    "publishWebhookUrl": ""
  },
  "steps": [
    {
      "id": "angles",
      "name": "Research angles",
      "type": "agent",
      "description": "Researches the topic on the web and proposes three angles, each with a hook, outline and sources.",
      "harnessId": "claude-code",
      "model": "sonnet",
      "timeoutMinutes": 20,
      "prompt": "We are {{vars.company}}, writing for {{vars.audience}}.\n\nTopic: {{issue.title}}\nBrief:\n{{issue.description | default:\"(no brief beyond the title)\"}}\n\nResearch the topic on the web: what has already been written, what the audience argues about, and data we could cite. Then propose exactly three distinct angles for a blog post, each in this shape:\n\n### Angle 1: <working headline>\n- Hook: <the opening idea in one sentence>\n- Argument: <the post's claim in two sentences>\n- Outline: <four to six section headings>\n- Sources: <the URLs it would lean on>\n\nYour final answer is the three angles and nothing else."
    },
    {
      "id": "pick",
      "name": "Pick an angle",
      "type": "approval",
      "description": "You pick one angle and can add notes for the writer.",
      "dependsOn": [
        "angles"
      ],
      "choices": {
        "fromStep": "angles",
        "mode": "single"
      },
      "approvalMessage": "Pick the angle to write for **{{issue.title}}**. Add a comment with anything the writer should know."
    },
    {
      "id": "draft",
      "name": "Write the post",
      "type": "agent",
      "description": "Writes the post for the picked angle and checks every fact against its sources.",
      "harnessId": "claude-code",
      "model": "sonnet",
      "dependsOn": [
        "pick"
      ],
      "timeoutMinutes": 30,
      "systemPrompt": "You write for {{vars.company}}. Audience: {{vars.audience}}. Voice: {{vars.voice}}",
      "prompt": "Write the blog post for this angle:\n\n{{steps.pick.selected}}\n{{#if steps.pick.comment}}\nNotes from the editor who picked it: {{steps.pick.comment}}\n{{/if}}\nOriginal brief: {{issue.description | default:\"(none)\"}}\n\nOpen the sources and check every fact you use; drop anything you can't confirm. 900 to 1,400 words. Markdown, starting with a # headline, with a \"Sources\" list of the URLs you used at the end. Your final answer is the post and nothing else.{{#if steps.edit.output}}\n\nThe editor reviewed your previous draft. Address every point:\n{{steps.edit.output}}{{/if}}{{#if steps.approve.output}}\n\nYour previous draft was rejected with this feedback. Rewrite it:\n{{steps.approve.output}}{{/if}}"
    },
    {
      "id": "edit",
      "name": "Edit for voice and claims",
      "type": "agent",
      "description": "An editor model checks voice and unsupported claims, and sends the draft back until it passes.",
      "harnessId": "anthropic-api",
      "model": "claude-opus-5",
      "dependsOn": [
        "draft"
      ],
      "timeoutMinutes": 10,
      "passPattern": "VERDICT:\\s*APPROVE",
      "loopBackTo": "draft",
      "maxLoops": 2,
      "prompt": "You are the editor. Voice guide: {{vars.voice}}\n\nDraft:\n{{steps.draft.output}}\n\nList concrete problems only: sentences that break the voice guide, claims or numbers without a source in the Sources list, sections that drift from the headline's argument, and anything a {{vars.audience}} reader would find vague. Quote the sentence for each. End with exactly one line: VERDICT: APPROVE if it's ready, otherwise VERDICT: CHANGES_REQUESTED."
    },
    {
      "id": "approve",
      "name": "Approve draft",
      "type": "approval",
      "description": "Shows you the final draft. Reject with a comment and it is rewritten.",
      "dependsOn": [
        "edit"
      ],
      "loopBackTo": "draft",
      "maxLoops": 3,
      "approvalMessage": "Send this draft on? Reject with a comment to have it rewritten.\n\n---\n\n{{steps.draft.output}}"
    },
    {
      "id": "publish",
      "name": "Send draft to CMS",
      "type": "shell",
      "description": "Posts the title and Markdown to your CMS or docs tool through a webhook.",
      "dependsOn": [
        "approve"
      ],
      "timeoutMinutes": 2,
      "command": "printf '{\"brief\":%s,\"title\":%s,\"markdown\":%s}' {{issue.key | json}} {{steps.draft.output | first_line | json}} {{steps.draft.output | json}} | curl -fsS -X POST -H 'Content-Type: application/json' --data @- {{vars.publishWebhookUrl}}"
    }
  ]
}