timeout — 2.5 seconds by default, 40 seconds
maximum. Some work genuinely takes longer: a slow third party, a human
approval, a generated document.
Do not try to stretch the timeout. Use the deferred pattern instead.
The problem with waiting
A caller hears silence as a broken line. Ten seconds of nothing is long enough for most people to say “hello?” and then hang up. Anything that might exceed a few seconds needs to acknowledge first and deliver later.The pattern
1
Return immediately with a placeholder
Your webhook answers straight away. The agent says something natural and the
conversation continues.
2
Include the call ID
Add
call_id as an automatic parameter so your worker knows which live call the
answer belongs to:3
Do the work off the request path
Your existing queue or worker. Nothing special.
4
Inject the result into the live call
When it completes, post the answer back as though the caller had said it. The
agent reads it and responds naturally — “just got that back, your refund was
approved.”
Messages can only be injected into a call that is joined and not yet ended.
Posting to a finished call returns an error — log it for retry rather than
dropping it, since the caller may need a follow-up another way.
Why this over a longer timeout
- The conversation keeps moving; the caller is not stranded
- The agent can answer other questions while the work runs
- A slow dependency degrades the answer’s timing, not the whole call
- It needs no new infrastructure — an HTTP tool you already have, plus one call back
Writing the placeholder
The placeholder is spoken. Make it sound like a person:When not to use it
If the work is fast but variable — usually 200ms, occasionally 4s — raisetimeout instead and set readOnly: true where safe, so the runtime can run it
eagerly. The deferred pattern is for work that is reliably slow, not
occasionally slow.