Negotiate a bundle — logroll linked issues
negotiate_bundleNegotiate several linked issues at once by logrolling — free, no account or key needed.
USE THIS WHEN: a deal has more than one issue on the table and they trade off — a job offer (base + equity + signing), a SaaS contract (price + seats + term + SLA), any package deal. It concedes on the issues you care about LESS (and the other side cares about MORE) to win the ones you care about most — a trade that beats splitting every issue down the middle. For a single PRICE, use negotiate instead.
Provide issues: a list of {"name", "options" (the choices), "my_utility" (how
good each option is to YOU — one number per option, any scale), "their_utility"
(how good each option is to THEM — their preference direction)}. Optionally
my_priorities ({issue_name: weight}, how much each issue matters to you) and
their_offers (their packages so far as {issue_name: option}, oldest first —
this is what lets it INFER their priorities). Returns {action, recommended_offer
(issue -> option), message, my_utility, their_expected_utility,
inferred_their_priorities, trade_logic, fit, confidence, acceptance_probability}.
Validated (separately from the single-issue +12%): returns a Pareto-efficient package that beats naive "split-every-issue-down-the-middle" bargaining by ~40% joint surplus (300 random 4-issue profiles). HONEST CAVEAT: the priority INFERENCE layered on top is weak (recovery r≈0.3) and currently adds only ~1% (and can be slightly NEGATIVE against some opponents) over the same engine run with no inference — so the proven value today is the efficient-package search, not (yet) the logrolling edge.
Optional timing refinement: pass rounds_left (bargaining rounds remaining)
with compute_ms > 0 to spend that many ms of Monte-Carlo rollouts choosing
WHICH package to hold for as the other side concedes over the rounds — a firmer
package closes later (discounted) than a generous one. 0 = the instant
closed-form package; the reply then carries a compute block. Modest by design
(never worse than the closed form in-model; helps on a minority of deals).
Example: a SaaS contract — you most want a low price_per_seat, can flex on seats/term/SLA. negotiate_bundle(issues=[ {"name":"price_per_seat","options":["$50","$40","$30"],"my_utility":[0,0.5,1],"their_utility":[1,0.5,0]}, {"name":"sla","options":["99%","99.9%"],"my_utility":[0,1],"their_utility":[1,0]} ...], my_priorities={"price_per_seat":0.55,"sla":0.1,...}, their_offers=[...]) -> a full package that gives ground on SLA to hold the price.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| issues | Yes | One dict per issue: {name, options (the choices), my_utility (value of each option to YOU), their_utility (value to THEM)} — utilities are one number per option, any scale. | |
| my_batna | No | Your best alternative to no deal, as a utility fraction in [0,1] (default 0.40); the returned package is guaranteed to beat it. | |
| compute_ms | No | EXPERIMENTAL. Milliseconds of rollouts to choose WHICH package to hold as they concede; 0 = instant closed-form package. | |
| rounds_left | No | Bargaining rounds remaining (used with compute_ms for the timing tier; default 8). | |
| their_offers | No | Packages the other side has tabled, oldest first, each as {issue_name: chosen_option} — lets it infer their priorities. | |
| my_priorities | No | {issue_name: weight} — how much each issue matters to you (any scale). Optional. | |
| their_batna_estimate | No | Your estimate of the other side's BATNA, [0,1] (default 0.40). |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| fit | No | ||
| error | No | ||
| action | No | ||
| compute | No | ||
| message | No | ||
| confidence | No | ||
| my_utility | No | ||
| trade_logic | No | ||
| recommended_offer | No | ||
| acceptance_probability | No | ||
| their_expected_utility | No | ||
| inferred_their_priorities | No |