Skip to main content

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 market and the VM buyer plugin are installed and ~/.config/arkhai/buyer.toml exists.
  • Make changes in an isolated test configuration before using a funded buyer wallet. Reading and writing configuration is local; market negotiate and market buy contact 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"]
  • bisection opens 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-markup are the scalar policies' flags (human, whole-token units per hour — 2 with 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, or default), with accept_exact_listing for 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-price and --max-price flags and any custom policies chain, then verify negotiation.policy is listed_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

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.