Blog post from a brief
Label an issue blog, or post a brief to a webhook. Claude Code researches the topic and proposes three angles. You pick one at the approval gate, it writes the post with sources, an editor model checks it against your voice and flags unsupported claims, and the approved draft is sent to your CMS or docs tool.
- Research angles Claude Code · Sonnet
- Pick an angle You
- Write the post Claude Code · Sonnet
- Edit for voice and claims Claude API · Opus 5
- Approve draft You
- Send draft to CMS Shell
What each step does
Research angles
Claude Code · SonnetResearches the topic on the web and proposes three angles, each with a hook, outline and sources.
Pick an angle
YouYou pick one angle and can add notes for the writer.
Write the post
Claude Code · SonnetWrites the post for the picked angle and checks every fact against its sources.
Edit for voice and claims
Claude API · Opus 5An editor model checks voice and unsupported claims, and sends the draft back until it passes.
Approve draft
YouShows you the final draft. Reject with a comment and it is rewritten.
Send draft to CMS
ShellPosts the title and Markdown to your CMS or docs tool through a webhook.
From copy to first run
- Copy the pipeline JSON with the button above.
- In Jimothy, open Pipelines → New pipeline, paste it under “Or import a pipeline JSON” and click Import.
- Fill in the variables below under Pipeline settings → Variables.
- Triggers → Add trigger → Linear, Jira or GitHub, filtered to the blog label. Or a Webhook trigger with title (topic) and description (brief).
What to fill in
The prompts and commands read these as {{vars.<name>}}. The examples are placeholders: replace them with your own.
| Variable | What to put in it | Example |
|---|---|---|
company | Who is publishing, and what you sell. | Acme, a reporting tool for finance teams |
audience | Who the post is for. | Controllers and finance managers at companies of 50 to 500 people |
voice | Your style guide in a few sentences. The editor step enforces it. | Plain, specific and a little dry. Short paragraphs. Concrete examples over adjectives. N… |
publishWebhookUrl | Where approved drafts go, e.g. a Zapier hook that creates a Google Doc, Notion page or CMS draft. | — |
Show the pipeline JSON
{
"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}}"
}
]
}More for marketing, and beyond
Weekly competitor watch
Checks your competitors’ sites, pricing and changelogs every Monday and posts only what changed since last week.
MarketingSocial posts from a launch
Reads a blog post, release or landing page and drafts posts for LinkedIn, X and your newsletter. You pick the ones to schedule.
MarketingMonthly website content audit
Checks your key pages every month for broken links, outdated claims, stale pricing and weak titles, and posts a prioritised fix list.