Why AI Calls Always End at the Same Duration - Zian AI

Why AI Calls Always End at the Same Duration

A call that ends at the same duration every time is a timer firing, not a bug — the exact number names the layer. 32 seconds is SIP 64*T1 (RFC 3261 Timer B). 30 seconds on a LiveKit SIP stack is media_timeout_initial. 600 seconds is a Vapi maxDurationSeconds default. 4 hours is Twilio.

Why do all my agent’s calls end after the same number of seconds every time?

Because something counted to a fixed number and then hung up. That is the whole diagnosis, and it is good news: a repeating constant is the fastest-narrowing symptom in an agentic voice stack. Load, carrier congestion, model stalls and bad audio all produce a distribution of call lengths. A timer produces a constant.

The trap is that the platform reports something uninformative when a timer fires. FreeSWITCH logs NORMAL_CLEARING. A carrier sends a plain BYE with Q.850 cause 16. Your dashboard says the call completed. Nothing there is wrong and nothing is useful, which is why the clock is the only signal you have. If your platform is giving you a specific code, start there instead: our guide to AI voice agent call drops and their ended reason codes maps those.

Every constant below is a timer someone can point at in a specification, a config file or a source tree. Find your number and you have your layer.

The duration lookup table: what each constant actually means

Durations measured from answer (the 200 OK / ACK), not from dial. Every default below was verified at the owning organisation as at 14 September 2026.

Observed constant Timer that produced it Owner and where it is written down The one check that confirms it
~10 s, dies just after the greeting Speech-to-text websocket closed for inactivity Deepgram: no audio or KeepAlive within a 10-second window closes the connection with a NET-0001 error (Deepgram docs) Grep STT client logs for NET-0001. If it is there, the telephony leg is innocent.
~15 s after audio stops mid-call Media inactivity timeout, steady state livekit/sip pkg/sip/media_port.go: defaultMediaTimeout = 15 * time.Second RTP packet counters flatline ~15 s before the BYE.
~30 s from answer, RTP never arrives at all Media inactivity timeout, initial livekit/sip pkg/sip/media_port.go: defaultMediaTimeoutInitial = 30 * time.Second. The SIP API reference names the override (media_timeout) but not the value Zero inbound RTP on the SIP port for the whole call, and the BYE lands within a few hundred milliseconds of 30 s.
31.5 – 32.0 s, exact SIP 64*T1. Either the INVITE transaction timed out (Timer B) or the far end never saw your ACK (Timer H), after which RFC 3261 says the session SHOULD be terminated with a BYE RFC 3261 §17.1.1.2, §17.2.1, §13.3.1.4 and Appendix A Table 4 In a capture: the 200 OK is retransmitted about ten times across the 32 seconds — per §13.3.1.4 that interval starts at T1 and doubles only until it reaches T2 (4 s) — and your ACK is absent or addressed where the far end is not listening.
Exactly half the Session-Expires value A session refresh was due and did not happen. RFC 4028 recommends refreshing once half the interval has elapsed RFC 4028 §7.2 and §9 Look for a re-INVITE or UPDATE at that moment that got no 2xx, or none sent at all.
The Session-Expires value, or a little under it Session timer expiry. The side not refreshing BYEs slightly early — RFC 4028 recommends the minimum of 32 seconds and one third of the interval RFC 4028 §4 and §10. Asterisk ships timers_sess_expires at 1800 and timers_min_se at 90 A 1768 s or 1800 s call with healthy audio throughout is this and almost nothing else.
Exactly 600 s (10:00) Application-level maximum call duration left at its default Vapi maxDurationSeconds: @default 600 (10 minutes), minimum 10, maximum 43200, in Vapi’s published API schema; the matching endedReason is exceeded-max-duration The provider reports the cap by name. No capture needed.
Exactly 14400 s (4:00:00) Carrier hard cap Twilio: the default time limit on calls is 4 hours, and that is also the maximum unless the 24-hour feature is enabled Call length equals the cap to the second across every long call.
300 s or 20 s on a room-based stack Room lifecycle, not call lifecycle LiveKit empty_timeout default 300 s (room open if no one joins) and departure_timeout default 20 s (after everyone leaves) The room closed first and the SIP leg followed. Room events precede the BYE. In livekit/sip issue #812, open as at 14 September 2026, a call ended 5 s after answer whenever no room participant sent audio, and the only reply on that thread points at these two room timeouts rather than at the SIP media timeout.

Two caveats. Asterisk ships rtp_timeout and rtp_timeout_hold at 0, meaning do not check, so a bare Asterisk produces no media-inactivity constant — but a carrier SBC in front of it often will, on a value it does not publish. And one instance is unresolved: community.openai.com topic 1393596, posted 30 August 2026, reports OpenAI Realtime API calls over SIP ending at 30.0 to 30.16 seconds across five consecutive tests, invariant of whether the webhook arrived, the sideband websocket connected, or the caller spoke. That thread had no replies and no published cause as at 14 September 2026. The shape is textbook; the cause is not yet public.

The Ten-Call Constant Rule: turning a number into a layer

The Ten-Call Constant Rule: place ten calls, record answer-to-hangup in milliseconds, take the spread, and let the spread choose the layer.

  • Spread under 500 ms (one SIP T1) — a fixed timer fired. Look the constant up in the table above. Do not investigate anything else first.
  • Spread 0.5 to 3 s — still a timer, but re-armed by network events: retransmission-driven expiry under packet loss, or a refresh that sometimes lands. Capture packets before changing config.
  • Spread above 3 s, or no repeating mode at all — not a timer. Stop reading this page.

Ten is the floor because a three-call sample cannot distinguish a 30-second timer from a caller who hangs up quickly. Measure to milliseconds: the gap between 30.0 and 32.0 is the gap between a media timeout and a SIP transaction timeout, and a dashboard that rounds to whole seconds hides it. If you have no clean way to place ten controlled calls, the pre-go-live test routine for voice agents is the harness to build first.

Three clocks, and they disagree on purpose. Your application log starts when your code learns the call was answered, which is after the fact. Your provider dashboard reports billable duration, rounded and sometimes started at dial rather than answer. The SIP trace on the media path is the only one that timestamps the actual 200 OK and the actual BYE. Take the constant from the trace; use the other two only for ordering. In the OpenAI case above, ordering is the finding: the SIP hangup at 12:05:07.31 precedes the websocket error at 12:05:09.92 by 2.6 seconds, which makes the websocket a symptom rather than a cause. Aligning those three timelines is ordinary AI agent observability work — traces, logs and outcomes.

Where 32 seconds comes from, derived

This is the most useful constant to recognise, so derive it rather than memorise it. RFC 3261 sets T1 to a default of 500 ms as an estimate of round-trip time. Timer A retransmits an INVITE at T1 and doubles each time. Timer B, the INVITE transaction timeout, is 64*T1.

Substitute 500 ms and the transmissions land at 0, 0.5, 1.5, 3.5, 7.5, 15.5 and 31.5 seconds — seven in total, which is exactly what the RFC says 64*T1 buys you — and Timer B fires at 32.0 s. Timer H, the server-side wait for an ACK, is 64*T1 for the same reason: it is chosen to equal Timer B. If your T1 has been tuned to 250 ms for a low-latency private link, your constant becomes 16 s; if a device has been set to 1 s, it becomes 64 s. The arithmetic is the diagnosis.

The practical failure this catches is an ACK sent but not delivered — addressed to the Contact URI instead of the Record-Route path, which is livekit/sip issue #730, open since 22 June 2026 against an Exotel TCP trunk. The far end never sees an ACK, retransmits the 200 OK, gives up at 64*T1 and BYEs. From your side the call answered, ran silently and ended at 32 seconds. Connecting an AI agent to a SIP trunk covers the routing decisions that create this fault.

When the duration is not constant, this is not your problem

Rule the class out in one pass. If your ten durations are 11 s, 47 s, 6 s, 133 s and 22 s, there is no timer to find and every minute in a packet capture is wasted. Variable-length failures are behavioural or load-driven: callers hanging up on a greeting, a model stall long enough that the caller gives up, one-way audio tolerated for a while, or capacity limits that bite only at peak.

Two intermediate cases are worth separating. A bimodal distribution — half the calls at 8 s and half at 32 s — is usually two faults stacked; split the sample by direction, trunk or region before analysing further. A distribution with a floor — nothing shorter than 30 s, everything else scattered above — is a timer that only fires when nobody speaks, which is a silence timeout rather than a media timeout; Vapi publishes silence-timed-out as a distinct endedReason from exceeded-max-duration.

Do this yourself, or hand the stack over

The method above is complete and runnable. What it costs to run is the part people underestimate, so here are the conditions rather than a conclusion.

Condition Do it yourself Hand the stack over
Trunks in production One trunk, one carrier Three or more, or multiple countries
Access to the media path You can run tcpdump or sngrep on the SBC Your provider owns the SBC and will not share captures
Skill on hand Someone reads SDP and a SIP ladder diagram unaided Nobody has opened a pcap this quarter
Repeat rate First occurrence Third fixed-duration incident in a quarter
Where the timer lives In config you control In a vendor default you cannot read or override

That last row decides it. A timer you can read is a twenty-minute fix; a timer you cannot read is an open support ticket. It is why private AI deployment for sales agents changes the shape of this problem rather than its difficulty: Zian AI supports private model deployment on customer infrastructure, so the media timeout, the session timer and the maximum call duration are values in your own configuration, readable at the moment a call ends at 30 seconds instead of a fortnight later. Same table, same rule — you look the constant up instead of asking for it.

Frequently asked questions

Is a hangup at exactly 30 seconds always a SIP problem?

No. On a LiveKit SIP stack, 30 seconds with no RTP at all is the media inactivity timeout, whose initial value defaults to 30 seconds in the source. On other stacks 30 seconds is often a silence timeout that fires when nobody speaks. The SIP constant is 32 seconds, not 30, and the two second gap is the distinguishing test.

What does the 32 second constant in SIP actually come from?

It is 64 times T1, and T1 defaults to 500 milliseconds, so 64 times 0.5 equals 32 seconds. RFC 3261 uses that value for Timer B, the INVITE transaction timeout, and for Timer H, the wait for an ACK. RFC 3261 section 13.3.1.4 states that if the server retransmits the 2xx response for 64 times T1 without receiving an ACK, the session SHOULD be terminated with a BYE.

How many calls do I need before the pattern is real?

Ten, measured to milliseconds from answer to hangup. The useful output is the spread rather than the average. Under 500 milliseconds of spread is a fixed timer. Above three seconds of spread there is no timer to find and you should stop looking for one.

Can a session timer end a call that has healthy audio in both directions?

Yes, and that is what makes it confusing. Session timers run on signalling, not media, so a perfectly audible call ends the moment a refresh fails. RFC 4028 recommends sending the refresh once half the session interval has elapsed, and it recommends that the side not refreshing send a BYE slightly early, at the minimum of 32 seconds and one third of the interval.

Where do I get the exact hangup time from?

From the SIP trace on the media path, because it timestamps the actual 200 OK and the actual BYE. Application logs start when your code learns about the call, which is later, and provider dashboards usually report rounded billable duration. Use the trace for the constant and the other two only to establish ordering.

My durations are all different. Does any of this apply?

No, and ruling that out quickly is the point of measuring ten calls first. Variable durations mean behaviour or load, not a timer: callers leaving, a model stall, one way audio, or capacity limits at peak. Go to the ended reason codes instead of to a packet capture.

Working on a stack where the constant is somebody else’s default

Zian AI builds autonomous AI sales agents with live phone, SMS, email and WhatsApp outreach across 30+ languages, with SmartReach AI™ orchestrating channel and timing and PrecisionPitch AI™ split-testing the approach. Private model deployment on customer infrastructure puts the telephony timers in your hands rather than in a vendor default. Zian is currently in partnership-application beta.

Apply For Partnership

Related Blogs

Related from Zian AI