← All blueprints
🔁

Blog Repurposer LangGraph

blueprint · 4 agents · 1 MCP server
987★ stars
121forks
4.6rating

What it does

Three channel writers work on the same source post in parallel: a thread writer distills the argument into a sequence where each line earns the next, a newsletter writer reshapes it with a personal opening and a single clear link, and a LinkedIn writer rewrites it for the feed without engagement-bait. A curator checks each piece against the source for factual drift and voice, fixes what's off, and files the set in Notion ready to schedule. Nothing is posted anywhere by the workflow.

The cast · 4 agents

Curatorcuratorreasoning

Check each version against the source post for factual drift and voice mismatch; fix what's off. File the three versions in Notion as one page with a section per channel. Do not post anything anywhere.

notes.create_page
Thread WriterthreadWriterreasoning

Distill the post into a thread. Lead with the sharpest claim, one idea per entry, each line earning the next. No numbering filler, no 'a thread 🧵'. Keep every fact faithful to the source.

no tools · reasoning only
LinkedIn WriterlinkedinWriterreasoning

Rewrite the post for LinkedIn: a first line that hooks without bait, short paragraphs, a concrete takeaway, no hashtag spam and no engagement questions. Professional but human.

no tools · reasoning only
Newsletter WriternewsletterWriterreasoning

Reshape the post as a newsletter section: a personal opening line, the core insight in the reader's terms, one clear link back to the full post. Warmer than the blog, never salesy.

no tools · reasoning only

Flow

⇉ parallel
Thread Writerthread
Newsletter Writernewsletter
LinkedIn Writerlinkedin
Curatorbundle

Interface

Inputs
poststring
The finished post to repurpose, plus a line on your voice if you have one.
Outputs
bundlestring
The three channel versions as filed in Notion.

Depends on · 1 MCP server

📋mcpcom.notion/mcpnotesEPublisher
⤓ Export runnable code
# Generated by @socketcat/compiler for target: langgraph
# blueprint: com.socketcat/blog-repurposer v1.0.0   schema: socketcat.dev/blueprint/v0
# This code is yours. Edit it freely. The socketcat_runtime helper is optional and can be vendored.

from typing import TypedDict
from langgraph.graph import StateGraph, START, END
import socketcat_runtime as _rt

class State(TypedDict, total=False):
    post: object
    bundle: object
    thread: object
    newsletter: object
    linkedin: object

def node_Fork_0(state):
    return {}

def node_Join_1(state):
    return {}

def node_AgentInvoke_2(state):
    return _rt.run_agent("threadWriter", state, {"post":"post"}, "thread")

def node_AgentInvoke_3(state):
    return _rt.run_agent("newsletterWriter", state, {"post":"post"}, "newsletter")

def node_AgentInvoke_4(state):
    return _rt.run_agent("linkedinWriter", state, {"post":"post"}, "linkedin")

def node_AgentInvoke_5(state):
    return _rt.run_agent("curator", state, {"post":"post","thread":"thread","linkedin":"linkedin","newsletter":"newsletter"}, "bundle")

def build():
    b = StateGraph(State)
    b.add_node("Fork_0", node_Fork_0)
    b.add_node("Join_1", node_Join_1)
    b.add_node("AgentInvoke_2", node_AgentInvoke_2)
    b.add_node("AgentInvoke_3", node_AgentInvoke_3)
    b.add_node("AgentInvoke_4", node_AgentInvoke_4)
    b.add_node("AgentInvoke_5", node_AgentInvoke_5)
    b.add_edge(START, "Fork_0")
    b.add_edge("Fork_0", "AgentInvoke_2")
    b.add_edge("Fork_0", "AgentInvoke_3")
    b.add_edge("Fork_0", "AgentInvoke_4")
    b.add_edge("Join_1", "AgentInvoke_5")
    b.add_edge("AgentInvoke_2", "Join_1")
    b.add_edge("AgentInvoke_3", "Join_1")
    b.add_edge("AgentInvoke_4", "Join_1")
    b.add_edge("AgentInvoke_5", END)
    return b.compile()

INPUTS = ["post"]
OUTPUTS = ["bundle"]

if __name__ == "__main__":
    _rt.main(build, INPUTS, OUTPUTS)
blueprint.json (the portable format)
{
  "id": "com.socketcat/blog-repurposer",
  "flow": {
    "type": "sequence",
    "blocks": [
      {
        "type": "parallel",
        "blocks": [
          {
            "in": {
              "post": "post"
            },
            "out": "thread",
            "use": "threadWriter",
            "type": "agent"
          },
          {
            "in": {
              "post": "post"
            },
            "out": "newsletter",
            "use": "newsletterWriter",
            "type": "agent"
          },
          {
            "in": {
              "post": "post"
            },
            "out": "linkedin",
            "use": "linkedinWriter",
            "type": "agent"
          }
        ]
      },
      {
        "in": {
          "post": "post",
          "thread": "thread",
          "linkedin": "linkedin",
          "newsletter": "newsletter"
        },
        "out": "bundle",
        "use": "curator",
        "type": "agent"
      }
    ]
  },
  "tags": [
    "marketing",
    "content",
    "parallel",
    "repurposing"
  ],
  "title": "Blog Repurposer",
  "agents": {
    "curator": {
      "model": {
        "hint": "reasoning"
      },
      "title": "Curator",
      "tools": [
        "notes.create_page"
      ],
      "instructions": "Check each version against the source post for factual drift and voice mismatch; fix what's off. File the three versions in Notion as one page with a section per channel. Do not post anything anywhere."
    },
    "threadWriter": {
      "model": {
        "hint": "reasoning"
      },
      "title": "Thread Writer",
      "instructions": "Distill the post into a thread. Lead with the sharpest claim, one idea per entry, each line earning the next. No numbering filler, no 'a thread 🧵'. Keep every fact faithful to the source."
    },
    "linkedinWriter": {
      "model": {
        "hint": "reasoning"
      },
      "title": "LinkedIn Writer",
      "instructions": "Rewrite the post for LinkedIn: a first line that hooks without bait, short paragraphs, a concrete takeaway, no hashtag spam and no engagement questions. Professional but human."
    },
    "newsletterWriter": {
      "model": {
        "hint": "reasoning"
      },
      "title": "Newsletter Writer",
      "instructions": "Reshape the post as a newsletter section: a personal opening line, the core insight in the reader's terms, one clear link back to the full post. Warmer than the blog, never salesy."
    }
  },
  "estate": {
    "thread": {
      "type": "object",
      "description": "The thread version."
    },
    "linkedin": {
      "type": "object",
      "description": "The LinkedIn version."
    },
    "newsletter": {
      "type": "object",
      "description": "The newsletter version."
    }
  },
  "$schema": "socketcat.dev/blueprint/v0",
  "authors": [
    {
      "url": "https://socketcat.com",
      "name": "SocketCat"
    }
  ],
  "license": "MIT",
  "servers": [
    {
      "ref": "com.notion/mcp",
      "alias": "notes"
    }
  ],
  "summary": "Rewrites one finished post for three channels in parallel, checks each against the source, and files the set in Notion.",
  "targets": [
    "langgraph",
    "*"
  ],
  "version": "1.0.0",
  "interface": {
    "inputs": {
      "post": {
        "type": "string",
        "description": "The finished post to repurpose, plus a line on your voice if you have one."
      }
    },
    "outputs": {
      "bundle": {
        "type": "string",
        "description": "The three channel versions as filed in Notion."
      }
    }
  },
  "extensions": {
    "dev.langgraph": {
      "checkpointer": "memory"
    }
  },
  "description": "Three channel writers work on the same source post in parallel: a thread writer distills the argument into a sequence where each line earns the next, a newsletter writer reshapes it with a personal opening and a single clear link, and a LinkedIn writer rewrites it for the feed without engagement-bait. A curator checks each piece against the source for factual drift and voice, fixes what's off, and files the set in Notion ready to schedule. Nothing is posted anywhere by the workflow."
}