creamy-window-79763
12/17/2025, 3:35 PMtall-airline-16756
12/17/2025, 3:35 PMtall-airline-16756
12/17/2025, 3:35 PMcreamy-window-79763
12/17/2025, 3:49 PMtall-airline-16756
12/17/2025, 3:49 PMpublish_data.
• Twilio configured to POST incoming WhatsApp messages to your webhook.
• Your existing Agent class can accept text input and return a text reply.
1) Webhook handler — receive Twilio WhatsApp message and publish to LiveKit room
from flask import Flask, request, jsonify
from twilio.rest import Client as TwilioClient
from livekit import Client as LiveKitClient # server SDK client
import os
app = Flask(__name__)
# env/config
TWILIO_SID = os.environ['TWILIO_SID']
TWILIO_TOKEN = os.environ['TWILIO_TOKEN']
TWILIO_WHATSAPP_NUMBER = 'whatsapp:+1234567890'
LIVEKIT_URL = os.environ['LIVEKIT_URL']
LIVEKIT_API_KEY = os.environ['LIVEKIT_API_KEY']
LIVEKIT_API_SECRET = os.environ['LIVEKIT_API_SECRET']
ROOM_NAME = 'whatsapp_room'
TOPIC = 'whatsapp_messages'
twilio = TwilioClient(TWILIO_SID, TWILIO_TOKEN)
lk = LiveKitClient(url=LIVEKIT_URL, api_key=LIVEKIT_API_KEY, api_secret=LIVEKIT_API_SECRET)
@app.route('/twilio-webhook', methods=['POST'])
def twilio_webhook():
sender = request.form.get('From') # e.g. 'whatsapp:+1425...'
body = request.form.get('Body', '')
if not body:
return ('', 200)
# Format message payload you want visible in the LiveKit room
payload = f"{sender}: {body}"
# Publish to LiveKit room via server API (data channel). Use topic to filter.
lk.room_publish_data(room=ROOM_NAME, data=payload.encode('utf-8'), topic=TOPIC, reliable=True)
return ('', 200)
Notes:
• Replace LiveKitClient call with the server SDK method your environment uses. The important action is publish_data to the room with a topic (here whatsapp_messages).
2) Agent integration — listen to LiveKit room data messages and respond
# Example Agent wrapper that registers a data callback on the LiveKit room
# This assumes you have a running process connected to the LiveKit room as a participant
# and have access to the room object with data callbacks.
class LiveKitWhatsAppBridge:
def __init__(self, room, agent, twilio_client):
self.room = room # livekit room object for the agent participant
self.agent = agent # your existing Agent instance with `generate_reply(text)`
self.twilio = twilio_client
# Register callback for messages published on TOPIC
self.room.register_data_callback(self.on_data_message, topic=TOPIC)
async def on_data_message(self, data_packet):
# data_packet.data is bytes; decode
text = data_packet.data.decode('utf-8')
# Expect format: "whatsapp:+1425...: message" or "whatsapp:+1425...: message"
# Extract sender if you included it in payload
if ':' in text:
sender, user_text = text.split(':', 1)
user_text = user_text.strip()
else:
sender = None
user_text = text
# Avoid processing messages sent by this agent participant
if data_packet.participant and data_packet.participant.identity == self.room.local_participant.identity:
return
# Get reply from your Agent (synchronous or async)
response = await self.agent.generate_reply(user_text) if callable(getattr(self.agent, 'generate_reply', None)) else self.agent.generate_reply(user_text)
# Publish reply into LiveKit room so other participants (and UI) see it
await self.room.local_participant.publish_data(response.encode('utf-8'), topic=TOPIC, reliability=True)
# Also send reply back to WhatsApp via Twilio if we have sender
if sender:
self.send_whatsapp(sender, response)
def send_whatsapp(self, to_whatsapp_number, body):
# Twilio expects 'whatsapp:+number' format
self.twilio.messages.create(from_=TWILIO_WHATSAPP_NUMBER, to=to_whatsapp_number, body=body)
3) Architecture summary
• Twilio webhook receives incoming WhatsApp messages and calls /twilio-webhook.
• Webhook publishes the message into the LiveKit room on topic whatsapp_messages.
• Your LiveKit-connected Agent (as a room participant) receives the data packet via register_data_callback, generates a reply, and publishes it back to the room.
• Bridge sends the agent reply back to the original WhatsApp sender via Twilio SMS API.
Would you like:
• A version tailored to your Agent class signature (share the method name and sync vs async), or
• A minimal runnable example showing the LiveKit server SDK method names you use (I can adapt the lk.room_publish_data call to your SDK)? Sources: Data packets | LiveKit docs | Agents telephony integration | LiveKit docs | Call forwarding | LiveKit docsadamant-bear-80166
12/17/2025, 3:54 PMtall-airline-16756
12/17/2025, 3:55 PMadamant-bear-80166
12/17/2025, 3:55 PMtall-airline-16756
12/17/2025, 3:55 PMadamant-bear-80166
12/17/2025, 3:56 PM