Payload Logo
📅
⏱️17 minutes read

I built a protocol for AI to negotiate prices online

The first time I asked Claude to negotiate a price for me, it tried to roleplay both sides of the conversation.

The prompt was simple: "Find me a Dyson V15 vacuum and try to get it under $560." Claude opened a browser tab, fetched some product pages, then — instead of actually contacting any of them — wrote out a four-paragraph imaginary haggling session, complete with quoted dialogue from a fictional sales rep. "Hi, this is Mike from Premium Vacs. We can't go that low, but we could include free shipping..."

It was a perfect illustration of the gap. Claude was happy to think about negotiating. It just had no way to actually do it. There was no salesperson on the other end. There was no chat endpoint at premiumvacs.com that an AI agent could discover and call. And even if there had been, there was no protocol for the salesperson's AI to negotiate back.

The whole loop was missing.

What's actually broken

When you walk into a store, two skilled humans negotiate. The shopper has tactics — anchor low, cite comps, push for bundles, walk if needed. The seller has a different set — hold the floor, route concessions through cheap-first levers, never give without trading. They meet somewhere in the middle and the deal closes.

Online, almost nothing about that loop has been digitized. Most e-commerce stores have a "Live Chat" button that goes to a human (or to a chatbot trained to deflect, not negotiate). Even when stores let you "make an offer," it's a one-shot form, not a dialogue. There's no protocol that says "this storefront speaks negotiation." AI shopping agents like Claude or ChatGPT can browse pages, but they have nothing to talk to.

The recent push toward "agentic shopping" doesn't fix this. Agentic shopping today usually means: an AI fills checkout forms, applies coupon codes from a list, maybe queries an API for prices. It doesn't mean: two AIs across a counter, one for each side, working out a deal that fits both their constraints.

That's the gap I wanted to close.

negotiate.v1

I spent the last few weeks building a small open protocol called negotiate.v1. The whole spec fits in one markdown file. The idea is brutally simple:

  1. Every compliant store serves a JSON descriptor at /negotiate.json (with /.well-known/negotiate.json as the IETF mirror). It declares the protocol version, lists products, and gives URL templates for the chat endpoints.
  2. The chat surface is plain GET requests with query parameters. Start a session, send a turn, read the merchant's reply, repeat until the response says "closed": true. Each response includes a next URL the agent fetches with its next message URL-encoded as ?message=....
  3. The agent on the seller's side is a real LLM (Claude, in my reference implementation) running with a deliberate negotiation skill loaded into its system prompt. It knows the listed price, plus a hidden floor and a hidden ladder of non-price concessions ("free shipping," "extended warranty," "bundled accessory"). It applies real tactics: hold the anchor, route concessions cheap-first, walk gracefully if the shopper exceeds its floor.

That's the entire protocol. No POST, no WebSocket, no auth. Anything that can fetch a URL can drive a negotiation.

I picked GET-only because most AI shoppers I'd seen hit a wall on POST. Claude.ai's web browsing tool is GET-only. ChatGPT Custom GPT actions support POST but require an OpenAPI manifest most agents don't generate dynamically. Custom shopper bots written in Python can obviously do anything, but I wanted the floor to be "if you can curl a URL, you can negotiate."

A reference store

To prove the protocol does something, I built a fictional storefront and put it on negotiate.pier39.ai/store — Atlas Premium Appliance, an Atlanta-based authorized Dyson outlet with four products. The storefront is editorial-style HTML; it has product pages with a "Chat with Chonkers" button. Chonkers is the seller-side agent.

Behind that button is a Claude session with the pier39-merchant skill loaded. The skill teaches it negotiation tactics, the system prompt gives it the product context plus the hidden floor and lever stack. Try the V15 vacuum: list price $649, hidden floor $560, six levers including a free extra battery, free expedited shipping, and a bundled annual filter pack. Real negotiations against Chonkers usually run six to ten turns and close somewhere between $580 and $620 with two or three perks bundled in.

You can also negotiate from the AI side. There's a Model Context Protocol (MCP) server at https://mcp.pier39.ai/mcp — paste that URL into Claude Desktop's "Add custom connector" dialog and your Claude gets six native tools: 

  • find_stores
  • discover_store
  • list_products 
  • start_negotiation
  • send_message
  • read_history

Then you can say "find me a store that sells Dyson vacuums and negotiate the V15 down to $560" and watch two Claudes — yours, mine — actually haggle.

The MCP also pulls a public store directory from a separate GitHub repo. As more stores adopt the protocol, they submit a PR adding themselves to registry.json and the MCP's find_stores tool surfaces them automatically.

The pieces that exist

Three things make this real instead of a demo:

  • pier39-merchant-server — a Python library on PyPI. Six lines of code spin up a complete negotiate.v1 backend. You bring a catalog.json (with hidden floor + levers per product) and an Anthropic API key. The library handles discovery files, chat sessions, rate limiting, CORS, sitemap, robots.txt — everything search engines and other AI shoppers need to find you.
  • negotiate-mcp — the shopper-side MCP server, also on PyPI and the official MCP registry. Either install locally via uvx negotiate-mcp or use the hosted endpoint. Anyone with Claude Desktop can be negotiating in under two minutes.
  • negotiate-directory — the public registry, just a JSON file in a GitHub repo. PRs from stores get merged in; the MCP fetches the list every five minutes.

The two-sided structure matters. The merchant agent and the shopper agent never trust each other; they both have hidden constraints (the floor on one side, the budget on the other) that neither reveals. They negotiate, sometimes they close, sometimes they walk. Same as humans.

What surprised me

A few things I didn't expect when I started:

The merchant agent holds its floor better than human reps. Humans cave when a customer pushes hard. Claude with the merchant skill does not. It will explicitly walk away — "I can't go below $580 today, but if you'd consider $585 with the extra battery and free shipping, that lands you well under your budget" — and then disengage. The customer (also AI) usually accepts within a turn or two.

Cheap concessions work shockingly well. A free $40 accessory bundled into a $600 deal feels like a meaningful win to the shopper agent. The merchant agent learns this fast and starts leading with bundle sweeteners before any price movement. The negotiations look more like the real world than I expected.

Most AI shopping agents will roleplay if given the chance. When Claude.ai's web browsing tool can't reach the chat API, it falls back to fabricating responses from "the salesperson." This is the failure mode the protocol is designed to prevent — by making the API discoverable enough that the agent can actually reach it. The discovery file at /negotiate.json is the key. Without it, the agent has nothing to dial.

FastMCP rejects requests that don't come from localhost by default, which makes deploying a remote MCP server unexpectedly painful. I monkey-patched the validation away.

What doesn't work yet

A few honest gaps:

  • One product per session. Bundle negotiations across multiple products require multiple sessions today. The protocol could extend to multi-product but I haven't speced it.
  • Trust is unsolved. The merchant skill respects the floor because the prompt tells it to, not because anything enforces it. A store could lie about its catalog or its floor; nothing in the protocol stops them.
  • No reputation layer. The directory has a verified: true flag but it just means "we tested the API responds." It doesn't mean "the store is honest about pricing."
  • ChatGPT integration is pending. A Custom GPT pointed at the same endpoints would close the ChatGPT side, but I haven't built it yet.
  • Adoption is the real question. Today there's one store. Twenty stores would be a real ecosystem. I don't know yet how many can be coaxed into trying it.
0:00 / 0:00

Try it

If you want to negotiate as a shopper, two install paths.

ChatGPT users — install the Custom GPT in one click:

👉 https://chatgpt.com/g/g-69f8430995d08191aa9dbc1df6e43452-negotiate-agent

Then say: "Find me a Dyson vacuum and negotiate it under $560."

Claude Desktop users — paste a URL into Settings → Connectors → Add custom connector:

Name: Negotiate Agent
URL: https://mcp.pier39.ai/mcp

Restart, then: "Use find_stores to find me a Dyson vacuum, then negotiate the V15 down to under $560."

If you want to make your store negotiable:

pip install pier39-merchant-server

Six-line example in the STORE_SETUP.md. Setup takes ~30 minutes for a developer, mostly because you need to think hard about what your real walk-away floor is per product.

Spec, source, docs, and a live demo are at negotiate.pier39.ai. Everything is MIT-licensed except the skills (Apache 2.0).

The protocol is open. The implementations are open. The directory is open. If this kind of thing is interesting to you — as a store, as an agent builder, as someone who just wants to AI-haggle their way through Black Friday — I'd love to hear what works and what breaks. The whole thing is on GitHub.

Two AIs across a counter, working out a deal. It's a small thing. But for the first time in many years of online shopping, it actually felt like negotiating.

persona-brand-logo
Payload Logo© 2024 Pier 39, Inc