Webhook & CRM Engine Hooks
Explore the Implementation
Clone RepositoryView on GitHub
Bash
git clone https://github.com/vobiz-ai/Livekit-Vobiz-Webhook-Integration-Example.git
cd Livekit-Vobiz-Webhook-Integration-ExampleAn advanced implementation pattern demonstrating how to deeply intertwine external CRM systems and webhook endpoints throughout a LiveKit agent's lifecycle. It maintains an active CallRecord state loaded via HTTP calls before the VoIP session even connects, and utilizes non-blocking aiohttp requests inside the LLM's function tools to continuously stream metadata (like intent capturing and note-taking) back to your servers securely via HMAC SHA-256 signed payloads.
How It Works
The architecture is separated into three distinct lifecycles: PRE-CALL, IN-CALL, and POST-CALL.
- State Resolution (Pre-Call): Before LiveKit bridges the SIP target, the entrypoint halts and performs an HTTP GET to
/contacts/search. The retrieved entity (name, company, open tickets) is injected directly into an isolateddataclass CallRecordwhich is then mounted onto the LiveKit session viaAgentSession(userdata=record). This ensures theAgentinherently knows who it is dialing. - Event Streaming (In-Call): Webhook triggers like
call.startedare immediately dispatched asynchronously. The agent is strictly provisioned with exactly four contextual function tools:record_intent,lookup_crm,update_crm_note, andtransfer_call. Executing any tool instantly resolves an external HTTP POST to the backend without blocking the active audio pipeline stream. - Security & Signatures: Every outbound payload dispatched by the agent contains a calculated
hmac.new(SHA256)signature validated against the request body using a configuredWEBHOOK_SECRET, proving the payload securely originated from the LiveKit engine. - Teardown (Post-Call): A hard lifecycle hook
@ctx.room.on("disconnected")intercepts session closures, compiling the total durational interaction, the finalized Intent array, and the SIP routing destination, resolving a final mastercall.endedburst back to the CRM API.
Implementation Code
Here is a representative LiveKit Python snippet illustrating how the CRM webhook synchronization binds seamlessly directly out of the LLM's active function toolset loop mid-call:
Python
import aiohttp
from livekit.agents import llm
async def fetch_crm_data(phone_number: str):
"""Fired BEFORE creating the LiveKit room to prime the Agent Prompt"""
async with aiohttp.ClientSession() as session:
async with session.get(f"https://api.crm.com/v1/contacts?phone={phone_number}") as resp:
data = await resp.json()
return data.get("name"), data.get("open_tickets", 0)
class CRMTools(llm.ToolContext):
def __init__(self, contact_id: str):
super().__init__()
self.contact_id = contact_id
@llm.function_tool(description="Log a custom intent note to the CRM mid-call")
async def log_intent(self, user_intent: str):
"""Asynchronous Webhook HTTP POST executed natively during audio streaming"""
async with aiohttp.ClientSession() as session:
await session.post(
f"https://api.crm.com/v1/contacts/{self.contact_id}/notes",
json={"summary": user_intent}
)
return "Note attached successfully."