Skip to content

Commit 1420a05

Browse files
committed
docs: add transfer troubleshooting runbook to learnings
Add transfers.md diagnostic guide covering: LLM not emitting tool calls, tool description reluctance, transferCall vs handoff selection, telephony failures (SIP REFER), and transient assistant foot-guns. Add two new config gotchas to tools.md (missing description, sipVerb refer). Update README with troubleshooting section.
1 parent 0a621e4 commit 1420a05

3 files changed

Lines changed: 159 additions & 1 deletion

File tree

docs/learnings/README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Non-obvious behaviors, silent defaults, and foot-guns in the Vapi platform that
44

55
Each file in this directory covers a specific resource type so you can load only the context you need:
66

7+
### Configuration Reference
8+
9+
These files cover non-obvious defaults and behaviors for each resource type:
10+
711
| File | What it covers |
812
|------|----------------|
913
| [tools.md](tools.md) | apiRequest, function, transferCall, endCall, handoff, code tools; tool messages; strict mode |
@@ -13,4 +17,12 @@ Each file in this directory covers a specific resource type so you can load only
1317
| [simulations.md](simulations.md) | Personalities, evaluation comparators, chat-mode gotcha, missing references |
1418
| [webhooks.md](webhooks.md) | Default server messages, timeouts, unreachable servers, credential resolution, payload shape |
1519

16-
**When to read these:** Before creating or modifying any resource file in `resources/<env>/`. These gotchas document behavior that the API reference and dashboard don't make obvious.
20+
### Troubleshooting Runbooks
21+
22+
Step-by-step diagnostic guides for common problems:
23+
24+
| File | What it covers |
25+
|------|----------------|
26+
| [transfers.md](transfers.md) | Transfers not working: LLM not calling tool, wrong tool type, telephony failures, transient assistant issues |
27+
28+
**When to read these:** Before creating or modifying any resource file in `resources/<env>/`, and when diagnosing runtime issues with deployed assistants.

docs/learnings/tools.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ Use the canonical names to avoid confusion.
9999

100100
Liquid/Mustache templates work in `sipVerb`, `message`, and `twiml` fields, but intentionally **do not** run on `summaryPlan` content.
101101

102+
### Missing `function.description` can make the LLM reluctant to transfer
103+
104+
If you don't set an explicit `function.description` on a transferCall tool, the auto-generated description may include overly cautious language that biases the LLM toward not calling it. Always set `function.description` explicitly.
105+
106+
### `sipVerb: "refer"` can silently fail with some providers
107+
108+
If your SIP trunk or telephony provider doesn't support the REFER method, transfers will appear to initiate on the Vapi side (`endedReason: assistant-forwarded-call`) but the destination never rings. If you're seeing this, remove explicit `sipVerb: "refer"` from your `transferPlan` and let Vapi use the default mechanism.
109+
110+
**See also:** [transfers.md](transfers.md) for a full diagnostic guide on transfer issues.
111+
102112
---
103113

104114
## endCall Tools

docs/learnings/transfers.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Transfer & Handoff Troubleshooting
2+
3+
A diagnostic guide for when `transferCall` or `handoff` tools don't work as expected. Walk through these steps in order to identify and fix the issue.
4+
5+
---
6+
7+
## Step 1: Confirm whether the tool call happened at all
8+
9+
### Symptom
10+
11+
Caller hears something like "Please hold while I transfer you" and then nothing happens — silence, call times out, or the original assistant continues talking.
12+
13+
### What it usually means
14+
15+
The model produced a text-only response instead of a tool call. This is common when the tool description is vague or the prompt doesn't explicitly require the tool call.
16+
17+
### How to fix
18+
19+
Make tool execution rules explicit in the system prompt. Put them at the **end** of the prompt so they're freshest in the model's context window.
20+
21+
**Recommended prompt pattern** — add this at the end of your system prompt:
22+
23+
```
24+
CRITICAL TOOL-CALL RULES — these override any ambiguity above:
25+
26+
1. Whenever you decide to transfer, you MUST invoke the transferCall
27+
function in that same response.
28+
2. Your spoken acknowledgment and the transferCall tool call happen
29+
in the SAME response turn.
30+
3. If you already said "I'll connect you now" but the call is still
31+
active, immediately invoke transferCall again without saying
32+
anything else.
33+
```
34+
35+
---
36+
37+
## Step 2: Fix tool descriptions that make the model reluctant
38+
39+
### Symptom
40+
41+
The assistant "knows" it should transfer, but it frequently doesn't.
42+
43+
### What it usually means
44+
45+
Some tool configurations end up with language like "DO NOT call this function unless instructed" in the tool description the LLM sees. This biases the model toward not calling it.
46+
47+
### How to fix
48+
49+
- **Always set an explicit `function.description`** on your transferCall/handoff tools. Without a custom description, some setups inject overly cautious guardrails into the tool definition.
50+
- **Make destination `description` fields specific and use-case oriented.** The LLM uses these descriptions to select the right destination — they're effectively part of your routing policy.
51+
52+
```yaml
53+
destinations:
54+
- type: number
55+
number: "+15551234567"
56+
description: "Transfer to the billing department for payment and invoice questions"
57+
message: "Let me connect you with our billing team."
58+
```
59+
60+
---
61+
62+
## Step 3: Use the right mechanism (transferCall vs handoff)
63+
64+
### Symptom
65+
66+
You're trying to transfer to another assistant in a squad, but it behaves like it's dialing a phone number, hallucinates a destination, or intermittently stalls.
67+
68+
### What it usually means
69+
70+
`transferCall` is a **telephony-forwarding** primitive — it dials phone numbers and SIP URIs. For transferring between assistants in a squad, use the `handoff` tool type instead.
71+
72+
### When to use each
73+
74+
| Mechanism | Use when |
75+
|-----------|----------|
76+
| `transferCall` | Transferring to an external phone number, SIP URI, or PBX |
77+
| `handoff` | Transferring between assistants within a squad |
78+
| `assistantDestinations` on squad members | Shorthand for handoff — Vapi converts these to handoff tools automatically |
79+
80+
Using `transferCall` for assistant-to-assistant routing can cause the original assistant to continue with an error message when the transfer doesn't work as expected.
81+
82+
---
83+
84+
## Step 4: Distinguish "platform executed transfer" from "telephony transfer succeeded"
85+
86+
### Symptom
87+
88+
The call's `endedReason` says the transfer happened (e.g., `assistant-forwarded-call`), but the destination never rang.
89+
90+
### What it usually means
91+
92+
`assistant-forwarded-call` means "Vapi initiated the transfer," not "the downstream provider successfully completed it." The telephony leg can still fail.
93+
94+
### Common telephony failure modes
95+
96+
**SIP REFER not supported by provider:**
97+
Some SIP trunks/providers don't support the REFER method. The call ends during transfer with no ring at the destination. Fix: remove explicit `sipVerb: "refer"` from your `transferPlan` and let Vapi use the default transfer mechanism.
98+
99+
**Provider-specific auth issues:**
100+
Some providers (especially with SIP REFER) reject the transfer due to authentication header issues. The call looks "forwarded" on the Vapi side but drops at the provider level. Check your provider's transfer compatibility docs.
101+
102+
### How to verify
103+
104+
Check the call's `endedReason` and provider-level call logs:
105+
- `assistant-forwarded-call` = Vapi sent the transfer command
106+
- Actual ring/answer = check your telephony provider's logs/CDRs
107+
108+
---
109+
110+
## Step 5: Watch for transient assistant foot-guns
111+
112+
If you're using transient assistants (created per-call via API), two extra issues arise:
113+
114+
### Tool descriptions drift between calls
115+
116+
If your tool's `description` isn't explicitly set, the auto-generated description can vary slightly between calls. This inconsistency can reintroduce LLM reluctance to call the tool.
117+
118+
**Fix:** Treat `function.description` as required configuration. Set it explicitly and keep it stable across calls.
119+
120+
### One-shot transfer flows are fragile
121+
122+
Transient assistants often appear in flows where you want immediate transfer behavior. Any prompt ambiguity increases the chance the model speaks first and stalls instead of calling the tool.
123+
124+
**Fix:** Put transfer rules at the end of the system prompt. Prefer a single atomic response that both acknowledges and invokes the tool.
125+
126+
---
127+
128+
## Quick Triage Checklist
129+
130+
Use this checklist when debugging transfer issues:
131+
132+
1. **Did a tool call appear?** Check the call transcript/messages. If the assistant only said "I'll transfer you" without a tool call, it's a prompt issue (Step 1).
133+
2. **Did the tool call error?** Check for validation or configuration errors in the tool call result. If so, it's a config issue (Step 2).
134+
3. **Is this a telephony failure?** Check if `endedReason` shows `assistant-forwarded-call` but the destination never rang. If so, it's a provider/SIP issue (Step 4).
135+
4. **Are you using the right tool type?** If transferring between squad assistants, use `handoff` not `transferCall` (Step 3).
136+
5. **Are you seeing intermittent "trouble accessing the system" messages?** This is often the LLM generating error text after a failed tool result — check the tool call result for errors.

0 commit comments

Comments
 (0)