Adding WhatsApp Tools to OpenAI Agents SDK and LangChain via MCP
Production agentic apps need to message humans. Here's how to wire WhatsApp into OpenAI Agents SDK and LangChain agents using the @gaviwhatsapp/mcp server.
If you're building production agentic apps in 2026, you're probably using one of these:
- OpenAI Agents SDK — OpenAI's official Python framework for multi-agent workflows
- LangChain / LangGraph — the most popular agent framework, supports both Python and TypeScript
- CrewAI, AutoGen, Mastra — newer frameworks for multi-agent systems
- Direct API integration — Anthropic API or OpenAI API with your own agent loop
All of these support MCP for tools — either natively or via adapters. That means a single MCP server like @gaviwhatsapp/mcp gives every framework the same WhatsApp toolkit, with no per-framework integration work.
This post shows the wiring for the two biggest: OpenAI Agents SDK and LangChain.
Why agents need WhatsApp
The most useful production agents do real work and close the loop with humans:
- A customer support agent that answers WhatsApp messages, queries your DB, escalates to humans when needed
- A lead-qualification agent that reaches out to new signups on WhatsApp, qualifies them, books a meeting
- A monitoring agent that watches infrastructure and alerts on-call via WhatsApp
- A fulfillment agent that texts customers at every step of an order
- A booking agent for service businesses that confirms appointments and handles reschedules on WhatsApp
In every case, the agent's intelligence is mature; what was missing was the messaging channel. WhatsApp solves that — 3 billion users, 98% open rates within an hour.
Pattern A: OpenAI Agents SDK
The OpenAI Agents SDK has first-class MCP support. You wire up the WhatsApp MCP server once and any agent in your app can call its tools.
Setup
pip install openai-agents
npm install -g @gaviwhatsapp/mcp # the MCP server (Node-based, runs via npx)
Define an agent with MCP tools
from agents import Agent, Runner
from agents.mcp import MCPServerStdio
# Connect to the Gavi WhatsApp MCP server
whatsapp_mcp = MCPServerStdio(
name="gaviwhatsapp",
params={
"command": "npx",
"args": ["@gaviwhatsapp/mcp", "--api-key", "gv_YOUR_KEY"],
},
)
agent = Agent(
name="SupportAgent",
instructions=(
"You are a customer support agent. When a user sends a WhatsApp, "
"look up their order status if relevant, answer their question, "
"and reply via the send_message tool."
),
mcp_servers=[whatsapp_mcp],
)
# Run the agent on an incoming WhatsApp message
async def handle_incoming(phone: str, text: str):
async with whatsapp_mcp:
result = await Runner.run(
agent,
input=f"User {phone} said: {text}. Reply on WhatsApp.",
)
return result.final_output
The agent now has access to all WhatsApp tools (send_message, send_template, send_media, send_broadcast, list_templates, list_messages) automatically — you didn't define any of them in your code.
Multi-agent example
A common pattern: a router agent decides whether to hand off to a support agent (which has WhatsApp + DB access) or a sales agent (which has WhatsApp + CRM access):
sales_agent = Agent(
name="Sales",
instructions="You qualify leads and book demos. Reply via WhatsApp.",
mcp_servers=[whatsapp_mcp, crm_mcp],
)
support_agent = Agent(
name="Support",
instructions="You resolve customer issues. Look up orders, escalate when needed.",
mcp_servers=[whatsapp_mcp, db_mcp],
)
router = Agent(
name="Router",
instructions="Decide which agent should handle this message.",
handoffs=[sales_agent, support_agent],
)
Pattern B: LangChain / LangGraph
LangChain supports MCP via the @langchain/mcp-adapters package (TypeScript) or langchain-mcp-adapters (Python). The adapter connects to an MCP server and exposes its tools as LangChain Tool objects.
TypeScript / LangGraph
npm install langchain @langchain/mcp-adapters @langchain/anthropic
import { MultiServerMCPClient } from '@langchain/mcp-adapters'
import { createReactAgent } from '@langchain/langgraph/prebuilt'
import { ChatAnthropic } from '@langchain/anthropic'
const mcpClient = new MultiServerMCPClient({
gaviwhatsapp: {
transport: 'stdio',
command: 'npx',
args: ['@gaviwhatsapp/mcp', '--api-key', 'gv_YOUR_KEY'],
},
})
const tools = await mcpClient.getTools()
const agent = createReactAgent({
llm: new ChatAnthropic({ model: 'claude-3-5-sonnet-latest' }),
tools,
})
const result = await agent.invoke({
messages: [
{ role: 'user', content: 'Send a WhatsApp to +919876543210 saying tests passed.' },
],
})
Python
pip install langchain langchain-mcp-adapters langchain-anthropic
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent
from langchain_anthropic import ChatAnthropic
client = MultiServerMCPClient({
"gaviwhatsapp": {
"transport": "stdio",
"command": "npx",
"args": ["@gaviwhatsapp/mcp", "--api-key", "gv_YOUR_KEY"],
}
})
tools = await client.get_tools()
agent = create_agent(ChatAnthropic(model="claude-3-5-sonnet-latest"), tools)
result = await agent.ainvoke({
"messages": [("user", "Send a WhatsApp to +919876543210 saying tests passed.")]
})
What tools the agent gets
| Tool | Use case |
|---|---|
send_message | Free-form text within the 24-hour conversation window |
send_template | Meta-approved template (cold messages, OTPs, transactional, marketing) |
send_media | Image, video, document, audio |
send_broadcast | Template send to many recipients with per-row variables |
list_templates | Discover approved templates |
list_messages | Read message history with delivery status |
These are exposed identically to every framework — the agent's framework-specific tool schema is auto-generated from MCP.
Production patterns worth knowing
1. Use templates for outbound
When your agent initiates a conversation (i.e. the user hasn't messaged your number in the last 24 hours), you must use a Meta-approved template. Create them in the Gavi dashboard and the agent can call send_template with the right name and variables.
2. Cap iterations
Bound the number of agent loops per user turn (typically 5-10) to prevent runaways and limit cost.
3. Memory
Store conversation history per phone number in Postgres / Redis. On each new inbound message, prepend the last N turns to the agent's input.
4. Webhook signature verification
Verify incoming WhatsApp webhook signatures before invoking your agent — this prevents abuse:
import { verifyWebhookSignature } from '@gaviwhatsapp/whatsapp'
if (!verifyWebhookSignature(body, signature, process.env.WEBHOOK_SECRET)) {
return new Response('Invalid signature', { status: 401 })
}
5. Tool result handling
Some MCP tool calls return data the agent will use in subsequent steps (e.g. list_messages then send_message). Make sure your framework's MCP adapter feeds tool results back into the agent's context — both OpenAI Agents SDK and LangChain handle this automatically.
Other patterns we cover
- End-to-end chatbot architecture with memory, business tools, and human handoff: WhatsApp chatbot with MCP
- Personal AI assistant in Claude Desktop: Claude Desktop + WhatsApp
- The flagship "why agents need WhatsApp" post: Give your AI agent the power to message humans on WhatsApp
Pricing
$9.99/mo flat from Gavi. No per-tool-call fee, no per-conversation fee, no markup on Meta's per-message charges (which go directly to your WhatsApp Business Account).
Try it: gaviventures.com · GitHub · npm
Ready to try Gavi WhatsApp?
Send WhatsApp messages from your code, AI agent, or CRM in under 5 minutes.