Build a LangChain social media agent: end-to-end tutorial with Posta

This tutorial walks through building a working LangChain agent that can draft and schedule social posts across LinkedIn, Bluesky, Threads, and any other Posta-supported network. The agent uses the Posta MCP server through langchain-mcp-adapters — so it discovers the tools at runtime instead of you writing custom Tool wrappers. Total time: 15 minutes.

What you'll build

A LangGraph ReAct agent that takes a high-level instruction like "Draft and schedule a LinkedIn post about our v2 launch for tomorrow 9am CET", picks the right Posta tools, calls them with typed arguments, and reports back with the scheduled post ID and URL. No glue code, no hand-rolled API client.

Prerequisites

  • Python 3.11+ and pip.
  • A Posta account with at least one connected social account. 14-day free trial.
  • A Posta API token (Settings → API in the Posta dashboard).
  • An Anthropic API key (or OpenAI — sample uses Claude).

Step 1 — Install dependencies

pip install langchain-anthropic langchain-mcp-adapters langgraph

Step 2 — Wire up the MCP client

MultiServerMCPClient takes a dict of MCP server configs and exposes them as LangChain tools. Point it at posta-mcp over stdio with your Posta token in the env:

# posta_agent.py
import asyncio
import os
from langchain_anthropic import ChatAnthropic
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent

async def main():
    client = MultiServerMCPClient({
        "posta": {
            "command": "npx",
            "args": ["-y", "posta-mcp"],
            "env": {"POSTA_API_TOKEN": os.environ["POSTA_API_TOKEN"]},
            "transport": "stdio",
        }
    })
    tools = await client.get_tools()

    agent = create_react_agent(
        ChatAnthropic(model="claude-sonnet-4-6", temperature=0.3),
        tools,
    )

    result = await agent.ainvoke({
        "messages": [(
            "user",
            "Look up my connected accounts. Draft a LinkedIn post "
            "announcing we shipped v2 of our SDK — focus on the new "
            "per-platform caption limits and the batch media endpoint. "
            "Schedule it for tomorrow at 9am CET. Save as a draft "
            "so I can review."
        )]
    })

    for msg in result["messages"]:
        print(f"[{msg.type}] {msg.content}")

asyncio.run(main())

Step 3 — Run it

export POSTA_API_TOKEN=posta_...
export ANTHROPIC_API_KEY=sk-ant-...

python posta_agent.py

On the first run the agent calls listAccounts to enumerate your connected social accounts, picks the LinkedIn one, drafts the caption with Claude, and calls createPost + schedulePost with the right arguments. Each tool call streams back to the agent, which decides the next step.

Step 4 — Add LangGraph state for multi-turn campaigns

The ReAct agent is great for one-shot prompts. For multi-day campaigns where you want the agent to react to webhooks between turns, wrap it in a LangGraph StateGraph:

from typing import TypedDict
from langgraph.graph import StateGraph, END

class CampaignState(TypedDict):
    messages: list
    scheduled_post_ids: list[str]
    published_post_ids: list[str]

graph = StateGraph(CampaignState)

# "draft" node runs the ReAct agent to draft + schedule
graph.add_node("draft", agent_node)

# "wait_for_publish" pauses until a webhook flips a published_post_ids entry
graph.add_node("wait_for_publish", wait_node)

# "draft_followup" runs after publish — drafts the next day's post
graph.add_node("draft_followup", agent_node)

graph.set_entry_point("draft")
graph.add_edge("draft", "wait_for_publish")
graph.add_edge("wait_for_publish", "draft_followup")
graph.add_edge("draft_followup", END)

campaign = graph.compile()

The wait_for_publish node is the closed-loop half: it sleeps until Posta's HMAC-signed webhook flips the state. For the webhook receiver pattern, see webhook-driven social media agent loops.

When to use the REST path instead

If your LangChain code is a deterministic chain (not an agent that picks tools), wrapping the Posta REST API in a @tool is simpler than running the MCP server. The two-step shape is documented on the LangChain integration page: create the draft with socialAccountIds/mediaIds, then POST /v1/posts/:id/schedule with scheduledAt.

Pitfalls

  • Set temperature low for tool-calling agents. 0.0–0.3 produces stable arg shapes; 0.7+ will occasionally invent arguments that fail JSON schema validation.
  • Always include "save as draft" in the user prompt for the first week. Until you trust the agent's output, schedule everything as drafts and approve manually.
  • If a tool call fails, the ReAct loop retries up to recursion_limit times — keep that bounded (default is 25) to avoid runaway loops on transient platform errors.

Where to go from here

Read the LangChain integration reference for the full LangGraph wiring. For the comparison with CrewAI and OpenAI Agents SDK, see the CrewAI tutorial and the OpenAI Agents SDK tutorial. For the broader pattern map, see agentic social media workflows. 14-day free trial, no credit card.

Ready to simplify your social media workflow?

Join creators and teams who save hours every week with Posta.