Post with CrewAI

Post to social media
with CrewAI.

Share one PostLake tool across the crew (or MCP). Publishing stays one call; the normalised response is what the next agent reasons over.

Get started free →

Free tier. No card · one API for every network · full MCP access

In shortOne CrewAI tool → PostLake publish. Next agents in the crew read the same targets[] shape.

When this guide is for you

A CrewAI crew needs a publisher role (research → write → post) without each agent speaking a different social API.

Before you start

Same setup the docs quickstart uses. Do this once:

  1. Sign up at app.postlake.dev and verify your email (unlocks free credits).
  2. On Channels, create a profile (e.g. my-brand) and connect at least one account. Bluesky is the fastest first channel: no app review. Instagram/TikTok/Facebook need each platform's review before API posting.
  3. Account menu → API Keys → create a key (sk_live_…). It shows once; treat it like a password.

Working example in CrewAI

Connect accounts once in the dashboard, then this is the publish call:

from crewai.tools import tool
import os, requests, uuid

@tool("Post to social")
def post_to_social(text: str) -> str:
    """Publish to the my-brand profile via PostLake. Returns JSON text."""
    r = requests.post(
        "https://api.postlake.dev/v1/posts",
        headers={
            "Authorization": f"Bearer {os.environ['POSTLAKE_API_KEY']}",
            "Idempotency-Key": str(uuid.uuid4()),
        },
        json={"text": text, "profile": "my-brand"},
    )
    r.raise_for_status()
    return r.text  # full Post JSON for the next agent

# Agent(role="Publisher", tools=[post_to_social], ...)

Make it work in CrewAI

Tool-specific glue on top of the shared setup above:

  1. Connect accounts under one profile the Publisher agent is allowed to use.
  2. Add one tool that POSTs /v1/posts and returns the response body so downstream agents can parse targets.
  3. Attach the tool only to the publisher role, keep researchers read-only.
  4. Or connect MCP and skip the custom tool entirely.

Read the response (don't skip this)

You get one Post with an overall state and a targets[] array. One entry per account. Always check each target; partial success is normal.

{
  "id": "post_a1b2c3",
  "state": "partial",
  "targets": [
    { "platform": "bluesky",  "state": "published", "url": "https://bsky.app/…" },
    { "platform": "linkedin", "state": "failed",
      "error": { "type": "invalid_request", "message": "…", "retryable": false } }
  ]
}

Where the post goes

Same rules as the docs. Pick one addressing style:

See Publishing: where to post.

Do more (same API)

Pitfalls specific to this path

Want zero wrapper code? Connect the hosted MCP server (https://api.postlake.dev/mcp) over OAuth. Same accounts and responses as this API path. Agents overview.

Common questions

How do I add social posting to a CrewAI agent?

Pass a custom tool that calls PostLake /v1/posts (or enable MCP). Give it to the publisher agent. One tool covers every network on the profile.

Does each agent need its own posting logic?

No. Share one PostLake tool. Other agents should consume the JSON result, not call platform APIs.

Can CrewAI use PostLake via MCP?

Yes, when your CrewAI/MCP host supports it. Same server URL as the MCP docs.

Go deeper in the docs

These guides stay short on purpose. Canonical behaviour lives here:

Also: Media · Errors · MCP · Analytics

Related guides

All guides · Full docs · llms.txt · Markdown

Stuck? The docs are the source of truth, start at Publishing.

Open the dashboard →