Audit voice agents built on Retell

Evidova reads the call Retell has already finished, and scores what the agent actually said.

What it catches

Retell hands you the transcript, the recording and its own summary of the call. None of that tells you whether the agent did the job you built it for. Evidova reads the same transcript and scores it against the checks you approved: whether the agent answered what was asked, whether it said it was not a person when asked, whether it quoted a price nobody gave it, whether it handed the caller to somebody, and where the caller gave up.

Connect Retell

  1. In Evidova, open Setup, choose Retell, and paste your signing secret.
  2. Copy the URL we generate.
  3. In Retell, set it as the webhook URL on your agent.
https://app.evidova.com/ingest/webhooks/retell/<your-token>
The token in the path names your workspace, and the secret proves the request is Retell's. A request that fails that proof is refused with a 401 and recorded, not dropped quietly.

What we read from Retell

call.call_idThe call's identity. Required, and every turn is filed under it
call.from_number, call.to_numberThe caller's number on a telephone call, so repeat calls from one caller group. An inbound call uses from_number, an outbound one uses to_number, and a web call falls back to call.call_id
call.start_timestamp, call.end_timestampWhen the call started and when it ended
call.transcript_object[].role, .contentThe turns. Roles agent, user and transfer_target, and any other role is kept as a note rather than scored as speech
call.transcript_object[].words[].start, .endWhen each turn began and finished, as an offset into the recording
call.latency.e2e.values[]Retell's own measured reply time for each agent turn. Read the trap below before you trust it
call.recording_urlAudio, for the latency and dead-air checks. We copy the bytes while the webhook is being handled, because that link expires
call.disconnection_reasonHow the call ended, kept on the end of the call
call.transfer_destinationWhether a person took over. A destination is a number or an endpoint a whole team answers, so we record that somebody human did and deliberately not who
call.agent_versionWhich build of the agent spoke

What we ignore, and why

Retell posts chat_started, chat_ended and chat_analyzed as well. We skip all three on purpose: this connector reads calls, and the shape of the chat payload is not one we have confirmed. The four transfer webhooks are kept, but as a note on the call and not as a turn, because nobody spoke in them. call_ended and call_analyzed both carry the whole transcript, so whichever lands first produces the turns and the second adds nothing. Anything outside those lists is refused with the event name in the note and lands in the dead-letter ledger, so a change on Retell's side becomes something you can query instead of coverage nobody noticed going missing.

One trap worth knowing

Retell never states outright when a turn happened. We build it from the first word's offset into the recording, added to the start of the call, which is close but only as good as what the transcriber reported. Retell also sends a precise reply time for each agent turn in latency.e2e.values, and lines those values up with the agent turns by order alone, which is a match it does not promise to hold. So we use them only when the count of values equals the count of agent turns exactly. One value missing and the whole call keeps the word offsets, because half a call on the precise clock and half on the rough one is worse than a call that is consistently approximate.

What Retell gives us

Channelvoice
AudioYes
TimestampsMilliseconds, on Retell's clock
DeliveryWebhook, push
RetriesRetell retries

Read next

This page as markdown