Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Whatsapp integration #2335

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
61 changes: 61 additions & 0 deletions cookbook/examples/apps/whatsapp_chat_agent/agents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import logging
import os

from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.storage.agent.sqlite import SqliteAgentStorage
from agno.tools.whatsapp import WhatsAppTools
from agno.tools.yfinance import YFinanceTools
from dotenv import load_dotenv

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Load environment variables
load_dotenv()

# Configure constants
VERIFY_TOKEN = os.getenv("WHATSAPP_VERIFY_TOKEN")
if not VERIFY_TOKEN:
raise ValueError("WHATSAPP_VERIFY_TOKEN must be set in .envrc")

WEBHOOK_URL = os.getenv("WHATSAPP_WEBHOOK_URL")
if not WEBHOOK_URL:
raise ValueError("WHATSAPP_WEBHOOK_URL must be set in .envrc")

AGENT_STORAGE_FILE = "tmp/whatsapp_agents.db"


def get_whatsapp_agent() -> Agent:
"""Returns an instance of the WhatsApp Agent.

Returns:
Agent: The configured WhatsApp agent instance.
"""
# Initialize WhatsApp tools
whatsapp = WhatsAppTools()

# Create and return the agent
return Agent(
name="WhatsApp Assistant",
model=OpenAIChat(id="gpt-4o"),
tools=[
whatsapp,
YFinanceTools(
stock_price=True,
analyst_recommendations=True,
stock_fundamentals=True,
historical_prices=True,
company_info=True,
company_news=True,
),
],
storage=SqliteAgentStorage(
table_name="whatsapp_agent", db_file=AGENT_STORAGE_FILE
),
add_history_to_messages=True,
num_history_responses=3,
markdown=True,
description="You are a financial advisor and can help with stock-related queries. You will respond like how people talk to each other on whatsapp, with short sentences and simple language. don't add markdown to your responses.",
)
81 changes: 81 additions & 0 deletions cookbook/examples/apps/whatsapp_chat_agent/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import logging

from agents import VERIFY_TOKEN, get_whatsapp_agent
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import PlainTextResponse

# Configure logging
logger = logging.getLogger(__name__)

# Initialize agent
agent = get_whatsapp_agent()

# Create FastAPI app
app = FastAPI()


@app.get("/webhook")
async def verify_webhook(request: Request):
"""Handle WhatsApp webhook verification"""
mode = request.query_params.get("hub.mode")
token = request.query_params.get("hub.verify_token")
challenge = request.query_params.get("hub.challenge")

if mode == "subscribe" and token == VERIFY_TOKEN:
if not challenge:
raise HTTPException(status_code=400, detail="No challenge received")
return PlainTextResponse(content=challenge)

raise HTTPException(status_code=403, detail="Invalid verify token or mode")


@app.post("/webhook")
async def handle_message(request: Request):
"""Handle incoming WhatsApp messages"""
try:
body = await request.json()

# Validate webhook data
if body.get("object") != "whatsapp_business_account":
logger.warning(
f"Received non-WhatsApp webhook object: {body.get('object')}"
)
return {"status": "ignored"}

# Process messages
for entry in body.get("entry", []):
for change in entry.get("changes", []):
messages = change.get("value", {}).get("messages", [])

if not messages:
continue

message = messages[0]
if message.get("type") != "text":
continue

# Extract message details
phone_number = message["from"]
message_text = message["text"]["body"]

logger.info(f"Processing message from {phone_number}: {message_text}")

# Generate and send response
response = agent.run(message_text)
agent.tools[0].send_text_message_sync(
recipient=phone_number, text=response.content
)
logger.info(f"Response sent to {phone_number}")

return {"status": "ok"}

except Exception as e:
logger.error(f"Error processing webhook: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))


if __name__ == "__main__":
import uvicorn

logger.info("Starting WhatsApp Bot Server")
uvicorn.run(app, host="0.0.0.0", port=8000)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

############################################################################
# Generate requirements.txt from requirements.in
############################################################################

echo "Generating requirements.txt"

CURR_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

UV_CUSTOM_COMPILE_COMMAND="./generate_requirements.sh" \
uv pip compile ${CURR_DIR}/requirements.in --no-cache --upgrade -o ${CURR_DIR}/requirements.txt
97 changes: 97 additions & 0 deletions cookbook/examples/apps/whatsapp_chat_agent/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# WhatsApp Chat Agent with Stock Market Insights

This is a WhatsApp chatbot that provides stock market insights and financial advice using the WhatsApp Business API. The bot is built using FastAPI and can be run locally using ngrok for development and testing.

## Prerequisites

- Python 3.7+
- ngrok account (free tier works fine)
- WhatsApp Business API access
- Meta Developer account
- OpenAI API key

## Setup Instructions

1. **Install Dependencies**

```bash
pip install -r requirements.txt
```

2. **Set up ngrok (for development testing only)**

- Download and install ngrok from https://ngrok.com/download
- Sign up for a free account and get your auth-token
- Authenticate ngrok with your token:
```bash
ngrok config add-authtoken YOUR_AUTH_TOKEN
```

3. **Create a Meta Developer Account**

- Go to https://developers.facebook.com/
- Create a new app
- Set up WhatsApp in your app
- Get your WhatsApp Business Account ID and Phone Number ID

4. **Environment Variables**
Create a `.envrc` file in the project root with the following variables:

```bash
export WHATSAPP_ACCESS_TOKEN=your_whatsapp_access_token
export WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id
export WHATSAPP_RECIPIENT_WAID=phone_number_with_country_code # e.g. +1234567890
export WHATSAPP_WEBHOOK_URL=your_webhook_url
export WHATSAPP_VERIFY_TOKEN=your_custom_verify_token # Can be any string you choose
export WHATSAPP_WEBHOOK_URL=your_webhook_url
export OPENAI_API_KEY=your_openai_api_key
```

## Running the Application

1. **Start the FastAPI server**

```bash
python app.py
```

2. **Start ngrok**
In a new terminal window:

```bash
ngrok http 8000
```

3. **Configure Webhook**
- Copy the HTTPS URL provided by ngrok (e.g., https://xxxx-xx-xx-xxx-xx.ngrok.io)
- Go to your Meta Developer Portal
- Set up Webhooks for your WhatsApp Business Account
- Use the ngrok URL + "/webhook" as your Callback URL
- Use your WHATSAPP_VERIFY_TOKEN as the Verify Token
- Subscribe to the `messages` webhook

## Testing the Bot

1. Send a message to your WhatsApp Business number
2. The bot should respond with stock market insights based on your query
3. You can ask questions about:
- Stock prices
- Company information
- Analyst recommendations
- Stock fundamentals
- Historical prices
- Company news

## Troubleshooting

- Make sure all environment variables are properly set
- Check the FastAPI logs for any errors
- Verify that ngrok is running and the webhook URL is correctly configured
- Ensure your WhatsApp Business API is properly set up and the phone number is verified

## Important Notes

- The ngrok URL changes every time you restart ngrok, You can also use a static ngrok URL by running `ngrok http 8000 --domain=your-custom-domain.com`, you can get a custom domain from [here](https://dashboard.ngrok.com/domains)
- You'll need to update the Webhook URL in the Meta Developer Portal whenever the ngrok URL changes
- Keep your WHATSAPP_ACCESS_TOKEN and other credentials secure
- The bot stores conversation history in a SQLite database in the `tmp` directory
10 changes: 10 additions & 0 deletions cookbook/examples/apps/whatsapp_chat_agent/requirements.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fastapi
uvicorn
python-dotenv
requests
yfinance
openai
agno
python-multipart
aiohttp
SQLAlchemy
Loading