Skip to content

In-Call Sequence

What happens during a single Vapi call, turn by turn — and where each piece of state lives. Use this to point to where a bug must be when behavior is wrong.

The loop, end-to-end

Where each piece of state actually lives

Piece of stateWhere it livesHow to inspect
System promptVapi assistant config (Vapi dashboard)Vapi dashboard → Assistants → click the EAS assistant → "Model" tab → "System Prompt"
Tool definitions (names, schemas, descriptions)Vapi assistant configSame place → "Tools" tab. Each tool has a name, description, JSON schema for arguments.
Tool URL (where Vapi POSTs each tool dispatch)Per-tool server.url inside the squad payload (priority 1 in Vapi's resolution stack — see vapi-squads.md). Built at agent-build time by FunctionTool.getVapiOpenAIModelTool via buildUrl(this.path), which reads process.env.NGROK_BASE_URL (defaults to https://app.avoca.ai).Vapi dashboard → squad detail → expand a sub-agent → each function tool's "Server URL" field. For FDE local dev, set NGROK_BASE_URL=<tunnel> then re-run test-phone-sync.
Tool handler (the code that runs)Avoca's repoapps/web/lib/vapi/tools/handlers/${toolName}.ts
Tool router (which handler fires for which tool name)Avoca's repoapps/web/pages/api/vapi/tools/dispatch.ts (or similar entry point)
Conversation historyVapi runtime — exists for the duration of the call onlyVapi dashboard → Calls → click a call → "Transcript" tab shows the full turn-by-turn
Audio recordingVapi (also forwarded to Avoca for storage)Vapi dashboard call view; Avoca's recording_url on the calls row
Caller-id phone numberVapi → forwards in webhook contextctx.message.customer?.number in any tool handler

"Here's a bug, where do I look?"

SymptomMost likely location
Agent uses the wrong opening lineSystem prompt (Vapi assistant config)
Agent doesn't call a tool when it shouldTool description / system prompt instructions about when to call the tool
Agent calls a tool with wrong argumentsTool's JSON schema (arg shape) or system prompt's example/instruction for that tool
Tool call returns an errorTool handler in Avoca's code (apps/web/lib/vapi/tools/handlers/${toolName}.ts)
Agent ignores tool's responseSystem prompt's instructions about how to use the result, OR tool result shape is too unstructured for the LLM to summarize
Agent hallucinates instead of using the tool resultTool result's JSON is too noisy / the LLM is "explaining" instead of acting; tighten the tool's response shape AND add a prompt-level "always quote the X field" instruction
Agent loops calling the same tool repeatedlyTool handler returned a result that doesn't satisfy the LLM's stop condition; OR system prompt is missing a "you've already done this, move on" guard
Tool fires but Avoca records nothingTool handler's persistence layer (Supabase write); or the tool returned synchronously but the side-effect was async without a guarantee
Agent says "let me look that up" then never references the resultEither the tool didn't actually fire (check Vapi transcript "tool calls" tab) or the prompt isn't telling the LLM how to use the response
Caller-id phone is wrong / missingVapi-side; sometimes customer.number is empty for inbound calls without caller ID. Defensive code in handlers.
Post-call workflow doesn't runAvoca didn't receive /api/vapi/end-of-call-report, OR Inngest didn't pick up the event. Check Datadog for the webhook hit and Inngest dashboard for the run.
Post-call workflow ran but did nothingInngest run's step graph — extraction may have classified callReason differently than expected.

How to "watch a call live"

In order of usefulness:

  1. Vapi dashboard, the call's page — refreshes the transcript in near-real-time. Each LLM turn shows up; each tool call shows up with its arguments + result expandable. This is the closest thing to a debugger for in-call behavior.
  2. Datadog logs filtered by service:avoca-next-prod — every /api/vapi/tools/dispatch POST shows up here as the call progresses. Filter further on @callId once you have it (Vapi puts the call id in the request body).
  3. Tail the Avoca prod logs via Datadog MCP — once the MCP tool is wired (post-restart), you can ask in-session "show me recent /api/vapi/tools/dispatch hits in the last 5 minutes" and see them stream.
  4. Inngest dashboard (production) — only relevant after the call ends. The workflow run appears within seconds of the end-of-call webhook hitting.

Pointers

  • The dispatch entry point in Avoca: search apps/web/pages/api/vapi/tools/ (Pages router) or apps/web/app/api/vapi/tools/ (App router) — Avoca has both.
  • Tool handlers all live under apps/web/lib/vapi/tools/handlers/.
  • The post-call entry point: apps/web/app/api/vapi/end-of-call-report/ (and its Inngest registration in apps/web/lib/workflow/post-call/end-of-call-report.ts).
  • Available tool catalog (the source of truth for tool name strings): apps/web/lib/voice-assistants/available-tools.ts.
  • Per-tool URL builder: apps/web/lib/voice-assistants/utils.tsbuildUrl(path) reads NGROK_BASE_URL and is what every FunctionTool calls when constructing its server.url.

Open in a new tab while debugging

  • Vapi dashboard → the assistant being called → System Prompt tab
  • Vapi dashboard → Calls → the live call (refresh)
  • Datadog → service:avoca-next-prod, last 30 min, refresh
  • Inngest → production env → Functions → EndOfCallReportInngestFunction (after call ends)