
How I won Ramp's Builders Cup with an AI that haggles with car dealers
We gave a voice agent real market data, a negotiation playbook, and a strict no-hallucination rule, then let it call dealerships live. A four-hour build story from the Ramp Builders Cup, where the judges tried to out-haggle it.
Lowball is an AI agent that calls car dealers and negotiates the price down for you, live. Gabe Meredith, a friend of mine from Armada at Cornell, and I built it in about four hours at the Ramp Builders Cup, Ramp's inaugural hackathon in NYC, where it took first place on the main "Save Time. Save Money." track.
The premise: the average used car carries thousands of dollars in dealer markup, and most of it is negotiable. But the dealer haggles ten times a day and you do it once every six years. Lowball flips that asymmetry. You describe the car you want in one line ("F-150 under $35k in New Jersey"), it finds real listings, ranks the sellers by who is most likely to cave, and a voice agent makes the call.
More: GitHub repo · Live site (browse and search; outbound calling is disabled outside the demo) · LinkedIn post
We didn't start with cars
The morning of the hackathon we had a shortlist that included a QR-code party negotiation game and "Bill Assassin," a voice agent that negotiates your bills. I'd already committed a full build plan for Bill Assassin, including the hardest part: a hand-rolled audio bridge between Twilio and the OpenAI Realtime API.
Two things killed it. First, an iMessage debate with Gabe landed on used cars as the bigger, more demoable savings story. Second, and more importantly, we realized we could delete the audio bridge entirely: Vapi handles telephony and speech-to-speech as a service, which meant the riskiest component of the whole build simply stopped existing. Owning less plumbing meant we could spend the four hours on the parts that make the demo interesting: the data and the negotiation brain.
Picking cars also settled an ethics question cleanly. We target dealerships, not private sellers. Dealers publish their phone numbers, a price inquiry is normal business traffic, and negotiation is expected in car sales. Cold-calling private individuals with an AI voice is regulated robocall territory, so we never touch them.
The negotiation brain
The agent runs a playbook, in order: open as a genuine buyer naming the exact car, anchor low with a comparable listing, lean on days-on-lot ("this has been listed a while, I'm ready to move today"), play the cash-buyer-today card, and only then threaten a polite walk-away. Function tools drive everything you see on screen: log_offer fires every time the dealer names a price, accept_offer closes the deal, end_call hangs up. It accepts only at or below a target price, around 91% of asking.
The rules that made it feel credible instead of scammy:
- Zero hallucination. The agent may only cite facts from its briefing: the real listing, real price-cut history, real comps. Nothing invented, because a dealer will call out a fake comp instantly.
- Cheaper-only comps. Only cars actually listed below the asking price count as leverage, and comps are model-scoped (same model, ±2 years) so the anchor survives scrutiny.
- A pushback ladder, not a trigger finger. Dealer games and junk fees get three escalating pushbacks before any walk-away talk, and the agent threatens the walk but never executes it mid-negotiation.
The data behind the calls is Gabe's Python scraper: 206 real cars.com listings, every one with a dealer phone number, full price-drop history, and the same-model market median. A ranking engine scores "negotiability" from price versus market, mileage, and how many times the listing has already been cut. The agent walks into every call armed with exactly the leverage a sharp human buyer would want.
The bug I didn't see coming
My favorite bug of the day: the text-to-speech layer read "$12,500" aloud as "one dollar and two five zero zero." Numbers are the entire product in a negotiation, so this was fatal. The fix was a spokenUsd() helper that converts every price to words ("twelve thousand five hundred dollars") before it reaches the voice, plus a prompt rule that outright forbids digits and dollar signs in speech.
Getting a phone line at all was its own saga. Vapi's free number turned out to be SIP-only, buying one through Vapi returned a 403, and my fresh Twilio account got stuck in a compliance hold. Gabe bought a Twilio number on his account, we imported it into Vapi via the API, and learned along the way that A2P 10DLC registration regulates SMS only, not voice calls, and that Twilio trial accounts will only dial verified caller IDs. The first live negotiated call went through my own verified cell, transcripts streaming from Vapi through the webhook into the dashboard.
A license plate instead of a search box
The frontend had one job: not look like every AI-generated hackathon dashboard. The landing page is a three.js night scene, a crane shot down onto a hero car, ending zoomed on a New Jersey license plate. The plate is the search input, a DOM layer projected onto the 3D scene, so you type "Jeep Wrangler, 2018+, under $30k" onto embossed metal. Bone paper, ink black, NJ-plate yellow, zero border radius, IBM Plex Mono.
One free-text line goes through a single cheap OpenAI structured-output call that extracts make, model, years, price cap, and zip. Entity extraction only, never URL synthesis, so the model can't hallucinate a listing slug that doesn't exist. Results come back as ranked cards with an honest "why this one will cave" line built only from real fields.
The demo that won it
Judging was science-fair style, and instead of showing a recording we handed the judges the phone. They played the dealer against the agent in a real call, trying to make it fold. It stonewalled one judge into naming a number, cited a real comp against another, and turned the booth into a game of who could beat it.
That's the takeaway I'm keeping: the best hackathon demo isn't something judges watch, it's something they can lose at.
Credits
Lowball was built by Gabe Meredith (cars.com scraper, dataset pipeline, and the Twilio rescue) and me, Arsh Singh (Vapi call flow, negotiation prompt and tools, webhook-to-dashboard wiring, and the three.js frontend). Thanks to Ramp's Emerging Talent team for the event, and to Cursor, OpenAI, and Chelsea Commons for sponsoring. The code is on GitHub, and the site is live at lowball.arshsingh.net.