Skip to content
Examples Gallery/Webhook & CRM API Hooks

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-Example

An 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 isolated dataclass CallRecord which is then mounted onto the LiveKit session via AgentSession(userdata=record). This ensures the Agent inherently knows who it is dialing.
  • Event Streaming (In-Call): Webhook triggers like call.started are immediately dispatched asynchronously. The agent is strictly provisioned with exactly four contextual function tools: record_intent, lookup_crm, update_crm_note, and transfer_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 configured WEBHOOK_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 master call.ended burst 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."