Inspiration I had a pitch coming up and realised the only place I had practised it was inside my own head. Every sales team I have seen does the same thing: hand someone a playbook, let them read it, then put them on a call with a real customer. The first real objection they ever hear comes from someone who can actually say no.

Text chatbots do not fix that. Practising a phone call in a chat window removes the interruption, the pause you cannot fill, the thing you forget because you are listening. The medium is the difficulty. So the practice has to happen on the phone.

What it does You pick the kind of person you have to win over: the investor who interrupts anything vague, the buyer who has heard it all, the seller who just fired their last agent. Sparbird rings your own phone and plays them. They push back on what you actually said, not on a script.

When you hang up, it marks the transcript against what that person needed to hear. A point is only awarded where a line of the call proves it, quoted word for word. Where nothing proves it, the card says the call did not show it rather than saying you failed, which is why a result reads "3 of 4 landed" and never as a bare percentage.

Then it stops listing things and names the single thing that cost you most, with a sentence to say instead.

How we built it TypeScript and Next.js on Node, SQLite for storage, and the CALL-E SDK for the call itself. Each persona is a JSON file with its traits, its hidden state, its scripted objections and its rubric; a compiler turns that into one CALL-E task with a resultSchema derived from the rubric.

The scoring engine is plain TypeScript with no model call in the default path, which is why the same code runs from a terminal with no server at all. Seven recorded calls replay through the real compiler, the real scoring engine and the real judge, with the expected outcome of each written down so a change that quietly makes marking more generous fails the test run.

Challenges we ran into The phone did not ring for two days. Calls to an Indian mobile failed instantly, failure_code: 404, zero seconds. The first version of the error handling collapsed every CALL-E failure into one unhelpful sentence, so unsupported_region, insufficient_balance and a bad key all looked identical. Surfacing the real code was what made the rest solvable: the shared line allows one concurrent call and something was holding it.

The routing hint was following the wrong thing. Calls went out with region: "US" because that is what the persona file said, while dialling +91. Region has to follow the destination. Locale does not, because an American investor should still sound American when he rings you in Chennai. Those were two different questions sharing one field.

International audio is rough. CALL-E's own documentation calls its international pool test-grade, and it sounds like it. Nothing I could fix.

Accomplishments that we're proud of The marking cannot flatter you. Every rubric point and every flag must quote the transcript or it is discarded rather than shown.

And it does not trust the platform. CALL-E returns its own structured account of how a call went, and sometimes that account is not supported by the recording. When they disagree, Sparbird keeps the recording, says so on the page, and marks from what was actually said. One of the recorded test cases exists purely to prove that catch still works.

The safety story is structural rather than procedural. There is no consent flow because there is nobody to consent: the person consenting, the person dialling and the person answering are the same person.

What we learned A disclosure nobody hears is not a disclosure. The first call that connected put the line out at zero seconds; I picked up at nine. The one sentence that cannot be edited or removed had been spoken to a ringing handset, and the persona was two turns into character before a human was listening. No amount of replaying fixtures would have found that. It took a real phone.

More generally: a structured result is a report to check against the transcript turn it came from, not a fact to mark somebody on.

What's next for Sparbird Replace createAndWait with the webhook path, so a dropped connection cannot lose a call that already happened and was already billed. Real persistence instead of in-memory storage. A local line for regions where the international pool is poor. And team rubrics, so a sales floor can practise against the objections its own buyers actually raise rather than the ones I wrote.

Built With

Share this project:

Updates

Submission history