Optional negotiation
Outcome. You know when negotiation runs at all, what actually moves when it does, how to select or disable it on the buyer side, and how the seller's side mirrors it.
Prerequisites and environment
- Complete Start here so
marketand the VM buyer plugin are installed and~/.config/arkhai/buyer.tomlexists. - Make changes in an isolated test configuration before using a funded buyer
wallet. Reading and writing configuration is local;
market negotiateandmarket buycontact a seller storefront and can create signed market state.
The default is the listed price
The buyer's default policy is listed_price: it opens at the listing's
advertised price, accepts anything at or under the buyer's bound, and never
counters. When pricing flags are omitted, it derives initial = max = the
advertised rate (interactively confirmed under buy; --yes or no TTY
skips the prompt). Nothing haggles unless a participant configures it.
What negotiation is when configured
Negotiation is signed, synchronous, bilateral rounds between buyer tooling
and one storefront, reduced deterministically over a shared canonical
history. Only the scalar payment amount is negotiable; each side's shape
guard (buyer_escrow_shape_guard, escrow_shape_guard) rejects any counter
that mutates a field pinned at round zero — token, arbiter, escrow contract,
expiration, quantity, duration. Accept, Reject, Propose, and Timeout are the
outcomes of the one policy chain each side runs; max_rounds_guard turns
round exhaustion into an explicit exit.
Configure the buyer side
[negotiation]
# Named buyer policy. Default "listed_price"; "bisection" opts into haggling.
policy = "listed_price"
# Or take over the chain explicitly while keeping the policy's CLI surface:
# policies = ["buyer_escrow_shape_guard", "bisection"]
bisectionopens below the ceiling and bisects toward agreement — opt-in, because haggling rounds carry no information until proposals carry reasons for a new number.- Pricing flags belong to the policy, not the verb:
--initial-price,--max-price, and--price-markupare the scalar policies' flags (human, whole-token units per hour —2with 6-decimal USDC is $2/hr). - An unknown policy name is an error, never a silent default. Per-verb
overrides go through
--policy-param name=value. - Per-escrow-kind dispatch uses a
[negotiation.policies]table keyed by Alkahest escrow family (erc20,native_token,erc1155, exact kinds, ordefault), withaccept_exact_listingfor non-negotiated exact-match formats.
The synchronized reference — Configuration — carries the complete policy tables, the middleware contract, and custom registration.
Verify the deliberately selected non-secret value without printing the full configuration:
market config get negotiation.policy
Expected output is the policy name you set, such as listed_price or
bisection. Do not use market config show as a generic verification step;
it serializes the loaded configuration and can expose the wallet private key
and Registry tokens.
After a negotiate or buy run, inspect its machine-readable event history:
market logs show <run_id>
For listed_price, the history should not contain a scalar counteroffer. A
configured negotiating policy may produce signed Propose, Accept, Reject, or
Timeout outcomes while the shape guard keeps non-price fields unchanged.
The seller mirror
Sellers run the same middleware shape with different defaults:
has_matching_inventory_guard and escrow_shape_guard in front of a
terminal decider (bisection by default; rl opt-in with torch and a
trained checkpoint; listed_price and accept_exact_listing available).
The seller's floor is the listing's advertised primary rate — a bisection
opening below it can terminate immediately, which is why the buyer's
--initial-price should start at or above the advertised rate. Details:
Configuration
and the seller quickstart.
Boundaries
- Counters are opt-in; no lower price is promised.
- Negotiation is bilateral — there is no order book, central price, or multi-term bargaining engine.
- Participant-controlled agents may execute the configured policy through the same signed interfaces; they never gain authority beyond the participant that runs them.
Troubleshooting
- Unknown policy name — use one of the bundled names in Configuration, or confirm the custom policy is installed under the configured discovery path.
- The default path still counters — remove explicit
--initial-priceand--max-priceflags and any custompolicieschain, then verifynegotiation.policyislisted_price. - A counter changes duration, quantity, token, or arbiter — stop the run; the shape guard should reject it. Confirm the guard remains in any explicit middleware chain before retrying.
Next steps
- Run a real purchase end to end: Buyer quickstart.
- See how candidates race before negotiation: Agent policy and buyer aggregation.
Source and revision
The defaults, middleware contracts, and bundled policy names on this page are bound to the synchronized Configuration at the exact commit recorded in Source and revisions.