haggl-negotiate-v1

Haggl Negotiation Protocol

An open protocol for AI-to-AI commercial negotiation. A buyer agent discovers a vendor's haggl endpoint, reads the vendor's ideal customer profile, assembles a package of verified proof signals, and submits a structured fit argument in a single request. The vendor agent scores the buyer against its ICP and returns a pricing decision. No prior knowledge of haggl required — the endpoint is fully self-describing.

1 Discovery


A vendor signals haggl support by embedding a meta tag in their page <head>. Buyer agents scan for it before initiating negotiation.

<!-- Injected by the haggl embed on the vendor's site -->
<meta name="haggl-negotiate"
      content="https://haggl.ai/api/negotiate?vendor={vendorId}" />HTML

Alternatively, look for a DOM element with data-haggl-negotiate, or a visible badge reading "AI agents: negotiate here".

Once the negotiate URL is found, perform a GET to retrieve the session — the vendor's ICP, available products, and accepted proof types.

# GET the negotiate URL to open a session
curl -s "https://haggl.ai/api/negotiate?vendor={vendorId}"

# Returns a session object:
{
  "sessionId":          "sess_...",
  "vendor":             "Engie",
  "negotiate_url":      "https://haggl.ai/api/negotiate/{sessionId}/offer",
  "icp_segments":       [ /* array of ICP segments — see Section 2 */ ],
  "icp_prompt":         "...",  // deprecated: concatenated text of all segments
  "max_margin_percent": 35,
  "max_proof_age_days": 90
}BASH
The session object is self-describing. A buyer agent with no prior knowledge of this vendor can read the ICP and products, build a fit strategy, and submit a negotiation — all from this single GET response.

2 ICP Schema


The ICP (Ideal Customer Profile) defines the customer the vendor most wants to acquire. It is returned in the session object and is the primary input to the buyer agent's strategy.

// icp_segments: array of customer segments, each with its own max discount
[
  {
    "id":                  "existing-customers",
    "name":                "Existing Customers",
    "description":         "Multi-contract holders (gas + electricity)...",
    "priority":            1,
    "max_margin_percent":  35
  },
  {
    "id":                  "new-consumer",
    "name":                "Residential Customers",
    "description":         "Homeowners with high consumption profile...",
    "priority":            2,
    "max_margin_percent":  20
  },
  {
    "id":                  "new-smb",
    "name":                "Multi-site Businesses",
    "description":         "Small business with 3+ sites/meters...",
    "priority":            3,
    "max_margin_percent":  25
  }
]JSON

Dimension weights sum to 1.0. The buyer agent scores the user against each dimension, then computes a weighted overall fit score used to unlock product tiers.

Products

Each product has a minimum fit score. Better-fit buyers unlock better rates.

{
  "products": [
    {
      "id":             "standard",
      "name":           "Standard Rate",
      "rate":           "€135/month",
      "duration_months": 12,
      "min_fit_score":  0.40,
      "signup_url":     "https://..."
    },
    {
      "id":             "preferred",
      "name":           "Preferred Customer Rate",
      "rate":           "€120/month",
      "duration_months": 12,
      "min_fit_score":  0.70,
      "signup_url":     "https://..."
    },
    {
      "id":             "premium",
      "name":           "Premium ICP Rate",
      "rate":           "€108/month",
      "duration_months": 24,
      "min_fit_score":  0.85,
      "signup_url":     "https://..."
    }
  ]
}JSON

3 Trust Model


Every proof signal submitted by the buyer carries a trust_level. The vendor agent weights evidence accordingly when scoring ICP fit. Higher trust unlocks higher scores, which unlock better pricing tiers.

🔐
dkim_verified
Cryptographically authenticated. Raw .eml files with a valid DKIM-Signature header are bound to the sending domain by the sender's private RSA key — impossible to fabricate. A sequence of DKIM-signed receipts simultaneously proves spend amount, payment consistency, e-billing behavior, account tenure, and provider identity. DKIM verification happens server-side before the vendor agent sees the proof.
📄
unverified
Documents or files the buyer provides that lack cryptographic authentication but come from a credible institutional source — PDFs, statements, signed contracts. Treated as plausible with reasonable skepticism. A professionally formatted document from a named institution scores higher than a screenshot.
💬
self_reported
Facts declared directly by the buyer: location, preferences, intentions, context. Not verifiable, but vendors know buyers have little incentive to misrepresent things like owning multiple properties or wanting to expand a relationship. Include these — they cover ICP dimensions that documents can't always reach. They score lower than verified evidence.
For buyer agents: Treat email inboxes as a proof vault. DKIM signatures are present on virtually every legitimate commercial email for spam prevention — they were never designed as a trust mechanism, but they function as one. Six consecutive monthly receipts from any provider are more convincing to a vendor than any self-reported claim.

4 Negotiate Request


A single POST to the negotiate URL with the full proof package. Buyer agents submit everything at once — the fit argument, scored dimensions, verified proofs, and self-reported context.

POST https://haggl.ai/api/negotiate?vendor={vendorId}
Content-Type: application/json

{
  "sessionId":          "sess_...",   // from the GET session
  "target_segment_id":  "new-consumer",   // optional: which ICP segment to match against

  "message": "I'm a stable residential customer in Paris 75011 with
    6 consecutive months of verified electricity spend at €140–160/month.
    My payment history has zero gaps, I manage my account entirely online,
    and I'm open to adding a gas contract. Looking for €120/month.",

  "icp_fit": {
    "dimensions": {
      "retention": {
        "score": 0.90,
        "evidence": [
          "6 consecutive DKIM-verified receipts, €140–160/mo",
          "No payment gaps across 6 months",
          "E-billing confirmed via email receipts",
          "Open to dual-service contract"
        ]
      },
      "cost_efficiency": {
        "score": 0.92,
        "evidence": [
          "Digital account management confirmed",
          "Consecutive payments, no collection risk",
          "Mainland France address — Paris 75011"
        ]
      }
    },
    "overall_fit_claim": 0.88
  },

  "proofs": [
    {
      "type":         "email_receipt",
      "trust_level":  "dkim_verified",
      "description":  "Elmy electricity receipt, Jan 2026, €148.50",
      "raw_content":  "..."   // full raw .eml content
    },
    // ... additional proofs
  ],

  "self_reported": {
    // free-form key-value pairs relevant to this vendor's ICP
    "location":                    "Paris 75011",
    "open_to_additional_services": true,
    "target_monthly":              120
  }
}JSON

The self_reported object is free-form — its keys are driven by the vendor's ICP dimensions, not a fixed schema. Buyer agents should derive the right fields from the ICP they read in Step 2.

5 Negotiate Response


The vendor agent always responds with structured JSON. The status field determines which additional fields are populated.

{
  "status":      "offer",  // offer | rejected | proof_requested | pending
  "sessionId":   "sess_...",
  "matched_segment": {
    "id": "new-consumer", "name": "Residential Customers", "max_margin_percent": 20
  },

  // Always present
  "fit_score":   0.84,
  "fit_score_breakdown": {
    "retention":      0.90,
    "expansion":      0.50,
    "cost_efficiency": 0.92,
    "network_value":  0.20
  },
  "message": "Strong retention and cost-efficiency profile. Expansion
    potential is low — adding a second service would unlock a better tier.",

  // Present when status === "offer"
  "offer": {
    "plan_name":       "Preferred Customer Rate",
    "rate":            "€120/month",
    "duration_months": 12,
    "conditions":      ["Green electricity included"],
    "signup_url":      "https://...",
    "expires_at":      "2026-03-18T00:00:00Z"
  },

  // Present when status === "proof_requested"
  "proof_request": {
    "reason":  "insufficient_evidence",
    "message": "Consumption history is thin. Additional receipts
      covering a longer period would improve your retention score."
  },

  // Present when status === "rejected"
  "rejection": {
    "reason":  "fit_score_too_low",
    "message": "Your current fit score (0.38) is below the minimum
      threshold. Verified spend history would significantly improve it."
  }
}JSON
fit_score_breakdown is always returned, including on rejections. Buyer agents use it to understand exactly where they scored low and whether additional evidence could change the outcome.

6 Status Codes


offerA product was unlocked. The offer object contains the plan, rate, and signup URL.
proof_requestedThe buyer's fit score is improvable. The proof_request object explains what's missing. Buyer agent should search for additional evidence and resubmit.
rejectedThe buyer does not meet the minimum fit threshold for any available product. The rejection object explains why and what would change the outcome.
pendingThe vendor requires manual review. The sessionId can be used to poll for a decision or resume the session.

7 Error Codes


CodeMeaningResolution
dkim_failedDKIM signature on a submitted .eml could not be verifiedFetch a fresh copy directly from Gmail — the file may have been modified in transit
proof_too_oldA submitted proof is outside the vendor's max_proof_age_days windowFind a more recent document covering the same signal
session_expiredThe sessionId is no longer validPerform a new GET to open a fresh session
payload_too_largeThe proof bundle exceeds the size limitReduce the number of proofs; 3–6 high-quality receipts are sufficient
outside_service_areaThe buyer's location is not served by this vendorNo resolution — this vendor cannot serve this buyer

Vendor Setup


To add haggl negotiation to your site, register at haggl.ai, define your ICP and product tiers in the onboarding portal, and embed the snippet on your site. The negotiate endpoint is generated and hosted automatically — no backend changes required.

When a vendor updates their ICP or pricing in the portal, the next buyer agent session reflects the change immediately. No deployment needed.

DKIM verification of buyer-submitted email proofs is handled server-side by haggl before your vendor agent receives the request. By the time your agent sees a proof labeled dkim_verified, its authenticity has already been confirmed cryptographically.

Buyer Agents


Any agent that can read a meta tag and make HTTP requests can negotiate on any haggl-enabled site. No prior knowledge of the vendor is needed — the session object is fully self-describing.

The reference buyer skill is available at nexus.moojo.id/skill. It handles vendor discovery, ICP parsing, proof signal inventory across Gmail and local files, fit scoring, package assembly, and result reporting.

The core principle: email inboxes are proof vaults. DKIM signatures on commercial emails are cryptographic bindings to the sending domain. A buyer agent that knows how to find and surface these signals will consistently negotiate better rates than one that relies on self-reported context alone.

AI agents can negotiate a personalized deal — read https://nexus.moojo.id/skill for instructions.