A keypress can reach an IVR three ways: as in-band audio tones mixed into the call, as RFC 4733 telephone-event packets carried beside the audio, or as SIP INFO messages. Twilio’s help centre states that Out of band RFC-2833 is supported. Out of band SIP INFO is not currently supported.
Check the INVITE SDP for a=rtpmap:101 telephone-event/8000 before you change a single prompt.
That check takes two minutes and it settles the question most teams spend a week on. Every managed voice platform logs a digit as sent the moment it hands it to the telephony layer, and that log is a statement about your own uplink, not about the far end. Below is the cross-platform transport table, what breaks each transport, the packet-level test that distinguishes them, and a dated, checkable example from LiveKit’s open-source SIP bridge, where the sample-rate handling is public enough to read commit by commit.
The three ways a keypress travels, and what kills each one
Vapi’s default-tools documentation, read on 10 September 2026, publishes the taxonomy plainly: in-band means tones are transmitted as part of the regular audio stream. This is the simplest method, but it can suffer from quality issues if the audio stream is compressed or degraded.
Out-of-band via RFC 2833 means tones are transmitted separately from the audio stream, within RTP (Real-Time Protocol) packets.
And SIP INFO means tones are sent as separate SIP INFO messages. While this can be more reliable than in-band DTMF, it’s not as widely supported as the RFC 2833 method.
RFC 2833 was obsoleted by RFC 4733 in December 2006, but the industry still says 2833 and means the same payload format. The RFC explains in §1.2 exactly why the out-of-band format exists: Separate RTP payload formats for telephony tone signals are desirable since low-rate voice codecs cannot be guaranteed to reproduce these tone signals accurately enough for automatic recognition.
That single sentence is the argument against relying on in-band tones on any path where the audio is coded for speech rather than passed straight through as G.711.
| Transport | What actually goes on the wire | What breaks it | The test that proves it |
|---|---|---|---|
| In-band audio tones | The two DTMF frequencies synthesised into the same PCM stream as the agent’s speech | Speech coding anywhere in the path. RFC 4733 §3.1 names G.723.1 as an example of a low bit-rate codec that renders DTMF tones unintelligible; it does not enumerate the rest, and we located no vendor page that does. Twilio’s pass-through guarantee is written for G.711 alone: In-band DTMF tones within the G.711 audio stream are passed-through in the audio stream untouched.Agent speech overlapping the tone is a second, independent risk |
Play the call recording and listen. If you can hear the tone, it was in-band. Then check the negotiated codec in the SDP |
| RFC 4733 telephone-event (RTP) | Separate RTP packets on a dynamically negotiated payload type, carrying an event code, a volume and a duration instead of audio | The far end never negotiating telephone-event in its SDP answer, so the packets arrive on a payload type nothing is listening to. Also clock-rate and timestamp-base mismatches, which RFC 4733 §2.1 forbids: named telephone events MUST use the same sequence number and timestamp base as the regular audio channel |
Wireshark filter rtp.p_type == 101, then expand RFC 2833 RTP Event and confirm the End of event bit is set on the last packet of each digit |
| SIP INFO | A separate SIP request per digit, in the signalling channel, never in the media path | The other side not supporting it at all. Twilio states SIP INFO is not currently supported |
Filter sip.Method == "INFO" in the same capture. No INFO requests means no digits went that way |
The transport is negotiated before the first digit is ever pressed, so no amount of prompt engineering can rescue a call where telephone-event was never in the SDP.
What Vapi, Retell AI, LiveKit and Twilio each send by default
Each vendor documents its own knob, and Vapi publishes the three-transport taxonomy in full. What we could not locate on any of these four vendors’ own documentation sites, read 10 September 2026, is the side-by-side, so here it is, every cell read from that vendor’s own page or source tree on that date.
| Platform | Transport it uses | Its own words | Where you set or check it |
|---|---|---|---|
| Vapi | Out-of-band RFC 2833, via the telephony provider’s API | Vapi’s DTMF tool integrates with telephony provider APIs to send DTMF tones using the out-of-band RFC 2833 method.The same page adds: Note, the tool’s effectiveness depends on the IVR system’s configuration and their capturing method. |
Dial Keypad (DTMF) in Vapi’s default tools; pause characters in the Vapi IVR navigation guide |
| Retell AI | RFC 2833 on the receive side, stated explicitly; the send side is the press_digit tool and Retell does not state its transport on that page |
Retell captures RFC 2833 DTMF (keypad tones sent as RTP events) by default. |
Retell’s capture DTMF input page; the sending tool is documented at Press digit (IVR navigation) |
| LiveKit SIP | RFC 4733 telephone-event/8000 over RTP, with in-band tones as an opt-in extra |
The docs say DTMF is transmitted over RTP using the telephone-event/8000 payload format, which ensures reliable signaling across codecs by sending event codes, durations, and volumes rather than the audio signal itself.The SIP service config carries a separate audio_dtmf flag whose source comment reads AudioDTMF forces SIP to generate audio DTMF tones in addition to digital. |
LiveKit’s Handling DTMF guide; audio_dtmf in pkg/config/config.go on livekit/sip main, which defaults to off |
| Twilio (sitting under many of the above) | Out-of-band RFC 2833 only; SIP INFO unsupported; in-band passed through untouched on G.711 | Out of band RFC-2833 is supported. Out of band SIP INFO is not currently supported. In-band DTMF tones within the G.711 audio stream are passed-through in the audio stream untouched. |
What DTMF types do you support?, last updated 23 May 2025 |
Transport choice is not a detail these vendors treat lightly. When Vapi rebuilt its DTMF tool it said so on its own blog on 15 May 2025: Until today, the existing DTMF tool in Vapi wasn’t working for all IVRs.
The rebuild was described as integrating with telephony providers to send the tones natively, and the current documentation names RFC 2833 as the method. LiveKit has gone the other way and pushed the problem up into the agent layer, documenting an ivr_detection option on AgentSession that, when set to True, automatically makes use of built-in tools to detect IVR systems and relay DTMF tones from the user back to the telephony provider
, plus a prebuilt GetDtmfTask for collecting digits from a caller. Both are worth knowing about before you write your own retry logic.
Two consequences fall straight out of the table. First, if your platform runs on Twilio and someone has configured the far-end trunk for SIP INFO, there is no configuration on the agent that will fix it. Second, Vapi’s and Retell’s published transport is the same RFC 2833 family, so a digit that works on one and fails on the other is almost never a transport difference; it is timing, or it is the trunk in between.
Why does my AI voice agent press a number and nothing happens?
Because sent
and received
are logged in different places, and most teams only have the first one. Use what we call the three-proof check: a digit is only proven when three independent artefacts agree.
| Proof | What you are looking for | If it is missing |
|---|---|---|
| 1. SDP proof — the transport was agreed | a=rtpmap:101 telephone-event/8000 and a=fmtp:101 0-15 in the INVITE, and the same payload type echoed in the 200 OK answer |
Retell’s packet-capture guide is explicit: If this line is absent, in-band or SIP INFO DTMF may be used instead.Stop here and fix the trunk |
| 2. RTP proof — the event left your side | Packets matching rtp.p_type == 101, with the End of event bit true on the final packet of each digit and a plausible Duration field |
Your platform’s tool log said success and nothing went on the wire. That is a platform bug, and it is worth a support ticket with the call ID |
| 3. IVR proof — the far end acted | The IVR’s next utterance is different from its last one, i.e. the menu advanced | The digit arrived and was rejected, or it arrived while the IVR was still speaking. This is the timing problem, not the transport problem |
Retell publishes the packet-level half of this in its guide to debugging SIP calls with a PCAP file, including the field meanings inside an RFC 2833 RTP Event: Event ID (0–9, *=10, #=11, A–D=12–15), End of event, Volume in dBm0, and Duration in RTP timestamp units, which you divide by the clock rate to get milliseconds. Its symptom table names the exact failure this page is about: DTMF not recognised, check for a Payload type mismatch between INVITE SDP and actual RTP packets
.
A platform-side log entry reading success is a claim about your uplink, never a receipt from the far end — the only receipt an IVR issues is changing what it says next.
Eight real calls into a carrier IVR: what the send logs did and did not prove
The clearest public evidence for proof 3 is not a vendor page. It is issue #45 in the open-source callpilot project, opened 29 July 2026 and still open when we read it on 10 September 2026; the issue is a migration of tianye1999/callpilot#73 and names @tianye1999 as its original author. It logs eight real calls placed from a cellular modem into one carrier customer-service IVR on 12 July 2026, and records for each call how many keys were pressed, in which mode, and whether the menu advanced.
Of the eight calls, five involved a keypress and three did not. Seven of the presses went out in the project’s inband mode and one via the modem’s own qvts command. One call is marked as the AI having heard a keypad menu and simply talked instead of pressing — the issue’s own verdict column reads should have pressed, didn’t
. Three more carry the warning marker in that column. One of the three spells the verdict out as pressed but effect dubious
, and for that call the transcript shows the digit going out and the IVR answering, in the issue’s own English translation, I didn’t understand you
. The other two carry the marker with no transcript published.
The author’s conclusion is the part worth carrying away, because it is the same trap on every managed platform: the tool’s success flag and the modem’s confirmation only prove “the local side sent it”, not “the peer IVR received it and advanced the menu”
. This is a single project’s log against a single carrier IVR, not a study, and it is a modem path rather than a SIP path — we are citing it for the shape of the evidence, not for a rate.
Its leading root-cause hypothesis is worth pairing with two vendor instructions. The issue suspects that under in-band mode the agent’s speech and the tone share one uplink and interfere, and notes that the failure was most obvious when the agent talked while pressing. Independently, Vapi’s IVR navigation prompt template tells the assistant to Avoid saying anything if using the dtmf tool at the same time
, and Retell’s custom-LLM instructions say: Have the agent stay silent for that response so it doesn’t speak while pressing.
Neither vendor explains why silence matters when the tone is not in the audio at all; the plausible mechanisms are acoustic interference on any in-band leg and the IVR’s own barge-in detector treating speech as input. We could not locate a vendor statement resolving which it is.
A dated example: LiveKit’s DTMF sample-rate fix was merged, then reverted
RFC 4733 §2.1 says the default clock frequency is 8000 Hz, but the clock frequency can be redefined when assigning the dynamic payload type
, and that telephone events MUST use the same sequence number and timestamp base as the regular audio channel
. So when the negotiated audio codec is not 8 kHz, a DTMF stream hard-coded to 8 kHz is emitting timestamps on a different base from the audio it accompanies.
That is precisely what pull request #819 on livekit/sip, titled Match DTMF sample rate to the audio codec rate.
, set out to fix. It replaced the hard-coded telephone-event/8000 with a rate derived from the negotiated audio codec, scaled the outgoing RTP timestamp accordingly, and added pipeline tests at 8000, 16000 and 48000 Hz. It was merged on 4 September 2026 as commit 4bf92ed.
Four days later, pull request #839 reverted it. The revert body is two lines: This reverts commit 4bf92ed845e026b7a30323ccb508d0f75d2c2d9f
and Reverting to unblock the deployment of the late offer changes.
It merged on 8 September 2026.
Read the state accurately, because the precision is the point. As of 10 September 2026, pkg/sip/media_pipeline.go on livekit/sip main is back to constructing the DTMF stream with the fixed dtmf.SampleRate constant, and the revert is the most recent commit touching that file. That is the current behaviour, and a title search of the repository turned up no later pull request re-landing the change. What this is not is a vendor failing. The stated reason for the revert is a release-sequencing conflict with an unrelated change, not a judgement that the fix was wrong, and LiveKit’s published documentation still describes telephone-event/8000, so the shipped code and the shipped docs agree with each other. What it is, for anyone running a LiveKit-based agent against a wideband trunk today, is a known open gap with a commit hash you can check against your own deployment.
The practical move is small: if your agent negotiates a 16 kHz or wideband codec and digits are unreliable, pin the audio codec to G.711 for calls that must navigate an IVR and re-test. The same discipline of reading the vendor’s own strings rather than a symptom description is what we applied to SIP response codes and platform ended-reason codes, which is the vocabulary to reach for once a call ends rather than merely misbehaves.
How far apart should the digits be? The spacing ladder
Once transport is proven, everything left is timing, and both major platforms publish numbers you can act on. Vapi documents pause characters for the digit string itself: Use w for a 0.5s pause, W for a 1s pause
on Twilio, Telnyx, Vapi numbers and BYOK SIP, and p for a 0.5s pause on Vonage. Its guidance is Start with 0.5s pauses and increase only if digits are still missed.
Retell exposes a different control on the other side of the problem: a Pause Detection Delay that governs how long the agent waits after the IVR stops speaking before it presses, defaulting to 1000 ms with a valid range of 0–5000 ms.
The ladder below is Vapi’s published escalation with a diagnostic column added, so each rung tells you something rather than just being tried.
| Rung | Setting | Try it when | What success at this rung tells you |
|---|---|---|---|
| 0 | Prove the SDP first | Always, before any of the below | Nothing below is meaningful until telephone-event is negotiated |
| 1 | No pauses, e.g. 123# |
Baseline only | The IVR buffers well; nothing to tune |
| 2 | 0.5s gaps, e.g. 1w2w3# |
First escalation, per Vapi’s own advice | The far end needs inter-digit spacing; a normal, common result |
| 3 | 1s gaps, e.g. 1W2W3# |
Digits still missed at rung 2 | The IVR is slow or your tones are marginal — check volume and duration in the RTP event before assuming it is the IVR |
| 4 | Delay the first press (Retell: raise Pause Detection Delay above 1000 ms) | The first digit is lost but later ones land | The agent was pressing before the menu finished reading, not a transport fault at all |
| 5 | Speak the option instead of pressing | Rungs 2–4 all fail | The menu accepts speech, so you have a working path today — but you still have an unfixed DTMF defect, and you should keep the ticket open |
One structural note from Vapi’s guide that saves a lot of retries: send a whole sequence in one tool call rather than several, because Multiple separate
dtmf calls can arrive too slowly or be partially ignored; a single combined sequence is more consistent.
Rung 5 is the honest cost of running this yourself. Working through the ladder needs a packet capture, a trunk you can reconfigure, and a real IVR to test against, and each round trip is a live phone call rather than a unit test. Zian AI runs live phone, SMS, email and WhatsApp outreach through autonomous sales agents, with SmartReach AI™ orchestrating channel and timing and PrecisionPitch AI™ split-testing the approach, and this class of telephony debugging is part of running them; Zian is in partnership-application beta, with no free trial and no self-serve signup. If the calls in question are inbound rather than outbound, the upstream checks are in our guide to getting a phone line ready for an inbound AI caller, and the design question of whether the menu should exist at all is covered in AI voice agents versus IVR phone trees. The agent types this telephony work sits underneath are set out on Zian AI’s autonomous sales agent solutions page.
Zian AI builds autonomous AI sales agents — outbound appointment setters, 24/7 support agents in 30+ languages, and sales call closers — with API and CRM integrations into HubSpot, Salesforce, HighLevel and Zapier. The platform is in a partnership-application beta.
Who owns each figure on this page
Every number and quoted string above belongs to somebody. This table names the owner, the exact page it came from, and the date we opened it, so you can re-check any of it without taking our word for it.
| Figure or quoted string | Owner (organisation) | Source URL | Date checked |
|---|---|---|---|
| RFC 2833 supported, SIP INFO not currently supported, in-band passed through on G.711 | Twilio | support.twilio.com article 223180088 (article last updated 23 May 2025) | 10 Sep 2026 |
| The three DTMF methods, and Vapi sending via out-of-band RFC 2833 | Vapi | docs.vapi.ai/tools/default-tools | 10 Sep 2026 |
| w = 0.5s pause, W = 1s pause, p = 0.5s on Vonage; start at 0.5s; single combined sequence | Vapi | docs.vapi.ai/ivr-navigation | 10 Sep 2026 |
| The existing DTMF tool was not working for all IVRs, before the May 2025 native-DTMF rebuild | Vapi | vapi.ai/blog/vapi-now-supports-sending-native-dtmf (published 15 May 2025) | 10 Sep 2026 |
| RFC 2833 captured by default; SDP and Wireshark checks; RFC 2833 RTP Event field meanings | Retell AI | docs.retellai.com/build/user-dtmf and /reliability/debug-calls-pcap | 10 Sep 2026 |
| Pause Detection Delay: default 1000 ms, range 0–5000 ms; stay silent while pressing | Retell AI | docs.retellai.com/build/single-multi-prompt/press-digit | 10 Sep 2026 |
telephone-event/8000 over RTP; publishDtmf; ivr_detection; GetDtmfTask |
LiveKit | docs.livekit.io/telephony/features/dtmf | 10 Sep 2026 |
PR #819 merged 4 Sep 2026 as 4bf92ed; PR #839 reverted it 8 Sep 2026; audio_dtmf config flag |
LiveKit (livekit/sip repository) | PR #819, PR #839, and pkg/config/config.go on main |
10 Sep 2026 |
| Eight-call keypress log; 5 calls with presses; 7 in-band / 1 modem-command presses; the local-side-sent conclusion | callpilot project (original author @tianye1999; migrated issue filed by @jjwxcfan) | github.com/jjwxcfan/callpilot/issues/45 (opened 29 July 2026, open when read) | 10 Sep 2026 |
| Default clock frequency 8000 Hz; same timestamp base as audio; low-rate codecs and G.723.1 | IETF (Schulzrinne & Taylor, December 2006) | RFC 4733, sections 1.2, 2.1 and 3.1 | 10 Sep 2026 |
| Three-proof check and the spacing ladder’s diagnostic column | Zian AI (this page) | Assembled here from the vendor sources above; the framing is ours, the underlying facts are theirs | 10 Sep 2026 |
Frequently asked questions
How do I tell whether my agent is sending in-band or out-of-band DTMF?
Take a packet capture and look at the INVITE SDP. Retell’s packet-capture guide tells you what to look for: the lines a=rtpmap:101 telephone-event/8000 and a=fmtp:101 0-15 mean RFC 2833 is negotiated on payload type 101, and if that line is absent, in-band or SIP INFO DTMF may be used instead. Then filter the media with rtp.p_type == 101 in Wireshark to confirm events actually left your side.
Does Twilio support SIP INFO for DTMF?
No. Twilio’s help centre article What DTMF types do you support?, read on 10 September 2026 and last updated 23 May 2025, states that out of band RFC-2833 is supported, that out of band SIP INFO is not currently supported, and that in-band DTMF tones within the G.711 audio stream are passed through untouched. If a trunk on the other side is configured for SIP INFO only, no agent-side setting will recover the digits.
Why do in-band DTMF tones stop working when the codec changes?
Because compressed speech codecs are built to carry speech, not pure tone pairs. RFC 4733 section 1.2 gives the reason in one sentence: separate RTP payload formats for telephony tone signals are desirable since low-rate voice codecs cannot be guaranteed to reproduce these tone signals accurately enough for automatic recognition. Section 3.1 of the same RFC names G.723.1 as an example of a low bit-rate codec that renders DTMF tones unintelligible.
My platform logs the keypress as sent, so why does the IVR say it did not understand?
Because the send log is written on your side. It records that the digit was handed to the telephony layer, not that the far end received it and advanced. Use the three-proof check on this page: SDP negotiated, RTP event on the wire with its end bit set, and a changed IVR utterance. Issue #45 on the open-source callpilot project, opened 29 July 2026 and still open on 10 September 2026, logs eight real calls where the tool reported success and the menu did not always advance.
How long should the pause between digits be?
Start at 0.5 seconds. Vapi documents w for a 0.5s pause and W for a 1s pause on Twilio, Telnyx, Vapi numbers and BYOK SIP, and advises starting with 0.5s pauses and increasing only if digits are still missed. Retell controls the other end of the timing with a Pause Detection Delay that decides how long the agent waits after the IVR pauses before pressing; it defaults to 1000 ms and accepts 0 to 5000 ms.
Does it matter if the agent talks while it presses a key?
Both vendors say to keep it silent. Vapi’s prompt template instructs the assistant to avoid saying anything if using the dtmf tool at the same time, and Retell’s custom-LLM guidance says to have the agent stay silent for that response so it does not speak while pressing. On an in-band leg the reason is direct interference; on an out-of-band leg the likely reason is the IVR’s own speech detector. We could not locate a vendor page that states which mechanism applies.
More of how we work through telephony evidence like this sits in the Zian AI questions and answers hub.