whatsapp-agent
A Python SDK and MCP server for the WhatsApp Agent Platform — the API behind agents on personal WhatsApp. Send and receive messages, upload and download media, and drive it all from n8n, Claude, Cursor, or any other MCP-compatible tool.
- A typed Python client for every endpoint in the developer manual: sending, long-polling for updates, read receipts/typing, and media.
- An MCP server (
whatsapp-agent mcp) so n8n's MCP Client Tool node — or Claude Desktop, Cursor, or any MCP host — can send/receive WhatsApp messages as tool calls, with no glue code. - A WhatsApp text-formatting module. WhatsApp is not Markdown —
*bold*, not**bold**— and this is the most common way agent output shows up broken in a chat.whatsapp_agent.formattingandwhatsapp_agent.markdownhandle it. - Client-side correctness the manual asks for: per-endpoint rate limiting, retry semantics that never double-send, and a long-poll loop that can't silently drop a message.
Two ways to use this
- Full package (
pip install whatsapp-agent) — typed models, automatic per-endpoint rate limiting, WhatsApp text formatting, and an MCP server for n8n/Claude/Cursor. Reach for this for an agent, a workflow, or anything long-running (alisten()loop). standalone/whatsapp_agent.py— a single, dependency-light file (requests+python-dotenv, nothing else) you copy directly into your project aswhatsapp_agent.py. For a monitoring script, a cron job, a web app's notification sender, or anything else that just needs to fire a plain HTTP request to send a WhatsApp message and isn't an AI agent at all. Its filename matches the installed package's import path, sofrom whatsapp_agent import WhatsAppAgentClientis exactly the same line of code either way — copy the file today, switch topip install whatsapp-agentlater, and nothing else in your code changes.
Both talk to the same API and cover the same endpoints; the standalone file just trades the package's extra machinery (rate limiting, typed models, MCP) for zero install footprint.
Install
pip install whatsapp-agent # SDK only
pip install "whatsapp-agent[mcp]" # SDK + MCP server
Requires Python 3.10+ (the bundled MCP SDK requires it). Or, for the simple single-file option -- which has no such dependency and works on Python 3.9+ -- just copy standalone/whatsapp_agent.py into your project as whatsapp_agent.py, no install step.
Get an API token
Open WhatsApp on your phone: Settings → Agents → Create an agent, set a name and avatar, open the agent's chat, then Chat info → API key. Store it somewhere safe — if you uninstall the app, you have to regenerate it.
cp .env.example .env # then paste your key into WHATSAPP_API_KEY
Quick start
from whatsapp_agent import WhatsAppAgentClient
client = WhatsAppAgentClient() # reads WHATSAPP_API_KEY from the environment
for message in client.listen(auto_mark_read=True):
text = message.text or f"[{message.type}]"
print(f"{message.from_}: {text}")
client.reply_text(message, "Got it!")
An agent can only message the WhatsApp account that created it — there's no way to message an arbitrary number. to accepts the from value of an inbound message, or a bare phone number for the creator.
Sending a one-off notification instead of running a listen loop? Set WHATSAPP_USER_ID in .env and skip to entirely:
client.notify("Backup finished successfully.")
Sending media:
media_id = client.upload_media("invoice.pdf")
client.send_document(message.from_, media_id, filename="invoice.pdf", caption="Here you go")
Slow reply? Keep the typing indicator alive (it otherwise dies after 25s):
with client.typing(message.id):
reply = call_your_llm(message.text)
client.reply_text(message, reply)
See examples/echo_bot.py and examples/media_bot.py for complete, runnable scripts.
WhatsApp text formatting
WhatsApp has its own inline formatting syntax, and it is not Markdown:
| Style | Markdown (for contrast) | |
|---|---|---|
| Bold | *text* |
**text** |
| Italic | _text_ |
*text* or _text_ |
| Strikethrough | ~text~ |
~~text~~ |
| Monospace block | ```text``` |
```lang\ntext\n``` |
| Inline code | `text` |
same |
| Blockquote | > text |
same |
| Bulleted list | - item |
same |
| Numbered list | 1. item |
same |
Headings, links, images, tables and horizontal rules have no WhatsApp equivalent at all. Send an LLM's raw Markdown output and **bold** shows up in the chat as two literal asterisks — this is the single most common way agent replies look broken.
from whatsapp_agent.formatting import bold, italic
from whatsapp_agent.markdown import from_markdown
client.send_text(to, f"{bold('Order #1234')} shipped {italic('today')}.")
# Or convert an LLM's Markdown output wholesale:
llm_reply = "**Total:** $42.00\n\nSee the [invoice](https://example.com/inv.pdf)."
client.send_text(to, from_markdown(llm_reply))
# -> "*Total:* $42.00\n\nSee the invoice (https://example.com/inv.pdf)."
Full reference, including escaping (WhatsApp has no escape character) and truncation rules: docs/formatting.md.
Use it from n8n (or Claude, or Cursor)
whatsapp-agent mcp --http --port 8765
Point n8n's MCP Client Tool node at http://localhost:8765/mcp, and the workflow gets wa_send_text, wa_send_media, wa_upload_media, wa_download_media, wa_get_updates, wa_mark_read, and wa_format_text as callable tools — no custom HTTP Request nodes, no hand-rolled auth.
Full setup (including Claude Desktop / Cursor config and an n8n workflow walkthrough): docs/mcp.md and docs/n8n.md.
Feature coverage
Everything in the developer manual is implemented:
| Manual section | SDK |
|---|---|
| §1 Send a message | send_text, send_image, send_audio, send_video, send_document, send_sticker, reply_text |
| §2 Receive messages | get_updates, listen |
| §3 Read receipts & typing | mark_read, typing() |
| §4 Media | upload_media, upload_media_bytes, get_media_info, download_media, delete_media |
| §5 Errors | typed exceptions per error.code — see docs/errors.md |
| §6 Rate limits | automatic, per-endpoint — see docs/rate-limits.md |
Documentation
docs/quickstart.md— install, auth, first messagedocs/api-reference.md— every client methoddocs/formatting.md— WhatsApp's text formatting, in fulldocs/mcp.md— running the MCP server, client configsdocs/n8n.md— n8n workflow walkthroughdocs/errors.md— exception types and what to dodocs/rate-limits.md— per-endpoint budgets and backoffdocs/migration.md— coming from the original single-filewhatsapp_agent.py
Roadmap
Not in v0.1, tracked for later releases:
AsyncWhatsAppAgentClient(httpx-based; the transport layer is already structured for this — seetransport.py)whatsapp-agent bridge --webhook <url>— long-poll and forward inbound messages to an n8n/Make webhook, for a push-based inbound path instead of scheduled polling- OpenAI/Anthropic tool-schema exporters for hand-rolled agent loops that don't use MCP
Contributions welcome — see CONTRIBUTING.md.
License
MIT — see LICENSE.
Release files for whatsapp-agent 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| whatsapp_agent-0.1.0.tar.gz | 280.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| whatsapp_agent-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 321.5 kB
Release files / whatsapp_agent-0.1.0.tar.gz
| Download URL | whatsapp_agent-0.1.0.tar.gz |
|---|---|
| Size | 280.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
91efe1809fd07f0843fae838c07e7b4f361e06fa1fae5e8ce034b24f02d14fe4
|
|
BLAKE2b-256 checksum How to use checksums |
b0b24bf59f60807aff483965e64080850aeeccba4562b165a38c65325b352674
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency logRelease files / whatsapp_agent-0.1.0-py3-none-any.whl
| Download URL | whatsapp_agent-0.1.0-py3-none-any.whl |
|---|---|
| Size | 41.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
84c30f360219aea0f4d415c2a1af61f5c8a6a2c672627eb1f64b76072e9e3b6f
|
|
BLAKE2b-256 checksum How to use checksums |
53ba7ed133b35f1e71b014982b90c9c0bde2a1994feb2a37ca77954c06892e41
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency log