Sold!
Short description
Take a photo of what you want to sell. Sold’s agents identify it, price it from real comps, write and post the listing, verify it’s actually live, then negotiate with buyers — without ever showing your floor price.
You know when you have something you don't use anymore and think, "I should probably sell this"?
And then you don't.
Not because you don't want the money. Listing is annoying. You have to figure out what the thing actually is, dig up what people pay for it, take photos, write copy, put it on a few marketplaces, and then live in the inbox for a week.
Sold is built around that exact pile of work. You take a picture, review what it finds, and it runs the rest: identify the item, price it from real comps, write the listing, post it, verify it's actually live, watch the inbox, and negotiate with buyers without giving away your floor.
What it does
- Identify. A vision agent reads your photos with vision/OCR and pulls brand, model, category, condition, visible text, and flaws.
- Find comps. It searches eBay, Craigslist, Facebook Marketplace, Mercari, Google Shopping, and the open web for real listings so the price comes from what things actually sell for, not vibes.
- Write the listing. It drafts title, description, suggested platforms, price reasoning, and a private minimum. You can edit everything before you approve.
- Post. An operator agent uses your own Facebook Marketplace, Craigslist, eBay, and other accounts in a real browser. You log in yourself. Sold never stores marketplace passwords.
- Verify. "Submitted" is not "live." Sold only marks a listing live after it captures a real public URL. If Facebook still says in review, Sold still says in review.
- Monitor and negotiate. Once it's up, Sold watches buyer messages. The negotiator can answer questions, counter, hold on lowballs, accept, or escalate anything sketchy. It knows your private floor and never shows that number to the buyer.
How I built it
The interesting part wasn't generating a listing. I wanted an agentic system that finishes a multi-step job in the real world, not one that just talks about it.
Photo → Identify → Find comps → Write listing → Review → Post → Verify → Monitor → Negotiate
The lister is a LangGraph graph (vision_extract → comp_search → generate_listing) on GPT-5.4. Negotiation is a separate loop because it has to keep running for the life of the listing.
The operator is what actually uses the marketplaces. Those sites don't give a clean API for what I needed, so the agent drives a real browser with Playwright:
look at the page → decide the next action → click / type / open editor → look again → …
It is not a fixed click script. It reads the current page and chooses the next move. There are separate workflows for posting, revising, and taking listings down, plus monitors on the inboxes.
Stack: GPT-5.4 (vision/OCR, listing generation, comp evaluation, browser decisions, negotiation), LangGraph, Playwright, Browserbase (research and Craigslist sessions), local Chrome profiles for authenticated Facebook and eBay, Next.js + React + Tailwind, SQLite for listings/messages/events/connections, and Composio for the Gmail ping once a listing is confirmed live.
Challenges
The model would invent prices. Early on, a few empty Google Shopping results still produced a confident median. Prompting harder didn't fix it, so I changed the rule: a comp only counts with a real listing URL, and a price is only suggested when
$$|C_{\text{url}}| \ge 3$$
Otherwise the price stays blank. Nothing beats a believable fake.
Search is only as good as identification. Querying "blue gift box" is useless. Reading the real product name or model off the label first made comps actually land.
Browser UIs fight you. Brand fields appear out of nowhere, category trees shift, dialogs interrupt. Hardcoded click paths kept breaking, which is why the operator decides each step from the live page.
A browser agent needs a short leash. "Post this item" is too broad. The operator can't open buyer chats, wander to arbitrary URLs, or poke file pickers through normal navigation. A lot of the work was defining what it may touch and what counts as proof it worked.
"Submitted" isn't "live." The agent can fill every field, hit Publish, and still leave the listing in review. The only success signal is a real public URL (facebook.com/marketplace/item/{id}, or the matching Craigslist/eBay link). That killed a whole class of fake wins.
Inboxes are noisy. Marketplace pages are full of banners, unrelated threads, and junk like a bare "Toronto, ON" that looks like a message. Dumping the whole page into the model attached replies to the wrong listing. Matching on item URL, thread, and buyer fixed that.
What I learned
Most of the progress came from making the agents not do things: no price from empty search, no "live" from a Publish click, no free rein in the browser.
Why it matters
Posting on Facebook Marketplace isn't hard. It's just annoying enough that you keep postponing it.
Sold is an attempt to delete that friction. Take the picture, review what it found, and let it handle the rest.
Built With
- browserbase
- composio
- css
- langchain
- langgraph
- next.js
- openai
- playwright
- react
- tailwind
- typescript
Log in or sign up for Devpost to join the conversation.