Skip to main content
A voice agent has less time than any other agent. The caller hears silence while the prompt is built, so the context has to be ready before the first word, and every lookup during the call has to fit inside a spoken turn. This guide wires a voice agent to Niadra from the moment the phone rings to the moment the call ends: context during the ring, history lookups sized for speech, the call metadata that proves who is calling, the transcript in two passes and the handoff to a human. We follow Marina Souza. At 2:02 pm she complained on WhatsApp that the technician never showed up. At 2:06 pm the billing agent posted a $40 credit on invoice 0823. At 2:07 pm she calls. The voice agent answers already knowing both.

What the voice agent receives

The voice view is the shortest channel view. It carries who the caller is, what is still open, what other agents just did and the history highlights that change the conversation, sized so the agent can read it before it speaks. Anything that happened on another channel after the pack was compiled arrives in live, and it goes at the end of the prompt. The SDK keeps its own time budget, independent of the voice platform. If the budget runs out, the call carries on and the agent speaks with what it has.

Steps

1. Read the context while the phone rings

Start the conversation as soon as your voice platform reports the inbound call, and ask for the context in the same handler. By the time the call is answered, the pack is in the prompt. The calling number is the subject; the platform call id is your conversation_id.
With conversation_id, the server pins the pack: every turn of this call gets the same bytes, so the model provider keeps the prompt prefix cached. What changes during the call (a new action by another agent, a message on WhatsApp) comes as a delta and as live turns. In Python, append ctx.turn_block at the end of each turn; in TypeScript, append ctx.suffix.
In TypeScript, a conversation on channel voice uses the voice view by default. Pass target with the provider and model of your speech agent when you know it, so the pack is sized for that model’s prompt cache.

2. Send the call metadata

The verification level is what the call proved, never a guess. Network attestation from the carrier (STIR/SHAKEN and its equivalents) is the strongest signal a call carries before any question is asked. Level A maps to V2; levels B and C map to V1. A hidden caller id or a PBX number is V0 or V1, and the agent identifies the person by conversation. Send the call details in the voice block of the first event. A call often has two ids, the platform id and the trunk id: put the second one in conversation_aliases so both resolve to the same conversation.
The effective level is always the lowest of three values: what you requested, the ceiling of your source and what the conversation proved. An automated agent source has a ceiling of V2. The response tells you what happened in verification.requested, verification.effective and verification.reason.

3. Let the agent look up the history, sized for speech

The pack answers the most common question on its own: its “From the history” section says whether this happened before and how it was settled. When the caller brings up something older, the agent searches. Bind the tools to the caller in your code, so the model chooses the query and never the customer, and use the voice budget.
A search called from a voice conversation returns up to 300 tokens, cut by value, with a recurrence block when the query matches a category: “second missed visit in 12 months; last time, a $40 credit”. Literal transcript excerpts are never returned to a voice audience.

4. Record what the agent says

Capture the agent turns as they happen. Call mark_injected() (Python) or markInjected() (TypeScript) each time the pack goes into the prompt: the agent’s next turns and actions then carry a context_stamp with the ETag of that pack and the moment it went in, which is how the context use measurement tells a late context from an unused one. If your agent is built on the OpenAI client, wrap() in either SDK injects the pack, stamps it and records the answers for you.

5. Hand off to a human, warm

When the caller asks for a person, record the handoff before the transfer. With mode="warm", the receiving desk reads the brief view: a short, spoken-length briefing your platform can whisper to the attendant. The attendant keeps working in the tool your company already uses; the context reaches it by API, webhook or MCP.
A transfer whose destination never reads the context within 10 minutes shows up as a handoff without reading in the measurement.

6. End the call, then send the final transcript

End the conversation the moment the call hangs up. In Python, leaving the with block does it; you can also call end(). That closes the session at once instead of waiting for inactivity, so the derived memory is ready in under a minute.
Voice platforms deliver in two passes: the real-time transcript during the call and a better one after it. Send the post-call transcript as new events on the same conversation_id, with their own idempotency keys. Late data is never an update: it marks the conversation for a new extraction, and the episode gets a new version. Turns with speech-to-text confidence below the threshold do not count as questions or claims in the measurement.
The audio itself never travels inside an event. Upload the recording with upload_media() in Python or uploadMedia() in TypeScript, passing the caller as subject so erasing the customer also erases the recording, and put the returned media_ref in voice.recording_ref or content.media_ref, with its SHA-256. Over HTTP, POST /v1/media/uploads returns the URL and the exact upload_headers to send with the PUT.

Next steps

Context and views

layers, pinning, live turns and delta.

Identity and verification

how V0 to V4 are proven and capped.

History navigation

search, timeline and open, with budgets.

WhatsApp agents

the other side of the 2:02 pm message.