---
title: "How do I call Ballet playbooks from LangChain?"
description: "TL;DR: Use langchain-mcp-adapters to load Ballet's MCP tools into a LangChain agent, or define a @tool that calls the execute endpoint. Configure MultiServerMCPClient with the streamablehttp transport pointed at https://app.ballet.dev/mcp and an Authorization header, then await client.gettools()."
canonical_url: "https://docs.ballet.dev/articles/how-do-i-call-ballet-playbooks-from-langchain-9oGBp3Ih16"
md_url: "https://docs.ballet.dev/articles/how-do-i-call-ballet-playbooks-from-langchain-9oGBp3Ih16.md"
---
# How do I call Ballet playbooks from LangChain?

**TL;DR:** Use `langchain-mcp-adapters` to load Ballet's MCP tools into a LangChain agent, or define a `@tool` that calls the execute endpoint. Configure `MultiServerMCPClient` with the `streamable_http` transport pointed at `https://app.ballet.dev/mcp` and an `Authorization` header, then `await client.get_tools()`.

## Who this is for

Python developers building agents with LangChain or LangGraph.

## Option A: Load Ballet's tools over MCP

Install the adapter (`pip install langchain-mcp-adapters`), point a `MultiServerMCPClient` at Ballet's endpoint, and pass the resulting tools to `create_agent`.

```python
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent
import os

client = MultiServerMCPClient(
    {
        "ballet": {
            "transport": "streamable_http",
            "url": "https://app.ballet.dev/mcp",
            "headers": {"Authorization": f"Bearer {os.environ['BALLET_API_TOKEN']}"},
        }
    }
)

tools = await client.get_tools()
agent = create_agent("openai:gpt-4o", tools)

result = await agent.ainvoke(
    {"messages": "Run the lead-enrichment playbook for cus_123 and summarize the result."}
)
print(result)
```

The agent now has Ballet's tools (`run_playbook`, `get_run`, `list_playbooks`, …) available.

## Option B: Define one playbook as a tool

To expose a single playbook, wrap the REST execute endpoint in a `@tool`.

```python
import json, os, httpx
from langchain_core.tools import tool

@tool
async def run_onboarding(customer_id: str) -> dict:
    """Run the customer onboarding playbook in Ballet."""
    url = f"https://app.ballet.dev/api/playbooks/{os.environ['BALLET_PLAYBOOK_ID']}/execute"
    headers = {
        "Authorization": f"Bearer {os.environ['BALLET_API_TOKEN']}",
        "Content-Type": "application/json",
    }
    result = None
    async with httpx.AsyncClient(timeout=None) as http:
        async with http.stream("POST", url, headers=headers,
                               json={"input": {"customerId": customer_id}}) as res:
            async for line in res.aiter_lines():
                if line.startswith("data:"):
                    event = json.loads(line[5:].strip())
                    if event.get("type") == "run_stop":
                        result = event["run"]
    return {"success": result and result.get("success"), "output": result and result.get("output")}
```

See [Run playbooks over the REST API](/articles/how-do-i-run-a-playbook-over-the-rest-api-KQIz0apagm) for the event details.

## Which option should I use?

- **MCP** — give the agent every playbook in the workspace.
- **REST tool** — expose one playbook with a typed signature.

## Related articles

- [How do I use Ballet playbooks in an agent framework?](/articles/how-do-i-use-ballet-playbooks-in-an-agent-framework-q3PWTx18lY)
- [The MCP endpoint](/articles/how-do-i-connect-to-ballets-mcp-endpoint-1ydPKBzHZm)
- [Run playbooks over the REST API](/articles/how-do-i-run-a-playbook-over-the-rest-api-KQIz0apagm)
