You have a Vapi assistant. It is a hosted voice pipeline with a system prompt and model choices. It has a server URL that receives call events and function calls, and a phone-call API. Every piece has a direct counterpart on ClutchCall. Unlike the code-first integrations (LiveKit, Pipecat), most of this port is configuration, not code. The only component that you continue to run is the server that backs your webhooks and tools. Your Vapi setup can instead pipe raw audio to your own model (a custom transcriber/voice over WebSocket). In that case, use the external agent seam. Your process holds one outbound QUIC/WebTransport session. It authenticates with a media key/secret from the console’s External-agent create flow. It receives each call’s 8 kHz pcm16 audio directly. The external-agent recipe covers that path end to end.

What maps to what

Port the assistant

The runnable starter is a port of Vapi’s server-example (Flask). It contains the webhook route, the two custom functions, and a provisioning script. It ships in the provider starters repo next to the telequick-agents SDK.
1

Recreate the assistant as a voice agent

In the console (agent.clutchcall.dev), create a voice agent. Copy over the assistant’s system prompt and STT/LLM/TTS choices. Provider keys are per-tenant. The control plane seals them at rest and resolves them at call setup. See BYO ASR / LLM / TTS for the provider matrix.
2

Register your server URL as a webhook

Management operations use an mpk_ API key (console → Settings → API keys) against POST /mcp. The SDK wraps the endpoint:
provision.py
The API returns the signing secret (whsec_…) only one time, on creation.
3

Verify deliveries where Vapi sent messages

Deliveries are signed Stripe-style. X-Clutchcall-Signature carries t=<epoch>,v1=<hmac_sha256(secret, "t.body")>. Your route changes from “switch on message.type” to “verify, then switch on the event header”:
webhook.py
4

Turn custom functions into agent tools

Vapi POSTs function-call messages to your server URL. Here, each function is an HTTP agent tool attached to the agent. The runtime’s LLM calls the tool mid-call. The platform POSTs the arguments to your route. The agent speaks the returned result:
Your Flask/Express handlers for the functions do not change. Only the registration moves. See Tool Calling for the full spec.
5

Replace the phone-call API

Vapi’s POST /call with an assistantId becomes one operation with an agent name. On answer, the engine connects the callee to that agent:

Troubleshooting

Check the signature against the exact raw request body. A re-parsed and re-serialized JSON body computes a different HMAC. Also check clock skew: verify_signature enforces a freshness window on the t= timestamp.
The tool’s description and parameter schema drive tool selection, exactly as with Vapi’s function definitions. Check that the tool upserted onto the correct agentId. Check that your endpoint returns quickly. A slow tool stalls the turn.
That is the external-agent seam, not a console agent. Your worker registers under an agent handle. The engine routes calls through VENDOR_BRIDGE. You read 20 ms pcm16 frames in-process. Start from the external-agent recipe.

LiveKit integration

The external-agent seam in depth, for code-first runtimes.

Tool Calling

HTTP agent tools: schemas, silent tools, and mid-call behavior.

SIP Trunking

Bring the numbers that your Vapi assistant answers today.

Run a LiveKit Agent on the Transport

The end-to-end external-agent recipe.