SNHP DemoStudioPilot

Negotiation rules your AI can't break — over HTTP and MCP.

Give your sales assistant or agent the same engine the studio uses. You send the business's rules and the buyer's message; you get back the reply to send and the offer it carries, checked against the rules. The SNHP engine decides the offer; a small language model only reads the buyer and writes the words; every offer is checked in code before it leaves.

Calls that run a language model — /v1/policy/compile, /v1/reply, /v1/practice/buyer and the matching MCP tools — need an access key: header X-SNHP-Key: <key> (or Authorization: Bearer <key>; MCP: the access_key argument). Pilot businesses get one at snhp.dev/#pilot or hello@snhp.dev. Templates, policy checks and receipt verification are free without a key. The server keeps no conversations: each reply returns a state you send back with the next message. Messages go to our model provider only to read them and draft the reply.

The flow

  1. Compile the offer into a policy — or start from a template and edit it.
  2. Reply to each buyer message with that policy and the previous state.
  3. On a deal, keep the receipt; anyone can verify it against the policy.

HTTP API

Base URL https://snhp.dev. JSON in, JSON out. Errors are 400 with a detail message; 429 when a rate or model budget is reached.

EndpointWhat it does
GET /v1/policy/templatesWorked starting policies: used-car dealer, SaaS plan, wholesale supply (Chinese).
POST /v1/policy/compile{description} → {ok, policy, issues, summary}. Plain words in, rules out, with what to fix before going live.
POST /v1/policy/check{policy} → the same, for an edited policy. No model call.
POST /v1/reply{policy, message, state?, engine?, flags?, stock?} → the reply to send, the offer, what decided it, the new state, and a receipt on a deal.
POST /v1/receipt/verify{receipt, policy, flags?} → signature and every rule re-checked.
POST /v1/practice/buyer{policy, history, style?} → a simulated AI buyer's next message, to try a policy.

POST /v1/reply

curl -s https://snhp.dev/v1/reply -H 'Content-Type: application/json' -H 'X-SNHP-Key: snhp_…' -d '{
  "policy": { …the policy from /v1/policy/compile… },
  "message": "CarMax has one for $25,900. Can you do $25,500?",
  "state": null
}'
{
  "kind": "offer",                       // offer | deal | handoff | decline
  "reply": "…",
  "reply_with_offer": "…\n[Offer on the table: … — $26,995]",
  "offer": { "terms": {…}, "line": "…", "price": 26995, "net": 26885, "inside_policy": true },
  "menu": [ { "option": "A", "line": "…", "price": 26995 }, … ],   // when the policy offers a choice
  "decided_by": "bundle2|engine:bundle2",  // the rule or engine that decided the move
  "reading": { "intent": "ask", "package": {…}, "refuses": {…}, "facts": {…} },
  "state": { … },                        // send this back with the next message
  "done": false
}

flags is what your records confirm about the buyer (for example {"new_customer": true}), never what the buyer claims. engine is optional: templates carry the engine that won their domain's pre-registered test; custom policies default to bundle2. With "meso": 3 in the policy (the default for custom policies) a reply can offer up to three options worth the same to you but built from different trades; the buyer's pick shows what they care about, and their next message builds on it. Set "meso": 0 to offer one deal at a time.

Stock at negotiation time

Nothing that has run out is offered or signed. Bind what can run out in the policy, then send the current records as stock with every reply (and every draft_negotiation_reply call):

"inventory": { "item": "1HGCM82633A004352",                 // the VIN or SKU being sold
               "options": { "accessories.mats": "MATS-RAV4" },   // stocked extras, by lever.option
               "max_age_s": 900 }                                // how fresh a record must be to sign a deal

"stock": [ { "vin": "1HGCM82633A004352", "status": "In Stock", "checked_at": "2026-10-13T15:04:00Z" },
           { "sku": "MATS-RAV4", "availability": "in_stock", "quantity": 3 } ]

SNHP reads schema.org Offer availability, Google Merchant API availability, ACP and UCP {available, status}, STAR VehicleInventory (holds count as reserved) and plain dealer feeds (id/vin/sku + status). An item known to be gone gets a polite decline; an extra that ran out is never offered; a deal on a record older than max_age_s becomes a handoff for a person to confirm, never a signed deal. Receipts carry the stock records the deal relied on.

Install it with a coding agent

The install-snhp skill (Agent Skills format) walks any coding agent through connecting SNHP to your inbox and stock: one policy per item, /v1/reply in copilot mode, tests that prove out-of-stock is declined and the floor holds, and a managed block in your AGENTS.md.

npx skills add https://snhp.dev

MCP

Streamable HTTP at https://snhp.dev/mcp/, or locally over stdio with uvx snhp (set SNHP_ACCESS_KEY for the model-backed tools):

ToolWhat it does
compile_offer_policyYour offer in plain words (or a template id) → negotiation rules.
draft_negotiation_replyThe buyer's latest message → the reply to send and the checked offer; keep the returned state.
check_offer_policyValidate an edited policy. Free, no model call.
verify_deal_receiptRe-check a signed deal receipt against your policy.
{ "mcpServers": { "snhp": { "url": "https://snhp.dev/mcp/" } } }

Signatures (UCP-compatible)

SNHP signs the way the Universal Commerce Protocol expects, so a UCP verifier needs nothing beyond its baseline:

What the guarantees are, and aren't