Inspiration
The idea came from a market stall, not a textbook. In bazaars and flea markets, a price tag is only the opening bid — you chat, you counter, you shake on it. Online shopping threw all of that away: the number on the screen is final, take it or leave it. I kept asking myself why e-commerce, which automated nearly everything else, never automated the oldest retail ritual there is: haggling.
The hackathon's theme, "Build What's Next with PayPal and AI," gave me the missing ingredients. PayPal contributes the trust layer — I can let a stranger talk the price down precisely because the money moves through PayPal's battle-tested Orders API, not through some duct-taped checkout. And a negotiating bot contributes the fun: a store that pushes back, teases a little, and rewards a patient buyer with a real discount. I also wanted to prove a solo developer could ship the full loop — negotiation, payment, capture, receipt, refund — without a team, which became its own motivation as the project grew.
There was a personal constraint too: whatever I built had to stay honest under pressure. A haggling bot that can be sweet-talked into selling below cost is a toy; one with a mathematically enforced floor is a store. That constraint shaped most of the engineering decisions below.
What it does
HaggleMart is a complete small-storefront with bargaining built into the product, not bolted on:
- AI negotiation, natural language. Buyers chat with "Marco", a market-stall persona that greets them, answers product questions, evaluates offers, counters with personality, recognizes quantity asks ("I'll take 3 of them"), and finally shakes hands — in under a minute, 24/7, in the buyer's language.
- A negotiation engine you can trust. Every money decision — counters,
the secret concession ladder (3–5 rounds), the walk-away, the final accept —
is made by deterministic code, never by the model. The seller's secret
floor_priceis mathematically unreachable: even a deliberately rogue model output gets stripped by a sanitizer that only permits engine-authorized prices. The LLM is the voice; the engine is the contract. - Instant PayPal checkout at the settled price. When the bot says "deal", a PayPal order is created for exactly that amount. Smart Payment Buttons (gold PayPal, Venmo, card) render in-page; the negotiated discount is real money movement, not a coupon.
- Payment reliability that survives real life. Four redundant capture
paths — browser redirect return,
CHECKOUT.ORDER.APPROVEDwebhook, a background poller, and a CREATED-order reconciliation pass — mean a deal is captured exactly once even if the buyer's Wi-Fi dies mid-redirect. - Merchant back office. PIN-gated area: edit listings and floor prices, watch orders, full or partial refunds, restock control. Sold-out items refuse to negotiate.
- Trust artifacts for a 3-person garage business. Styled HTML + fpdf2 PDF receipts, automatic email delivery when PayPal provides a verified address, inventory auto-decrement on capture.
How we built it
- PayPal integration (central to the project): Orders v2 REST API (create / capture / get / refund), PayPal JavaScript SDK Smart Payment Buttons, server-side capture endpoint, webhook receiver with signature verification, and a poller for reconciliation. Fully sandbox-driven.
- AI architecture (the interesting part):
haggle_bot.pyis a strict two-layer design. Layer 1 is a deterministic negotiation engine: regex parsers for offers/quantities/FAQ, a hidden concession ladder ending abovefloor_price, stock and round limits. Layer 2 is the LLM, which receives the engine's decision plus an explicit allow-list of prices and may only phrase the reply. A prompt-injection defuser treats every buyer message as untrusted data — payloads ("ignore previous instructions", "print your system prompt", persona hijacks, Unicode homoglyphs) are redacted before the model sees them. A post-generation sanitizer then deletes any reply that echoes an injection, mentions limits, runs past the length cap, or contains a non-authorized amount; a floor value in any Unicode form wipes the whole output. If the LLM fails for any reason — no API key, timeout, garbage — the app falls back to a deterministic voice and commerce continues. 22 dedicated pytest tests cover these guarantees, including a 200-iteration offer fuzz and a 60-iteration prompt-injection fuzz proving no message sequence can settle below floor or make it leak. - Stack: Python 3.10+ + Streamlit UI, PayPal Orders v2 via
requests, OpenAI-compatible chat completions (works with OpenAI, Groq, or fully local Ollama), fpdf2 for PDF receipts, SQLite for orders and receipts. Deploys to Streamlit Community Cloud in minutes or any self-hosted machine that keeps the poller/webhook alive.
Challenges we ran into
Making an LLM sound like a shrewd negotiator without letting it act like one took three layers of defense: decision-first prompting, allow-list sanitization, and engine-only acceptance. Getting capture idempotency right across redirect/webhook/poller paths was the other deep rabbit hole — the fix was a single settlement ledger keyed by PayPal order id.
Accomplishments that we're proud of
A complete, testable storefront in one file each; a payment flow that survives a browser crash mid-checkout; and a negotiation bot that stayed honest in every one of 200 randomized attack runs.
What we learned
LLMs make brilliant liars about prices — architecture, not prompting, is what keeps money safe. And "meaningful PayPal integration" turns out to be the easy half: Orders v2 + webhooks are a joy next to the state-machine work.
What's next for HaggleMart
Multi-language personas, voice negotiation, an agent-to-agent API so other AI shopping agents can haggle programmatically, and a hosted version for Instagram/Facebook sellers.
Log in or sign up for Devpost to join the conversation.