Telephony and the PSTN: your voice agent's hardest dependency is a network you cannot optimise.
You can shave two hundred milliseconds off time-to-first-token and still ship a phone agent that sounds worse than the one you demoed, because roughly half the turn latency, all of the audio quality and the entire question of whether the call connects at all live in a carrier path you do not control and cannot profile. Integrating with the phone network means accepting a fixed transport tax, treating your outbound number as a reputation asset that degrades under volume, and designing around the fact that a phone call carries no metadata channel — no auth header, no idempotency key, no structured result.
The transport tax is fixed, and it is charged before your model sees anything.
A voice agent on the web talks to a browser over WebRTC with a path you own end to end. A voice agent on a phone number talks through a chain — the caller's handset, their mobile or landline carrier, one or more interconnect carriers, your SIP trunk provider, your media server — and every hop adds delay you cannot tune. The latency budget has line items here that no amount of model work touches.
- Post-dial delay on outbound. Between your SIP INVITE and the far end ringing there is signalling across carriers, and it commonly runs one to several seconds. This is invisible in your traces because nothing of yours is running, and it is the first thing a user perceives as "the agent is slow to start".
- The jitter buffer is latency you are choosing to add. Packet arrival over the PSTN is uneven, so the media server buffers before playing out. A short buffer means clipped and garbled audio; a long one means every turn is slower. Somewhere between 40 ms and 120 ms is the usual operating range, and it is a genuine quality-versus-speed dial, not a bug to be fixed.
- Codec transcoding costs a pass. Interconnects still negotiate G.711 constantly. If your stack prefers Opus you are paying a transcode on both legs, and if a leg runs G.729 you have added compression artefacts on top of narrowband.
- 8 kHz is the ceiling, not the floor. Telephony audio is band-limited to roughly 300–3400 Hz. That is where sibilants blur and letters of the alphabet stop being acoustically distinct — the reason every recognition benchmark you read is optimistic for your channel. HD voice over Opus or AMR-WB exists but only survives when both legs and every carrier in between support it, which you cannot assume and should not design for.
The practical consequence is a budgeting discipline: measure the transport separately from the model, and measure it in production rather than in the lab. Instrument time from SIP answer to first inbound RTP packet, and time from your first outbound audio frame to the far end hearing it, and hold those as a floor. Optimising the model below that floor buys nothing a caller can perceive.
A test that costs an afternoon and changes the roadmap: run your existing eval set once over a real phone leg and once over WebRTC, and compare entity error rate and p95 time to first audio. Teams routinely find that most of their gap to the demo was the channel, and that the fix list they had written — a faster model, a shorter prompt — addressed none of it.
Your number is an identity with a reputation, and the reputation is the product.
This is the part that surprises engineering teams, because it has no analogue anywhere else in the stack: a phone number accumulates a trust score across carriers and analytics vendors, that score determines whether your calls are delivered, silently labelled "Spam Likely", or blocked outright, and it moves in response to how the called parties behave, not to anything in your code.
- STIR/SHAKEN attestation is a claim your carrier makes about you. A-level means the originating carrier both authenticated you and confirmed you have the right to use that number; B-level means it knows the customer but not the number's provenance; C-level means it is just passing the call along. Attestation is the input to downstream filtering, so it is the difference between "connects" and "goes to a labelled screen nobody answers". Getting to A is paperwork and provisioning with your trunk provider, not engineering — do it before launch, not after the connect rate collapses.
- Rotating numbers to escape a bad label is the classic mistake. It looks like it works for a week. Analytics vendors detect the rotation pattern itself and it is a stronger negative signal than the original complaints, so the second label arrives faster than the first. Fix the calling behaviour instead: fewer calls, better targeting, an opt-out that actually works.
- Branded calling is worth more than another 50 ms. Registering your number so the handset displays your business name lifts answer rates far beyond anything you can achieve inside the agent, and it is a per-carrier registration process with a lead time.
- Reputation is a shared resource across your tenants. If you serve multiple customers from a pooled number range, one customer's aggressive campaign degrades delivery for everyone else on the pool. Either isolate numbers per tenant or make calling-behaviour limits a contractual term, because the noisy-neighbour problem here is external and irreversible.
The metric to own is answer-seizure ratio segmented by carrier and number. Aggregate connect rate hides that one mobile carrier started filtering you on Tuesday, which is exactly the event you need to catch within hours rather than at the end of the month.
There is no metadata channel. The other side's IVR is your API.
Every integration pattern you rely on elsewhere assumes a side channel: a header for auth, a key for idempotency, a structured body for the result. A phone call has none of them. The entire interface is audio, and the only structured signalling available is a sixteen-symbol keypad.
- Send DTMF out of band and expect to be misheard anyway. RFC 4733 telephone-events are the reliable path; in-band tones survive G.711 and are mangled by compressed codecs. Also expect the reverse problem — your speech synthesis can produce artefacts that a far-end IVR scores as a keypress.
- Navigating someone else's phone tree is a retrieval problem, not a reasoning problem. The menu is stable for months and re-listening to it every call costs thirty seconds of dead time. Cache the tree per destination number, replay the known path, and fall back to listening only when the cached path fails. Treat the cached tree as data with a staleness policy, because the callee changes it without telling you.
- The outcome arrives as a sentence, so extraction is where correctness is decided. "Yeah we've got a couple left, I think" has to become a typed result. Do that with a structured extraction step over the transcript rather than letting the conversational model assert an outcome inline, and carry a confidence field that downstream code is required to handle.
- Nothing is idempotent. If your call drops after the far end agreed to something, you have no request ID to retry against and no way to ask whether the effect happened. The exactly-once machinery you would normally reach for has nothing to grip. The only real mitigations are asking a confirming question before the mutating step, and recording a durable local intent record before you place the call so a human can reconcile.
Worth stating plainly because it shapes the whole design: a phone call is a best-effort, unauthenticated, unacknowledged, non-repeatable channel. Any workflow that needs a guarantee has to obtain it somewhere else — an emailed confirmation, a booking system, a human check. Do not put the phone call on the critical path of anything you cannot reconcile afterwards.
Transfers are where the state dies.
Escalation is the one feature every phone agent ships and the one most likely to be implemented as a shrug. The telephony primitives make it easy to move the call and offer nothing at all for moving the context.
- Blind transfer (SIP REFER) hands off the leg and drops you out. Cheap, and it means the caller repeats everything. If the destination is busy or rejects, you are no longer in the call to recover — the caller just gets a failure.
- Attended transfer keeps you bridged until the human accepts. More expensive in trunk minutes and more code, but it lets you announce the caller, hand over a summary by voice, and abort back if nobody picks up. For anything where the caller has already invested five minutes, this is the one to build.
- Move the context out of band, before the audio moves. Write the conversation summary, the captured entities and the reason for escalation into the CRM or ticket keyed by call ID, then transfer. A human agent who sees the record as their phone rings is the entire difference between a good handoff and a restart, and it is the piece that handoff design keeps insisting on because it keeps getting skipped.
- Decide what happens to recording and disclosure across the boundary. A transfer can move the call into a different jurisdiction's consent regime or out of the scope of the disclosure you made at the top. Answer it once, in policy, rather than per-integration.
The legal layer is architecture, not paperwork you attach later.
Phone calls are the most regulated channel an agent can touch, and the rules are old, enforced, and expensive. In the United States the FCC's February 2024 declaratory ruling settled the foundational question: an AI-generated voice is an "artificial or prerecorded voice" under the TCPA, so every consent rule written for robocalls applies to your agent in full.
- Consent depends on the purpose of the call, and marketing is the strict tier. The FCC's rule requires prior express written consent for marketing calls using an artificial voice, and prior express consent — which can be oral — for informational ones. In February 2026 the Fifth Circuit held in Bradford v. Sovereign Pest Control that the statute's text requires only prior express consent for artificial-voice calls, which softens the position in Texas, Louisiana and Mississippi and changes nothing in the other forty-seven states. Build to the written-consent standard; a circuit split is not a design input.
- Statutory damages are per call and uncapped. $500 to $1,500 per violating call, multiplied by an agent that can dial continuously, is the reason the pacing and suppression logic belongs in the same fail-closed tier as your kill switch rather than in the prompt.
- Disclose identity and automation at the top of the call, every time. The FCC's rulemaking to define an AI-generated call and mandate specific disclosure language was still a proposal as of August 2026, so treat immediate disclosure as the safe default rather than waiting for the text. In the EU, the AI Act's transparency obligations already require that a person be told they are interacting with an AI system, and those provisions have been enforceable since 2 August 2026 — the same disclosure discipline covered in disclosure and provenance.
- Recording consent is a separate, state-by-state question. Two-party consent jurisdictions require the announcement before any recording begins, which means before your speech-to-text pipeline starts, which means it is a property of the media path and not of the prompt.
- Opt-out has to be honoured in the record, not just in the conversation. "Press 0 to opt out" that does not write to a durable suppression list shared by every campaign is a violation with a transcript attached. Wire the spoken opt-out and the do-not-call list to the same store, and make the suppression check a precondition on dialling.
None of this is optional infrastructure, and none of it can live in a system prompt — a model that can be talked out of a disclosure is not a compliance control. Encode consent state, suppression and disclosure as code paths the agent cannot bypass, exactly as outbound voice agents lays out.
Operate it like a network service, because that is what it is.
Once the agent works, the failures that follow are telecom failures, and they will not appear in the dashboards you built for the model. Your provider changes an interconnect, a carrier updates its filtering, a codec negotiation shifts, and the symptom is a quality metric drifting with no deploy attached to it.
- Monitor the media path directly. Jitter, packet loss and round-trip time per call, aggregated by carrier and by trunk. A rise in loss on one route is the root cause behind a week of "the agent keeps mishearing people" tickets, and no transcript-level metric will name it.
- Watch answer-seizure ratio and post-dial delay as leading indicators. Both move before your business metrics do, and both move for reasons entirely outside your deploy history.
- Keep a second trunk provider provisioned and tested. Trunk outages happen, failover configured but never exercised does not work, and the test is a scheduled synthetic call over the standby route — not a document.
- Record everything you are permitted to record, and keep the audio. The audio is the only ground truth; a transcript is already a lossy interpretation of it, and the eval set you actually need is recorded calls. Pair retention with a deletion policy, because call recordings are personal data in every regime that matters.
- Alert on dead air and on call duration outliers. A call that ran eleven minutes when the median is ninety seconds is a stuck loop billing you by the minute on both legs — one of the few places where an agent failure has a direct, linear, external cost.
If you do only one thing this week: pull your answer-seizure ratio and p95 post-dial delay segmented by carrier, then check your STIR/SHAKEN attestation level with your trunk provider. If you are not at A-level attestation, that single fix will move your connect rate more than any change you could make to the agent — and it takes a support ticket, not a sprint. The phone network is a dependency you integrate with and negotiate with, never one you optimise.
Related: realtime agent architecture for where the loop lives relative to the media path, voice agent failure modes for the catalogue this monitoring is trying to detect, and voice and realtime agents for the ground floor.