Evaluating a form-filling voice agent that enrols mothers over a phone call
In India, almost every social benefit starts with a form, yet the people who need these benefits most are often unable to read or write. Someone needs to talk to them and fill the form on their behalf. Today that work falls to frontline health workers who enrol beneficiaries one at a time, a poor use of their stretched capacity. To solve this problem, we built FormBharo (“fill the form” in Hindi), a voice agent that fills a structured form over a phone call under tight latency and cost budgets. It is being piloted with ARMMAN, to enrol low-income, Hindi-speaking mothers in antenatal and postnatal care. Watch a demo call below:
One of the most common questions I get is “how do we build an evaluation dataset?”. In this post, I aim to answer that by walking you through the evaluation design for FormBharo, as a case study. Even though your use case is different, the process and approach are transferable.
TL;DR
- We explain why it is hard to perform this task reliably: calls often contain background noise; users alternate between Hindi and Hinglish and spell values in diverse ways, sometimes with pauses in between; they might not know the answer or refuse to answer; and the agent must reply quickly to feel like a real call, while staying cheap enough to run at scale.
- Under the hood, the agent listens to the caller, converts their speech to text, uses an LLM to extract the answer for each question on the form, validates it, decides which question to ask next, uses another LLM to generate the reply which is spoken back to the user.
- To evaluate this agent, we generated 960 simulated phone calls: LLM-generated user personas that mimic real users from our pilot and multiple realistic conversations for each one covering the most common scenarios; annotators matching our target user demographics record themselves speaking those conversations aloud, under different acoustic conditions (background noise, mic distance, speaking pace) to mimic real call environments.
- We used these simulated calls to test each component of the system separately:
- how accurate is the transcription?
- does the LLM extract the correct form values?
- does the LLM ask the right next question?
- does it end the call at the right time?
- Some of our key findings:
- Frontier models perform almost perfectly when transcription is perfect. But, once real transcripts are used, their performance degrades, worse for weaker models.
- Mistakes in data extraction per turn compound into significant performance drops at the overall form completion and even changes which models are the best performing. This is why end-to-end evaluation cannot be skipped.
- Good system design can make smaller, cheaper models viable by recovering some of their mistakes. This is critical for meeting our cost and latency needs.
- No single model is the best at cost, accuracy and latency at once. We share a simple method for finding the right model to deploy that trades off these 3 dimensions.
- Even though your use case is different, the same process can be applied for your evaluation too: public benchmarks can inspire but not replace use-case specific benchmarks, start by thinking through the evaluation design carefully as outlined in this post, use synthetic data to build your first evaluation set before you deploy your AI solution to real users, and evaluate every component of your agent along with the agent end-to-end.
Setting up the problem
Before we discuss the evaluation design, we need to understand why filling forms is hard, how FormBharo does it and why it needs to be evaluated.

Figure 1 illustrates the intended flow for how the form must be filled. It highlights the diversity a single form can contain: “name” is an open-ended field, district is restricted to a fixed set of values, answers to conditional questions (like, whether the user is pregnant) dictate which questions come next, the child’s date of birth must be a valid date in the past, the WhatsApp number must be 10 digits, and incorrect values could end the call prematurely.

Figure 2 shows how FormBharo works: A speech-to-text (STT) model transcribes the caller’s speech. An LLM (called EXTRACT), extracts the relevant form values. A few rules are applied to validate the extracted value (for example, is the phone number 10 digits? is the child’s date of birth a valid past date?). Valid values are stored in the form. A different set of rules picks the next question to ask, given the current state of the form. A second LLM, REPLY, phrases the question naturally, which a text-to-speech (TTS) model speaks back to the caller. If all the fields have been answered, the LLM decides to end the call instead.
A lot of things can go wrong here:
- Users often call from areas with background noises of various kinds. The trickiest one being multiple background speakers, which makes it hard to understand which user’s speech is relevant for the call.
- Many calls have background music with lyrics, which get transcribed too. Sometimes the noise is static but so loud that the user’s speech is inaudible even for us.
- Users speak in colloquial terms to answer questions and often alternate between Hindi and Hinglish.
- Speech-to-text models are known to perform poorly on accurately capturing proper nouns.
- For certain fields, they might answer instantly (for example, whether they are pregnant) but for other questions (like phone numbers or ID) they might have to look it up first and the agent needs to wait.
- Numbers could be spelled out in groups of 2-3 letters/numbers with pauses in the middle, instead of saying it in one go (for example, “2-3-4 4-2 4-2-3 3-9”). This is challenging because the agent needs to distinguish when a pause indicates that the user is done speaking from a pause that indicates there is more to come to ensure it can respond quickly for the former while wait for a bit longer for the latter.
- The agent also needs to maintain the language it has been instructed to speak throughout the conversation without switching to english, which the users won’t understand.
- If a user indicates they don’t know the answer, the agent needs to correctly decide when to prompt them to re-answer with a helpful nudge or skip the question entirely or end the call if the question is mandatory.
The agent needs to navigate these complexities while still being perceived as responding in real-time, which realistically gives a buffer of 1-2 seconds for responding. Coupled with this, given the scale of India and that India is a cost-sensitive market, every call should cost no more than Rs 2 per call at scale.
Evaluation design
Every potential error described above can be attributed to a specific component: the STT model, the extraction LLM or the reply LLM. We found several TTS models that sound good enough and so, exclude it from our first phase of evaluation.
We evaluate our agent at two levels. Unit tests score each component in isolation: predicted transcripts against reference transcripts, extracted form data against the expected values, quality of the agent’s response to the user and the ability to end the call at the right time. End-to-end tests chain the components to measure the end-to-end performance of the agent, mimicking how a real user interacts with it.
Dataset creation
We begin by defining 5 simulated user profiles (“personas”), each with fixed personal details, corresponding to the fields we intend to capture.
Synthetically generating calls using an LLM
For each persona, we generate several simulated calls with the agent. The expected flow for a call is the agent asking one question from the form at a time and the user providing the corresponding answer. Since the form has several conditional questions, it creates multiple branches that a user might traverse.
For example: “is pregnant → for 8 months”, or “is not pregnant → child’s name is Ram → child’s date of birth is 12 Feb 2026”
The user’s past answers decide which branch it follows. Each simulated call follows one branch. For example, the same simulated user produces one call in which she is pregnant and another in which she is not. In total, that produces 2×3×4×2=48 distinct paths through the form, one call per path: two pregnancy branches (pregnant or not), three branches for whether the calling number is linked to the clinic (linked, not linked and correct value provided, or not linked but not able to remember the linked number), four choices for whether the WhatsApp number is the same as the calling number (same, not same and answered, not same but unable to recall the WhatsApp number, cannot recall if they are the same), and two branches for the Aadhaar digits (answered or not known).
Across the 5 personas, this gives 5×48=240 calls.
We also account for 3 acoustic variations to ensure our dataset mimics the conditions in a public clinic: background noise (ambient chatter and nearby speakers), microphone distance (close or far, chosen at random), and speaking pace (fast or slow, chosen at random). Each call uses a single acoustic condition throughout (e.g. noisy environment or speaking slowly), since a caller’s environment does not change mid-call. Each of the 240 calls are recorded in environments with each of the 3 acoustic variations, in addition to the ideal acoustic environment. This yields a total of 240×4=960 calls in our dataset.


The value is generated once for each persona whereas the transcript is generated for each call with value as a reference under field-specific constraints defined with ARMMAN. For example, names and district names with phonetically hard spellings, a user unable to recall their phone number, etc. Both generations use GPT 5.5.
Audio dataset
The transcripts generated for all 960 calls are deduplicated to get 380 unique transcripts that need to be recorded since there is a significant amount of duplication across the calls for each persona. Each unique transcript is spoken by an annotator to produce a recording.
Five native Hindi speakers were selected to match the target demographic: all female, aged 18–35, drawn from two states (Uttar Pradesh and Maharashtra) to cover differences in accent and colloquialisms. Annotators were trained with sample recordings and recorded each answer under specific directives. For example, “record in a noisy environment, or keep the mic at least 25 cm away, or speak slowly”. A separate set of human supervisors listened to every clip to ensure the recordings met the requirements.
This gave us 380 audio recordings.
Unit Tests
Speech-to-Text
Word Error Rate (WER) is commonly used for comparing STT models. However, it is a poor metric for transcription quality on Indic languages and for agents: it counts every surface difference as an error (“nine” vs “9”), even when the meaning is unchanged.

So, we use LLM-WER instead: an LLM judge reviews every mismatch flagged by WER and classifies whether they are semantically equivalent or phonetically similar. The WER is then recomputed over the genuine errors.
Data extraction accuracy
To evaluate data extraction quality, we prepare unit tests at the turn level from every call, since every mistake happens at the turn level. Each test case contains the latest user response and the preceding conversation history as input the expected form values as the ground truth.

The form values extracted by the agent are compared with the expected form values to compute the extraction accuracy for that test case as shown below.

Fields like numbers, dates, and booleans are compared exactly with the expected values. But open-ended fields like names are harder to judge since the expected value can have many phonetic forms (“Lakshmi” versus “Laxmi”). So, we use a binary LLM judge instead to evaluate the extraction as shown below.

The LLM judge compares the agent’s extracted value against the criteria given to it and evaluates whether the response passed the criteria or failed.
To align the LLM judge, we compared its judgements with our review and iterated on the prompt until it was completely aligned with us. The accuracy of the LLM judge is validated on a separate unseen test set to avoid overfitting. Since the evaluation task for the LLM judge is narrow, achieving 100% alignment was possible.
A conversation can have many turns. Each turn is converted into a test case. To ensure that every error can be attributed to the agent’s mistake in that turn, the agent is assumed to respond perfectly to all previous turns in that test case. So, if a test case has 10 turns, 5 messages from the user and 5 responses from the agent, only the last response of the agent is evaluated, while the previous 4 responses are kept 100% accurate. Deduplicating tests with identical inputs across all 960 calls yields 1,880 unit tests. We report the mean extraction accuracy over all of them.

Response quality
Similarly, we prepare unit tests from the calls to measure response quality, with two key differences. If you recall, the architecture of FormBharo has a rule-based layer in between the extraction and reply generation steps (Figure 2) which decides which question to ask next. Each test case additionally receives a tool call carrying the decision of the rule-based layer as an input too. So, if the rule-based layer decides that the “district” must be asked then, that decision is sent as input to the REPLY LLM, along with the conversation history. Figure 10 shows one example corresponding to the example for extraction accuracy shown in Figure 6.

Secondly, REPLY LLM either generates the next question or ends the call given the form state. The decision to end the call is recorded as a tool call and evaluated using exact match as shown below.

For every other case, we need to evaluate the generated reply. We use binary LLM judges to do that.
Each reply is graded across 6 independent dimensions:
Correctness: Does the response contain the right question?
Hindi adherence: Is the response in Hindi?
Conciseness: Is the response just one line?
No acknowledgment: Does the response exclude any acknowledgements (like, “Got it”)? No acknowledgements in the response is considered a success.
No Value Echo: Does the response echo the user’s answer back to them?
Script Fidelity: Does the response phrase the question correctly?
We define an LLM judge for each dimension, which independently evaluates whether the agent’s response passed or failed the criteria for that dimension.

Using separate LLM judges for evaluating different dimensions independently helps us easily inspect where a mistake is, instead of having to read the reasoning for each test case to figure it out, as shown below.

Each of the LLM judges was calibrated by comparing our labels on a subset of the data. The figure below shows one example of how we improved the agreement of the LLM judges iteratively.

An accurate response either passes all the LLM judgments or ends the call at the right time. We report the mean response accuracy. Similar to extraction accuracy, deduplicating the tests across the 960 simulated calls, each call producing many tests, yields 1,880 unit tests: 920 require a reply, while the remaining 960 check whether the call is ended correctly.
End-to-end testing
Testing components in isolation is not enough. For the unit tests above, we assume that their inputs were perfect. For extraction accuracy, that means assuming the transcription was perfect. For response accuracy, we additionally assume the extraction was perfect as well.
In practice, an end-to-end agent chains the components together, so the output of one feeds into the next. This means that errors propagate across components too. An incorrect transcription affects extraction accuracy. Also, we care about how the agent performs on the overall task of form completion, not just a single turn.
We make the following changes to test our agent end-to-end:
- We replace the reference transcripts in the unit-test inputs (which assumes perfect transcription) with transcripts produced by the STT models. Thus, transcription errors propagate to the LLMs.

- We compute form completion accuracy to measure the overall task performance using the mapping for every simulated call to its corresponding unit tests at each turn. For each call, starting from an empty form state, we accumulate the values extracted for each turn’s unit test on top of each other sequentially. This gives us the predicted form at the end of each call. Comparing this against the expected values gives the form-completion accuracy: the fraction of form fields captured correctly at the end of the call.

To quantify the impact of this error propagation, we compute all the metrics using both the reference transcripts as input (perfect transcription) and the transcripts produced by each STT model.
Dataset summary
This gives us our final benchmark dataset of 380 audio recordings, 3,760 multi-turn conversation tests across 960 simulated calls, which we call FormVoiceAgentBench.
Findings
Transcription quality
The table below shows the comparison across 5 STT models. For all the columns, lower values are better.

It shows that WER and LLM-WER disagree: Nova-3 (Deepgram) has the best WER yet the second-worst LLM-WER. This is even more pronounced because our reference transcripts are in Romanized Hindi whereas the predictions are in Devanagari. Following our reasoning before, we rank models by LLM-WER, which is robust to the script differences. Chirp 3 (Google) has the best LLM-WER but costs at least twice as much as any other model, while Scribe v2 performs close to Chirp 3 at a fraction of the cost. GPT-4o-transcribe (OpenAI) is the least accurate. Scribe v2 (ElevenLabs) and Saaras v3 (Sarvam) are close to each other, both in terms of quality and cost. A detailed analysis of the transcription mistakes will be done in a separate post but you can see the full evaluation results along with the audio samples here.
Calibrate is an open-source AI agent evaluation platform built for domain experts and non-profits. We built it because none of the existing evaluation platforms sufficiently addressed our evaluation needs and were often too hard to use, without an explicit focus on evaluation. All the evaluations covered in this blog post were run on Calibrate.
Turn-level extraction accuracy


Table 2 compares various LLMs on per-turn extraction accuracy. Our observations:
- When perfect transcription is assumed (the Reference column), frontier models achieve almost perfect accuracy: GPT-5.5 leads at 99.79%, with Gemini 3.5 Flash (99.36%) and the two Claude models (99.15%) just behind.
- When real transcripts from STT models are used, we notice a performance drop. For transcripts generated by the STT model of ElevenLabs, the median drop in performance is modest (0.42 percentage points [pp]). But for the STT models by Sarvam and Deepgram, the drop is more significant (3.14 points). Weaker models degrade much more: GLM-5.1 collapses by 35 points with Scribe v2 transcripts.
- Using real transcripts also changes the leaderboard. The best extraction accuracy drops to 98.94%, achieved by Gemini 3.5 Flash and Claude Sonnet 4.6, with ElevenLabs STT, compared to 99.79% by GPT 5.5 when perfect transcription is assumed.
End-to-end form completion

Similar to extraction accuracy, Table 4 shows the form-completion accuracy across all the LLMs being tested. A few interesting observations:
- The best model end-to-end differs from the best model per-turn: Under perfect transcription, GPT-5.5 leads extraction accuracy (99.79%), whereas Gemini 3 Flash and Gemini 3.5 Flash tie for the highest form-completion accuracy at 100%.
- The harness recovered the turn-level extraction errors: Gemini 3 Flash was #8 on the per-turn Reference leaderboard (Table 2) but became #1 on the form-completion leaderboard. Per-turn extraction accuracy evaluates the raw output produced by the LLM, whereas form-completion evaluates the values ultimately stored in the form after the rule-based layer (Figure 2) processes it. All the extraction errors for this model arise from a type mismatch: a numeric field being returned as a string by the LLM. The rule-based layer normalizes it before storing the value, preserving 100% form-completion accuracy. The agent harness around the LLM enabled a smaller model to perform better end-to-end even if its per-turn inference was not perfect.
- Form completion accuracy degrades significantly with real transcripts: median form-completion accuracy drops by 7.67 percentage points with Saaras v3, 7.38 points with Scribe v2, and 13.56 points with Nova-3 (Table 3), compared with median per-turn extraction drops of only 0.42–3.14 points. So, although the rule-based layer recovers some extraction errors, uncorrected errors can accumulate across turns to produce a larger degradation end-to-end.
Response quality

Similar to the previous sections, we saw almost perfect performance by frontier models when transcription errors are ignored but some degradation when real transcripts are used and errors are propagated across the components.
Selecting which models to deploy
We need to choose 3 models for deployment: the STT model, the LLM that extracts form values and the LLM that generates the reply for the user. From Table 3, since Scribe v2 causes the least degradation in performance, we select it for deployment.
For selecting the extraction LLM, we compare the form completion accuracy on the Scribe v2 transcripts. First, we discard the models that fail to meet our deployment constraints: latency below 5 seconds and form-completion accuracy above 90%. This leaves behind six candidates, all of which are on the Pareto frontier: meaning, none of the remaining models is worse than every other model on all 3 dimensions at once: cost, latency or accuracy.
So, we rank the models instead by assigning weights to cost, latency and accuracy such that it reflects their relative importance for our use case. Changing the weights gives the best model accordingly.
You can view the full comparison of the extraction LLMs on the Scribe v2 transcripts here. You can see the output of every LLM we tested across all the tests cases from the Results tab by following the link, as shown below.

The Model selection lets you see the impact of changing the individual weights on the leaderboard as shown below.
Note: the evaluation run on Calibrate shows the per-turn extraction accuracy, not the form completion accuracy, since it evaluates the raw LLM outputs only. The form completion accuracy is calculated deterministically from the turn-level extractions separately and the best extraction model (Gemini 3.5 flash) is selected with form-completion accuracy as the accuracy metric.
Similarly, the full comparison of different LLMs for reply generation on the Scribe v2 transcripts can be seen here. In this case, GPT 5.4 mini comes out on top for all the weight combinations where the weight for accuracy is < 0.7.
Insights
Summarising the key takeaways from this case study on evaluating our voice agent:
- You need to methodically think of the evaluation design specific to your agent and use case. Existing public benchmarks (like this one) can serve as inspirations but every agent requires bespoke evaluation.
- Synthetic data can provide a great starting point. If you operate in highly sensitive domains, you don’t have the luxury to deploy your AI system first and then, start building your evaluation dataset using real user interactions. You need to gather enough confidence before deployment. LLMs can be used to create high-quality evaluation datasets. But you need to do this carefully and with a sound evaluation design in place.
- If your agent is composed of multiple components, a good evaluation system would measure both the accuracy of each component and the agent end-to-end. In the example above, we saw how transcription errors caused degradation in extraction accuracy once the components were chained together.
- It is important to measure the overall task-level performance of your agent. For us, extraction errors in each turn compound into a large performance drop in form-completion accuracy.
- Your agent harness, or, simply put, how you orchestrate different models to create your agent, matters a lot. The right harness can overcome limitations of the underlying models to enable smaller, cheaper models to perform equally as well as larger, costlier models. Our rule-based engine recovered minor extraction errors by Gemini 3.5 Flash at the turn level to produce a much higher form-completion accuracy end-to-end, enabling it to jump from #8 in the turn-level extraction leaderboard to #1 in the form-completion leaderboard.
- Any realistic deployment cares about 2 other metrics beyond accuracy: cost and latency. Deployment constraints can be applied to filter out irrelevant models. The Pareto frontier helps you further narrow down the list of candidates. One way to make a concrete decision is to assign weights to cost, quality and latency, that reflect their relative importance. Varying these weights to match your deployment requirements will produce the best model tailored to you.
Next steps
We are already in the process of creating a second version of the benchmark covering more linguistic and acoustic variations to replicate the challenges faced during our pilot more closely while expanding to more local languages beyond Hindi (Marathi, Telugu, and Kannada). One of the limitations of the current dataset is that the audio recordings are read aloud from scripted transcripts, not captured from spontaneous, real calls.
Our current evaluation design is tied to the current architecture. To make the evaluation more general purpose and architecture agnostic, we are setting up end-to-end voice simulations with realistic user personas where any voice agent, irrespective of its architecture, can be evaluated. Here, one voice agent mimics the user and converses with the form-filling voice agent built by FormBharo and its performance is evaluated at the end of each call. The biggest hurdle here is ensuring the simulated users can accurately replicate the challenges of a real call. One such challenge is background noise. To handle that, we are working on simulating different types of background noise (music, multiple speakers, car horn, dog barking, etc.) that we have noticed from our pilot and adding it to the simulated calls. Early results indicate that the agent’s performance drops when the simulated background noise is injected into the call. Ironically, this is promising because it gives us confidence that we can create realistic simulations.
We have pilots with other non-profits and government partners in progress now. But, manually creating the evals for each form is not scalable. So, we are preparing a recipe to automatically generate synthetic evaluations for any form using the framework described above, by expanding it to make it more general purpose.
Although we compute form completion accuracy, certain fields carry more importance than others. So, computing field-level form completion accuracy will give a clearer picture of where the issues are and whether the agent is ready for scale.
Depending on the call duration, the cost per call ranges from ~Rs. 4 to ~Rs. 20 today, the bulk of which comes from LLM API calls. Although accuracy and latency are our biggest concerns at present, we will work on identifying ways to reduce the cost to meet the milestone of ~Rs. 2/call without compromising on latency or accuracy.
Finally, we are continuously monitoring all our deployments through the automated traces on Calibrate so that users can easily report errors and every error can be converted into either a structured unit test or a simulation.
Closing notes
The full implementation details can be found in our preprint here: https://arxiv.org/abs/2608.06027
FormBharo is also publicly available now. You can create a voice agent for your forms at: https://formbharo.artpark.ai
If you have any feedback to share with us or if this post helped you think about the evaluation for your use case, please drop me a note.
If you find this type of work interesting or want to transition into the social sector, we are hiring Voice AI engineers, Developer Advocates and ML engineers in our team.