Skip to main content

whatsapp-agent

CI PyPI Python versions License: MIT

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.formatting and whatsapp_agent.markdown handle 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 (a listen() loop).
  • standalone/whatsapp_agent.py — a single, dependency-light file (requests + python-dotenv, nothing else) you copy directly into your project as whatsapp_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, so from whatsapp_agent import WhatsAppAgentClient is exactly the same line of code either way — copy the file today, switch to pip install whatsapp-agent later, 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 WhatsApp 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

Roadmap

Not in v0.1, tracked for later releases:

  • AsyncWhatsAppAgentClient (httpx-based; the transport layer is already structured for this — see transport.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)

Source distribution for whatsapp-agent 0.1.0
File Size Uploaded
whatsapp_agent-0.1.0.tar.gz 280.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for whatsapp-agent 0.1.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page