Skip to content
Evode Manirahari

Selected workSecondLine

SecondLine

A phone line that gets better after every call.

Answer the calls a small business misses, and make every call an input to the next version of the agent.

Stage
Hackathon build
Event
YC Voice Agents Hackathon
Status
Hackathon build, deployed
Timeline
One day, May 2026
Partners
Pipecat · Cekura · NVIDIA · AWS · Twilio
Surfaces
Phone line · WebRTC · owner dashboard
Where it stands
Built in one day at the YC Voice Agents Hackathon. Deployed and demonstrable; not a running business.

A small business that misses a call usually loses the customer outright. Most callers do not leave a voicemail and do not try again — they call the next shop on the list. For a florist or a clinic, the phone is a large share of revenue, and the missed-call problem is a revenue problem wearing a support-tooling costume.

SecondLine is the number a business forwards its missed calls to. It answers over a real phone line, recognises returning callers, takes the order through typed tools, and files a structured task for the owner. The part I cared about is the last one: it tests itself, scores the failures, and rewrites its own policy.

Call flow

Inbound

Phone call

Forwarded missed call over telephony

Automated test call

Real WebRTC session from the eval platform

Agent pipeline

Speech to text

Streaming, with turn detection

Model

Open-weight by default, provider-switchable

Typed tools

Eleven tools, one shared dispatch

Text to speech

Back out over the same transport

Business state

Customers, allergies, orders, transcripts

Owner task

Structured task filed for every order

Eval harness

Same dispatch layer as the live bot

Both inbound paths run the same code. A test call exercises production behaviour rather than a mock of it.

A real call and an automated test call take the same path through the agent. The evaluation harness and the live bot share one dispatch layer, so a test exercises production code.

The core decision: typed tools, not a trusted model

The model never holds business state. Customers, allergies, past orders, inventory, and owner tasks live in a backend module behind eleven typed tools and a single dispatch function. If the model wants to know what someone ordered last time, it calls a tool; it cannot recall, approximate, or invent it.

That one decision is what made the safety guarantees possible. Rules like the allergen guard live at the tool layer, below the model, so they hold regardless of what the model was persuaded to say.

Where safety is enforced

Model intent

“Add a lily bouquet to this order”

Tool layer validation

Allergen guard, low-confidence escalation

Business state

Written only if validation passes

Blocked

Caller has a recorded lily allergy. The write is refused and safe alternatives are offered instead.

Why below the model

The same rule in a prompt is a suggestion. In the tool layer it survives every future prompt change.

Validation sits between the model's intent and the business state. A blocked call returns a refusal and safe alternatives rather than failing silently.

The scenario that mattered

From the demo script — a returning caller, recognised by caller ID, with an allergy already on file.

Caller
Hi — same as last time, but no lilies, my mom's allergic.
Agent
Welcome back! I've got your usual — a dozen red roses, and I'll keep it lily-free for your mom. Want that for pickup?
Caller
Perfect, pickup at five.

This is the scripted demo scenario, not a captured production transcript. The same scenario runs in the evaluation harness as the allergy trap.

The self-improvement loop

Sixteen scenarios — new orders, repeat callers, the allergy trap, refunds, escalation, manager requests — run against a simulated caller. Each call is graded on six dimensions: task completion, correct tool use, memory accuracy, escalation behaviour, hallucination, and latency.

Failures are not just reported. The improvement engine classifies each one into a validation rule, an escalation rule, a prompt patch, or a memory update, writes it into the agent's policy file, and re-runs the suite to prove the change landed.

Before and after

Local evaluation harness, sixteen scenarios, open-weight model under test.

Pass rate
88%94%
Unsafe actions
10

The unsafe action was the agent about to add a lily bouquet for a caller with a recorded lily allergy. The loop wrote a validation rule that blocks it at the tool layer and proved it gone on re-run.

The first automated voice-testing run scored zero percent. Every transcript said the same thing: the main agent did not speak.

The production bug that only automated calls could find

That zero was not a scoring artefact. The deployed bot handled the Twilio websocket transport and local WebRTC, but not the Daily transport the hosting platform uses for WebRTC sessions — so on those sessions it silently constructed no pipeline at all and sat there. Local tests could not see it, because locally the transport was different.

Adding the missing transport case and redeploying took the agent from silent to fully conversational, verified by the same automated calls that caught it. Find, fix, re-run, on the real deployment.

Starter template versus what was built

The project began from the Pipecat Field & Flower starter. The split is worth stating plainly.

Already existedBuilt during the hackathon
Pipeline skeleton, speech-to-text and text-to-speech wiring, Twilio serializerBusiness brain with persistent caller-ID memory: customers, allergies, past orders, transcripts, owner tasks
Local WebRTC and Twilio transportsDaily transport support — the fix the automated testing surfaced
Hosted model and speech endpointsEleven typed tools and a shared dispatch used by both the live bot and the harness
Evaluation platform and its APISixteen-scenario harness, six-dimension grader, and the failure-to-fix improvement engine
Allergen safety guard at the tool layer, owner dashboard, provider switching, deployment, and project site

Evode’s contribution

What I built

Built during a single-day hackathon on top of a starter pipeline. Concretely:

  • 01

    Built the business backend and the eleven typed tools, with one shared dispatch function used by both the live bot and the evaluation harness so tests exercise production code paths.

  • 02

    Implemented the allergen safety guard at the tool layer, below the model, along with safe-alternative suggestions when an order is blocked.

  • 03

    Wrote the sixteen-scenario evaluation harness with a simulated caller and a six-dimension grader.

  • 04

    Wrote the improvement engine that classifies each failure into one of four fix types, patches the agent policy file, and re-runs to prove the change.

  • 05

    Integrated the automated voice-testing platform through its REST API — agent creation, scenario generation, live WebRTC test calls, and result retrieval.

  • 06

    Diagnosed and fixed the production transport bug that made the deployed agent silent on hosted WebRTC sessions.

  • 07

    Built the owner dashboard — task queue, transcripts, and the before-and-after pass rate — and deployed the agent behind a real phone number.

Honest limits

What remains unproven

  • No business has used it. This was a one-day hackathon build, and the evaluation results come from a simulated caller, not from real customers on a real line.
  • The pass-rate improvement is measured on the local harness against sixteen scenarios I designed. It is a real before-and-after on a fixed suite, not a claim about general voice-agent quality.
  • Owner SMS was built and wired but ran on a trial phone number that cannot send messages, so notifications surfaced as dashboard tasks rather than texts.

Lessons

What I took from it

Automated calls against the real deployment find what local tests cannot

The silent-agent bug existed only under a transport that local development never used. No amount of unit testing would have surfaced it; one automated voice call did, immediately.

Put the guarantee below the model

An allergen rule in a prompt is a suggestion. The same rule in the tool layer is a guarantee, and it survives every future prompt change.

A score of zero is information

The instinct is to assume the harness is broken. Reading the transcripts instead turned a scoring failure into a production fix within the hour.

Reference

Stack

  • Python
  • Pipecat
  • Twilio
  • WebRTC
  • SQLite
  • FastAPI
  • NVIDIA Nemotron
  • Claude
  • Cekura

Responsibilities

  • Business logic, typed tool layer, and persistent caller memory
  • Allergen safety guard enforced below the model
  • Sixteen-scenario evaluation harness with a simulated caller
  • Automatic failure-to-fix improvement loop
  • Multi-transport deployment and production debugging
  • Owner dashboard and task queue