基于LangChain、FastAPI与Meta Webhooks的WhatsApp机器人重复POST请求问题
WhatsApp聊天机器人重复触发Meta Webhook请求问题
我用LangChain、FastAPI和Meta Webhooks做了个WhatsApp聊天机器人,现在碰到个棘手的问题——用户发一条消息,AgentExecutor链会多次触发Meta Webhooks的200 OK POST请求。
下面是我的Webhook处理代码:
@router.post("/webhook") async def webhook_events(request: Request): payload = await request.json() # print(json.dumps(payload, indent=4)) message = "" # print(payload) if "contacts" in payload["entry"][0]["changes"][0]["value"]: user_name = payload["entry"][0]["changes"][0]["value"]["contacts"][0]["profile"]["name"] wa_id = payload["entry"][0]["changes"][0]["value"]["contacts"][0]["wa_id"] user_id = user_name.split(" ")[0] + "@" + wa_id if "messages" in payload["entry"][0]["changes"][0]["value"]: reciepient = payload["entry"][0]["changes"][0]["value"]["messages"][0]["from"] chat_history = RedisChatMessageHistory(user_id) memory = ConversationBufferMemory( chat_memory=chat_history, memory_key="chat_history", return_messages=True) if not chat_history.messages: chat_history.add_ai_message("Hi! What's your name? I'm MobSecBot, designed to help you with your mobile and security questions.") chat_history.add_user_message(f"Hi! My name is {user_name}.") expire_chat_history(r, f'message_store:{user_id}') agent_chain = agent_handler.init_chain(agent, memory) # agent_chain = initialize_agent( # tools, # llm, # agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, # memory=memory, # handle_parsing_errors="Check your output and make sure it conforms!") if "text" in payload["entry"][0]["changes"][0]["value"]["messages"][0]: message = payload["entry"][0]["changes"][0]["value"]["messages"][0]["text"]["body"] print(f"{reciepient}: {message}") try: response = agent_chain.run(message) except Exception as e: response = str(e) # response = response.removeprefix("Could not parse LLM output: `").removesuffix("`") print(f"MobSecBot: {response}") else: response = "Sorry! I can only respond to text messages for now." await messenger.send_message(response, reciepient)
参考图片:两张请求日志截图,显示了多次重复的200 OK POST请求记录。
问题排查和解决思路
1. Meta Webhook重试触发(最可能原因)
Meta的Webhook有重试机制:如果接口超过几秒没返回200,它会重复发送请求。你的代码里agent_chain.run(message)是同步阻塞调用,LLM调用、工具调用都很耗时,导致FastAPI没法快速给Meta回200,直接触发了重试,所以会出现多次请求记录。
解决办法:
用FastAPI的BackgroundTasks把Agent处理和消息发送逻辑放到后台,让接口先立刻返回200给Meta,避免重试:
from fastapi import BackgroundTasks @router.post("/webhook") async def webhook_events(request: Request, background_tasks: BackgroundTasks): payload = await request.json() message = "" user_id = None reciepient = None response = "" user_name = "" # 先快速解析所有必要参数,不做耗时操作 if "contacts" in payload["entry"][0]["changes"][0]["value"]: user_name = payload["entry"][0]["changes"][0]["value"]["contacts"][0]["profile"]["name"] wa_id = payload["entry"][0]["changes"][0]["value"]["contacts"][0]["wa_id"] user_id = user_name.split(" ")[0] + "@" + wa_id if "messages" in payload["entry"][0]["changes"][0]["value"]: reciepient = payload["entry"][0]["changes"][0]["value"]["messages"][0]["from"] if "text" in payload["entry"][0]["changes"][0]["value"]["messages"][0]: message = payload["entry"][0]["changes"][0]["value"]["messages"][0]["text"]["body"] else: response = "Sorry! I can only respond to text messages for now." # 把耗时的Agent处理和消息发送丢到后台任务 async def process_and_send(): nonlocal response, user_id, reciepient, message, user_name if message and user_id: chat_history = RedisChatMessageHistory(user_id) memory = ConversationBufferMemory( chat_memory=chat_history, memory_key="chat_history", return_messages=True) if not chat_history.messages: chat_history.add_ai_message("Hi! What's your name? I'm MobSecBot, designed to help you with your mobile and security questions.") chat_history.add_user_message(f"Hi! My name is {user_name}.") expire_chat_history(r, f'message_store:{user_id}') agent_chain = agent_handler.init_chain(agent, memory) try: response = agent_chain.run(message) except Exception as e: response = str(e) print(f"{reciepient}: {message}") print(f"MobSecBot: {response}") if reciepient: await messenger.send_message(response, reciepient) if reciepient: background_tasks.add_task(process_and_send) # 立刻返回200,告诉Meta我收到了 return {"status": "ok"}
2. Agent内部重复调用
检查你的agent_handler.init_chain配置的Agent,有没有设置成多次调用工具,或者工具内部逻辑触发了Webhook相关请求,导致循环触发。
解决办法:
- 开启LangChain的DEBUG日志,打印Agent的思考和调用步骤,看是否有重复执行的环节。
- 检查
messenger.send_message方法,确认它不会触发Meta的Webhook回调,避免循环请求。
3. Redis聊天历史异常
如果Redis里的聊天历史有重复消息,可能导致Agent重复处理,间接引发多次请求。
解决办法:
- 给初始消息添加判断逻辑,避免重复写入(比如检查历史里有没有初始问候再添加)。
- 确认
expire_chat_history方法正确设置了过期时间,避免残留的历史消息干扰。
内容的提问来源于stack exchange,提问作者Kushagra Punia
相关产品推荐
相关产品推荐

