Skip to main content
The WhatsApp interface lets you deploy agents, teams, or workflows as WhatsApp bots that handle text, images, video, audio, and documents.

Setup

Follow the WhatsApp deploy guide to create a Meta App, configure the WhatsApp Business API, and set up webhooks. Required configuration:
  • WHATSAPP_ACCESS_TOKEN (from Meta App Dashboard > WhatsApp > API Setup)
  • WHATSAPP_PHONE_NUMBER_ID (from WhatsApp > API Setup)
  • WHATSAPP_VERIFY_TOKEN (any string you choose for webhook verification)
  • Webhook URL set to {prefix}/webhook (use ngrok for local development)

Example Usage

basic.py
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.models.openai import OpenAIChat
from agno.os.app import AgentOS
from agno.os.interfaces.whatsapp import Whatsapp

agent_db = SqliteDb(db_file="tmp/persistent_memory.db")

basic_agent = Agent(
    name="Basic Agent",
    model=OpenAIChat(id="gpt-4o"),
    db=agent_db,
    add_history_to_context=True,
    num_history_runs=3,
    add_datetime_to_context=True,
    markdown=True,
)

agent_os = AgentOS(
    agents=[basic_agent],
    interfaces=[Whatsapp(agent=basic_agent)],
)
app = agent_os.get_app()

if __name__ == "__main__":
    agent_os.serve(app="basic:app", reload=True)

Sessions

Each WhatsApp user gets a single session scoped to their phone number.
Session format: wa:{entity_id}:{user_id}. For example, an agent named “Basic Agent” talking to user +1234567890 produces wa:Basic Agent:1234567890.
Users can send /new to start a fresh session. The old session is preserved in the database, and a new session ID is created with a random suffix. This requires a db on the agent, team, or workflow.

Media

Users can send images, video, audio, and documents to the bot. Media is downloaded from Meta’s servers and passed to the agent automatically. Agents can send media back in their responses. See the media agent example for a complete multimodal agent, and the reference page for supported message types.

WhatsAppTools

WhatsAppTools lets your agents send interactive messages: reply buttons, list menus, images, documents, locations, and reactions.
from agno.tools.whatsapp import WhatsAppTools

agent = Agent(
    tools=[WhatsAppTools(
        enable_send_reply_buttons=True,
        enable_send_list_message=True,
        enable_send_location=True,
    )],
)
See the interactive concierge example for a full agent using all interactive features. For parameters and methods, see the WhatsAppTools reference.

Multi-Instance

Run multiple bots on the same server with different prefix values:
agent_os = AgentOS(
    agents=[basic_agent, research_agent],
    interfaces=[
        Whatsapp(
            agent=basic_agent,
            prefix="/basic",
            access_token=getenv("BASIC_WHATSAPP_ACCESS_TOKEN"),
            phone_number_id=getenv("BASIC_WHATSAPP_PHONE_NUMBER_ID"),
            verify_token=getenv("BASIC_WHATSAPP_VERIFY_TOKEN"),
        ),
        Whatsapp(
            agent=research_agent,
            prefix="/web-research",
            access_token=getenv("RESEARCH_WHATSAPP_ACCESS_TOKEN"),
            phone_number_id=getenv("RESEARCH_WHATSAPP_PHONE_NUMBER_ID"),
            verify_token=getenv("RESEARCH_WHATSAPP_VERIFY_TOKEN"),
        ),
    ],
)
Each instance gets its own route prefix, session namespace, and Meta App credentials.
Each Meta App can only have one webhook callback URL, so multi-instance setups require separate Meta Apps (one per bot), each with its own phone number.

Phone Number Encryption

Enable with enable_encryption=True to encrypt phone numbers before storing them as user_id. Raw numbers are never written to the database.
Whatsapp(agent=my_agent, enable_encryption=True)
# Set WHATSAPP_ENCRYPTION_KEY env var (64 hex chars = 32 bytes)
Phone numbers are encrypted with AES-256-GCM using a deterministic nonce, so the same phone always maps to the same user_id. Requires the cryptography package.

Security

Every incoming webhook is verified using HMAC-SHA256 signature validation:
  1. The X-Hub-Signature-256 header is extracted
  2. A signature is computed: HMAC-SHA256(app_secret, request_body)
  3. The computed signature is compared using constant-time comparison (hmac.compare_digest)
If WHATSAPP_APP_SECRET is not set, the server returns a 500 error unless WHATSAPP_SKIP_SIGNATURE_VALIDATION=true is set. Always configure the App Secret for production. Find it at App Settings > Basic in your Meta App Dashboard.

Troubleshooting

Cause: Webhook not configured or not subscribed to the messages field.Fix: In your Meta App Dashboard, go to WhatsApp > Configuration and verify the callback URL matches your tunnel URL (e.g., https://your-tunnel.ngrok.io/whatsapp/webhook). Click “Manage” and confirm you’re subscribed to the messages field.
Cause: Invalid App Secret or missing signature validation config.Fix: Verify WHATSAPP_APP_SECRET matches the value under App Settings > Basic in your Meta App Dashboard. For local development, set WHATSAPP_SKIP_SIGNATURE_VALIDATION=true.
Cause: Verify token mismatch or server not running.Fix: Ensure WHATSAPP_VERIFY_TOKEN matches the value you entered in the Meta webhook configuration. Your server must be running when you click “Verify and save”.
Cause: Expired or insufficient access token.Fix: Temporary tokens expire after ~24 hours. For production, create a permanent System User token via Meta Business Manager. Ensure the token has whatsapp_business_messaging permission.
Cause: Missing environment variables or agent errors.Fix: Check application logs. Common causes: WHATSAPP_ACCESS_TOKEN not set, expired token, or an error in your agent’s tools or model configuration.
Cause: macOS system Python missing root certificates.Fix: Set the SSL_CERT_FILE environment variable:
export SSL_CERT_FILE=$(python3 -c "import certifi; print(certifi.where())")

Developer Resources

Interface Reference

All parameters, endpoints, and session handling details.

Deploy Guide

Create a Meta App, configure webhooks, and deploy step by step.

WhatsAppTools Reference

Toolkit parameters and methods for interactive messages, media, and locations.

Usage Examples

Agents, teams, media, image generation, reasoning, and more.