Give a LangChain agent a WhatsApp number
A LangChain agent gets WhatsApp in two halves. Incoming messages arrive at your web route through the number's webhook, and the route invokes the agent. To act, the agent loads the EasyCoexistence MCP tools through LangChain's MCPAdapter with OAuth, or calls the Cloud API directly with the number's token and phone number id.
Minimum langchain[mcp] version for the langchain.mcp namespace, which is in beta.
Runs the full OAuth 2.1 flow: discovery, dynamic client registration, browser redirect and token exchange.
Meta's error when more than 24 hours have passed since the recipient last replied.
How does a LangChain agent load the WhatsApp tools?
Through MCPAdapter, LangChain's MCP client, which hands an MCP server's tools to create_agent as ordinary LangChain tools. It needs langchain[mcp] at version 1.4.0 or later and is marked beta.
Authentication is delegated to FastMCP. Passing auth="oauth" on the client runs the full OAuth 2.1 flow: discovery, dynamic client registration, the browser redirect and the token exchange. That is what the EasyCoexistence MCP server expects, so there is no key to create or paste. By default tokens live in memory and each run repeats the browser step; a FastMCP OAuth provider with a token store keeps them between runs.
Once loaded, the agent sees the tools with their descriptions: list_numbers first, because every other tool takes a connection_id from it, then send_message, send_template, list_templates, get_number_health and the rest.
from fastmcp.client import Client
from langchain.agents import create_agent
from langchain.mcp import MCPAdapter
URL = "https://easycoexistence.com/api/mcp"
async def build_agent(model: str):
async with MCPAdapter(Client(URL, auth="oauth")) as adapter:
tools = await adapter.list_tools()
return create_agent(model, tools)How does an incoming WhatsApp message reach the agent?
Through the webhook, because MCP cannot do it. The protocol is request and response, so nothing in it lets a server wake a client when a customer writes.
Set the number's webhook destination to a route in your own application, with a long random secret in the URL path. The route answers Meta's verification GET with the raw challenge, accepts each POST, returns 200 at once and queues the work. A worker then takes the sender and the text from the payload and invokes the agent with them, with the sender's number as the thread id so memory stays per customer.
Check the secret in the URL rather than the X-Hub-Signature-256 header. Meta signs with the Tech Provider's app secret, which is never shared, so that header cannot be validated by the customer.
Should the agent send through MCP or through the Cloud API?
Either works, and the difference is who holds the rules. The MCP tools carry the WhatsApp rules in their descriptions, such as send_message working only inside the 24 hour window and send_template being the way to reach someone who has not written. A model reading those descriptions picks the right one most of the time, and an agent deciding freely is where that helps.
A plain tool of your own that posts to the Cloud API messages endpoint with the number's token is simpler when the agent's job is narrow, such as always replying to the person who just wrote. Then the window check sits in your code, which is where a rule that must never be broken belongs. Free text outside the window comes back as error 131047, and the customer never sees anything.
Common mistakes
- Expecting MCP to deliver incoming messages. Without a webhook route, the agent never hears from a customer.
- Leaving OAuth tokens in memory on a server. Each restart wants a browser sign-in; persist them with a token store.
- Using one thread for every customer. Key the agent's memory on the sender's number.
Connect the number at easycoexistence.com, set the webhook destination to your route, and load the MCP tools into the agent with one OAuth sign-in. From US$ 9 per number per month, falling to US$ 1 as you add numbers, with the first 3 days free.
Frequently asked questions
Is this Python only?
The MCPAdapter example is Python. The webhook and the Cloud API are plain HTTP, so any language LangChain runs in can do the receiving and sending.
Does the agent need list_numbers every time?
It needs a connection_id, and list_numbers is the only place one comes from. On a single number the agent calls it once at the start.
Can the team still reply from the phone?
Yes. Coexistence keeps the WhatsApp Business app working, and phone replies reach your route as echo events the agent can take into account.
Does EasyCoexistence read the conversation?
No. Meta delivers straight to your route and message content is never stored on our side. The MCP tools read account and number state.
Keep reading
Ready to get started?
Set up WhatsApp Coexistence in minutes, not months. The app keeps working on the phone.
Start Free TrialVerified on