-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
base: main
Are you sure you want to change the base?
Whatsapp integration #2335
Changes from all commits
b159dce
023fb59
c56527b
f385eee
6840a53
9844b3b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,94 @@ | ||||||
# 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** | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe explain why ngrok is needed here? I know, but for users. |
||||||
|
||||||
- Download and install ngrok from https://ngrok.com/download | ||||||
- Sign up for a free account and get your authtoken | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
- 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 `.env` file in the project root with the following variables: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We generally prefer a |
||||||
|
||||||
```env | ||||||
WHATSAPP_ACCESS_TOKEN=your_whatsapp_access_token | ||||||
WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id | ||||||
WHATSAPP_VERIFY_TOKEN=your_custom_verify_token # Can be any string you choose | ||||||
OPENAI_API_KEY=your_openai_api_key | ||||||
``` | ||||||
|
||||||
## Running the Application | ||||||
|
||||||
1. **Start the FastAPI server** | ||||||
|
||||||
```bash | ||||||
python whatsapp_chat_agent.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 (unless you have a paid account) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could create a static URL without paying? But that was a while ago There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, you can. this is cursor written, i will change it soon. |
||||||
- 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 |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,10 @@ | ||||||
fastapi>=0.68.0 | ||||||
uvicorn>=0.15.0 | ||||||
python-dotenv>=0.19.0 | ||||||
requests>=2.26.0 | ||||||
yfinance>=0.1.63 | ||||||
openai>=1.0.0 | ||||||
agno>=0.1.0 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would actually have to be 1.1.10 after we release this, so the agent would have the right tools. Maybe don't specify a version, then it would be latest. |
||||||
python-multipart>=0.0.5 | ||||||
aiohttp>=3.8.0 | ||||||
SQLAlchemy>=1.4.0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
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 | ||
from fastapi import FastAPI, HTTPException, Request | ||
from fastapi.responses import PlainTextResponse | ||
|
||
# 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" | ||
|
||
# Initialize WhatsApp tools and agent | ||
whatsapp = WhatsAppTools() | ||
agent = 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.", | ||
) | ||
|
||
# Create FastAPI app | ||
app = FastAPI() | ||
|
||
|
||
@app.get("/webhook") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would define the app and the endpoints in another file. Like with other apps we have an |
||
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") | ||
|
||
logger.info(f"Webhook verification request - Mode: {mode}, Token: {token}") | ||
|
||
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) | ||
whatsapp.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") | ||
logger.info(f"Webhook URL: {WEBHOOK_URL}") | ||
logger.info(f"Verify Token: {VERIFY_TOKEN}") | ||
logger.info( | ||
"Make sure your .env file contains WHATSAPP_ACCESS_TOKEN and WHATSAPP_PHONE_NUMBER_ID" | ||
) | ||
Comment on lines
+126
to
+128
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wouldn't put this here again |
||
|
||
uvicorn.run(app, host="0.0.0.0", port=8000) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
""" | ||
WhatsApp Cookbook | ||
---------------- | ||
|
||
This cookbook demonstrates how to use WhatsApp integration with Agno. Before running this example, | ||
you'll need to complete these setup steps: | ||
|
||
1. Create Meta Developer Account | ||
- Go to Meta Developer Portal (https://developers.facebook.com/) and create a new account | ||
- Create a new app at Meta Apps Dashboard (https://developers.facebook.com/apps/) | ||
- Enable WhatsApp integration for your app (https://developers.facebook.com/docs/whatsapp/cloud-api/get-started) | ||
|
||
2. Set Up WhatsApp Business API | ||
- Get your WhatsApp Business Account ID from Business Settings (https://business.facebook.com/settings/) | ||
- Generate a permanent access token in System Users (https://business.facebook.com/settings/system-users) | ||
- Set up a test phone number (https://developers.facebook.com/docs/whatsapp/cloud-api/get-started#testing-your-app) | ||
- Create a message template in Meta Business Manager (https://business.facebook.com/wa/manage/message-templates/) | ||
|
||
3. Configure Environment | ||
- Set these environment variables: | ||
WHATSAPP_ACCESS_TOKEN=your_access_token # Permanent access token from System Users | ||
WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id # Your WhatsApp test phone number ID | ||
|
||
Important Notes: | ||
- WhatsApp has a 24-hour messaging window policy | ||
- You can only send free-form messages to users who have messaged you in the last 24 hours | ||
- For first-time outreach, you must use pre-approved message templates | ||
(https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-message-templates) | ||
- Test messages can only be sent to numbers that are registered in your test environment | ||
|
||
The example below shows how to send a template message using Agno's WhatsApp tools. | ||
For more complex use cases, check out the WhatsApp Cloud API documentation: | ||
https://developers.facebook.com/docs/whatsapp/cloud-api/overview | ||
""" | ||
|
||
from agno.agent import Agent | ||
from agno.tools.whatsapp import WhatsAppTools | ||
|
||
agent = Agent( | ||
name="whatsapp", | ||
tools=[WhatsAppTools()], | ||
) | ||
|
||
# Example: Send a template message | ||
# Note: Replace 'hello_world' with your actual template name | ||
agent.print_response( | ||
"Send a template message using the 'hello_world' template in English" | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add the requirements.in and the generate_requirements script like we have with other apps