Skip to content
AI Voice Agents
AI Voice Agents10 min read0 views

Build a Voice Agent with VAPI Functions and Custom Tools (2026)

VAPI deprecated 'Custom Functions' for the Tools API. Wire a webhook tool, secure with HMAC, and ship a working appointment-booker — code + pitfalls.

TL;DR — VAPI's "Custom Functions" feature was deprecated in 2026 in favor of the Tools API. Tools are reusable across assistants, support async webhooks, and have a clean HMAC-signed contract. This is the only correct way to extend a VAPI agent today.

What you'll build

A VAPI assistant that calls a book_appointment tool against your Next.js webhook, validates the HMAC signature, books the slot in Postgres, and returns a confirmation the assistant speaks aloud.

Architecture

flowchart LR
  CL[Caller] --> VP[VAPI assistant]
  VP -- function_call --> TL[Tool: book_appointment]
  TL -- HMAC POST --> WH[Your /api/vapi/book webhook]
  WH -- result JSON --> VP --> CL

Step 1 — Create the tool in dashboard

In dash.vapi.ai → Tools → Create. Pick Custom Tool and fill:

  • Name: book_appointment
  • Server URL: https://yourhost.com/api/vapi/book
  • Description: "Book a slot once the user confirms an ISO-8601 date+time."
  • Parameters JSON:

```json { "type": "object", "properties": { "iso": { "type": "string", "description": "ISO-8601 datetime" }, "name": { "type": "string" } }, "required": ["iso", "name"] } ```

Hear it before you finish reading

Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.

Try Live Demo →

Step 2 — Attach to assistant

In Assistants → Edit → Tools, toggle book_appointment on. The system prompt should mention "Use book_appointment once the caller confirms."

Step 3 — Webhook handler (Next.js)

```ts // app/api/vapi/book/route.ts import crypto from "crypto"; import { db } from "@/lib/db";

export async function POST(req: Request) { const raw = await req.text(); const sig = req.headers.get("x-vapi-signature") ?? ""; const expected = crypto.createHmac("sha256", process.env.VAPI_WEBHOOK_SECRET!) .update(raw).digest("hex"); if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) { return new Response("bad sig", { status: 401 }); } const body = JSON.parse(raw); const call = body.message.toolCallList[0]; const { iso, name } = call.function.arguments; await db.appt.create({ data: { iso, name } }); return Response.json({ results: [{ toolCallId: call.id, result: Booked ${name} for ${iso}., }], }); } ```

Step 4 — Programmatic create

```ts const r = await fetch("https://api.vapi.ai/assistant", { method: "POST", headers: { Authorization: Bearer ${process.env.VAPI_API_KEY}, "Content-Type": "application/json" }, body: JSON.stringify({ name: "Clinic Concierge", model: { provider: "openai", model: "gpt-4o", toolIds: ["tool_book_appointment"] }, voice: { provider: "11labs", voiceId: "rachel" }, transcriber: { provider: "deepgram", model: "nova-3" }, firstMessage: "Hi — Sunrise Clinic, how can I help?", }), }); ```

Step 5 — Async tools

For long-running work (>5s), set async: true on the tool. VAPI keeps the user engaged with a fill phrase ("One sec while I check that...") and waits up to 60s for your webhook to POST a result back via the /call/:id/control endpoint.

Step 6 — Test with the simulator

vapi-cli simulate --assistant <id> --transcript 'I want 3pm tomorrow' exercises the tool path without spending phone minutes.

Still reading? Stop comparing — try CallSphere live.

CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.

Pitfalls

  • toolCallId mismatch: Your response results[].toolCallId MUST match the request call.id — otherwise VAPI ignores the result.
  • HMAC vs server JWT: Some old docs reference Bearer tokens — Tools use HMAC by default in 2026.
  • Idempotency: VAPI retries on 5xx — return 200 even on duplicate, with the same result body.
  • Tool description quality: One job per tool, plain-English description; the LLM picks tools by description, not name.

How CallSphere does this

CallSphere ships 37 agents · 90+ tools · 115+ DB tables · 6 verticals, including a VAPI tier for low-volume franchise customers. $149/$499/$1,499 · 14-day trial · 22% affiliate.

FAQ

Default vs custom tools? VAPI ships defaults like endCall, transferCall, dtmf — use them for control flow and reserve custom tools for business logic.

Latency? Tool execution adds your webhook RTT; keep p95 under 800ms or VAPI fills with a "still checking" line.

Streaming responses? Tools are request/response only — for streaming use a Custom LLM URL instead (separate feature).

Multi-step workflows? Use VAPI Workflows (visual graph) or chain tool calls in your prompt.

Sources

Share

Try CallSphere AI Voice Agents

See how AI voice agents work for your industry. Live demo available -- no signup required.

Related Articles You May Like