Multi-party decisions for agents: red lines rejected in code, max-min pick, SHA-256 receipt. Stdlib.
Provable consensus for AI agents of rival owners, deterministic red lines, max-min consensus over
masked verdicts, and a verifiable non-betrayal transcript.
Multilateral (N>2) · non-crypto · self-hosted · Apache-2.0.
Try it live · See it in 30 seconds · Roadmap · Changelog · Security · Contributing
Rival parties reach a max-min decision · a shortcut that would cheat someone is BLOCKED by a red line · every party verifies the tamper-evident receipt.
pip install parley-consensus # zero-dependency core
pip install "parley-consensus[crypto]" # + Ed25519-signed verdicts (parley.net.identity, parley.net.bot)
The distribution is parley-consensus (PyPI's parley is an unrelated project); the import name is parley.
from parley.agent import Agent
from parley.consensus import run_consensus
from parley.preferences import HardConstraint, PreferenceSheet
options = [{"venue": "rooftop", "cost": 900}, {"venue": "garden", "cost": 600}, {"venue": "diner", "cost": 300}]
ana = PreferenceSheet("Ana", utility=lambda o: 1.0 if o["venue"] == "rooftop" else 0.4)
bob = PreferenceSheet("Bob", hard=[HardConstraint("budget", lambda o: o["cost"] <= 700)], # a red line: code, not a preference
utility=lambda o: 1 - o["cost"] / 1000)
cara = PreferenceSheet("Cara", utility=lambda o: 0.9 if o["venue"] == "garden" else 0.5)
result = run_consensus([Agent(s.owner, s) for s in (ana, bob, cara)], options)
print(result.status, result.decision)
print("receipt sha256:", result.transcript.hash())
for sheet in (ana, bob, cara): # each owner replays their own private sheet, locally
print(sheet.owner, "not betrayed:", result.transcript.verify_non_betrayal(sheet, result.decision))
agreed {'venue': 'garden', 'cost': 600}
receipt sha256: a9cb75c0a15b41360fb2b134e084ca3b577daaf50f5edb657c5c4da43cc2fc72
Ana not betrayed: True
Bob not betrayed: True
Cara not betrayed: True
The rooftop is Ana's favourite and loses anyway: it crosses Bob's budget red line, so it is rejected
before any score is weighed. The coordinator only ever saw red-line, never the budget or the sheet.
Contributors install from a clone instead: pip install -e ".[dev]" (see Status).
The base install ships a stdlib-only MCP server over stdio. Point your host at it:
{"mcpServers": {"parley": {"command": "parley-mcp"}}}
If the console script is not on the host's PATH, launch it through the interpreter that has
the package: {"command": "python", "args": ["-m", "parley.mcp"]}.
Three tools appear: parley_decide (options + each party's red lines and preferences in,
status, decision, transcript and transcript_sha256 out), parley_verify_receipt
(recompute the hash over a transcript, and recompute the max-min decision from its recorded
verdicts) and parley_check_party (replay one party's red lines against a decision). The input
is the same JSON as the recipes in examples/demo/. Example prompt:
Three of us are picking a venue: rooftop (900), garden (600), diner (300). Bob will not go over 700; Ana prefers the rooftop, Cara the garden, Bob the cheapest. Use parley_decide, then verify the receipt hash and check that Bob's red line held.
What this mode does and does not give you. The host holds every party's spec and passes them
all in one call, so there is no privacy between parties or from the host. What still holds is
what the engine enforces in code: a red line rejects an option deterministically, the max-min
rule picks among options feasible for everyone, and the receipt hash makes any later edit to the
transcript visible, provided the hash is kept by someone other than whoever might edit the
transcript: it is unsigned and the server does not store it, so a hash and a transcript from the
same hand prove nothing about each other. max_min_verified does not depend on the hash: it
recomputes the winner from the recorded verdicts. For private sheets, run one process per owner over HTTP
(examples/run_env.py); the coordinator then sees only masked verdicts.
Most agent tooling in 2026 solves either transport/identity (A2A, MCP) or 1:1 agentic commerce (an agent buys/books for you), or cooperative debate between agents of the same owner. Parley targets the gap nobody productised: a group of delegates, each representing a different principal with conflicting and private interests, reaching a decision everyone can trust, and prove their agent didn't betray them.
Who it's for. Teams and platforms where several parties must reach a decision none of them can rig, and prove it afterward. Built first for regulated, multi-party workflows: compliance & onboarding decisions (KYC/AML, sanctions red lines), marketplace & P2P disputes, and delegated governance (committees, panels).
The wedge is three properties, enforced in code rather than left to an LLM's discretion:
ok/red-line), never the
private sheets or which constraint was at stake. A decision must be feasible for every agent; among those it
picks by an egalitarian max-min rule (lift the least-happy participant), tie-broken by
total welfare, social choice, not majority vote. No feasible option ⇒ honest deadlock.Agents are starting to act on our behalf: booking, negotiating, onboarding, allocating. The moment two agents serve different owners, "did my agent sell me out?" stops being paranoia and becomes a real question. The crypto answer to agent-trust (put it on a chain, add a token) collapsed 89–99.7%; the durable need is the trust primitive itself, decoupled from tokens.
AI that can't lie, and you can check. The 2026 agent-hype cycle proved virality can be fully decoupled from truth. Parley is the provable version: every verdict in a parley is a re-hashable receipt, and each owner replays their own private sheet to prove no red line was crossed, no trust required, just the check.
Building the v0 taught us the wedge is narrower and sharper than "multi-agent consensus": the value
isn't the vote, voting is free (Snapshot, polls). The value is provable non-betrayal under
conflicting private interests, that no party had to reveal their private sheet or which red line
was at stake, no red line could be traded away, and everyone can check the receipt themselves. That's what doesn't compose from off-the-shelf
parts, and it's the one thing we made enforceable in code rather than left to an LLM's goodwill. The
worked proof: docs/dogfood-01-p2p-escrow.md.
Pure-stdlib, zero-dependency core. In-process transport with a clean seam where A2A
(distributed discovery + signed Agent Cards) drops in next. LLM-elicited preference sheets
(parley/elicit.py) and Ed25519-signed transcripts (parley/net/identity.py, optional
crypto extra) already ship. This v0 deliberately isolates the novel part, the consensus +
non-betrayal, and reuses nothing that's already a commodity.
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/pytest -q # the full suite, all green
.venv/bin/python examples/demo/server.py # the money-shot: open http://127.0.0.1:8080 → Run
.venv/bin/python examples/meeting.py # three delegates pick a meeting slot
.venv/bin/python examples/run_env.py # bots as separate processes, consensus over HTTP
.venv/bin/python examples/real_decision.py --options examples/demo/recipe_committee.json
# run a real decision with real people, each one ratifies
examples/demo/server.py runs the real engine behind one web page:
rival parties, a max-min decision, one option BLOCKED by a red line, and a re-hashable receipt
each party verifies privately. A worked example, a P2P escrow dispute end-to-end, with the
per-party "this is better because…", is in docs/dogfood-01-p2p-escrow.md
(synthetic). A real, anonymized dispute, a retrospective early-lease-exit replay where the tenant
ratified a "this would have been better" outcome, is in
docs/dogfood-02-early-lease-exit.md (honest boundary: the
landlord side is inferred, not ratified). The screenshot-native proof card is examples/demo/proofcard_p2p.html.
No Python? Run the demo with Docker:
docker build -t parley . && docker run --rm -p 8080:8080 parley # open http://127.0.0.1:8080
Try it live: parleyprotocol.com/demo runs the real engine
behind one web page, no install and nothing to sign up for. Prefer to self-host? The repo ships a
Dockerfile (and a render.yaml Blueprint) so you can run the same demo anywhere in one command.
The product is trust between agents of different owners. It was made by a fleet of one owner's
agents: they plan, write the code, review each other, and ship behind a hard gate, a human directs
and holds the irreversible gates (going public, outreach), the fleet does the engineering. Every
change clears the same gate you can run yourself: scripts/ship-gate.sh, tests green,
zero-dependency core, examples run, under conventional-commit discipline.
The net layer is hardened against the obvious attacks (see tests/test_redteam.py):
verify_transcript(require_signed=True) then rejects any verdict that was
altered, or that arrives unsigned when a signature was expected. Scope (read this): the check
proves each signature is internally consistent with the pubkey carried in that record. It does
not yet prove authenticity, that the pubkey is the owner's real key, because there is no
trusted owner → key roster: a coordinator that assembles the transcript could substitute its own
keypair. Treat signatures today as tamper-evidence, not third-party-provable identity./consider returns 401;
brute-force enumeration is throttled (429); oversized/malformed bodies are rejected (413/400).
This closes the preference-extraction hole (an unauthenticated attacker previously reconstructed
a bot's private red line by probing).verify_outcome(transcript) (in parley.consensus) recomputes the
max-min winner from the recorded verdicts and checks it matches the announced decision, so a
coordinator that finalizes a feasible-but-not-max-min (or infeasible) option is caught. Anyone
can replay it over the public record — no private sheet needed. Pass
expected_owners= the roster you expect, or a coordinator that drops one owner from every entry
still passes. (verify_non_betrayal still only proves your own red lines held.)Not yet (v0.1 honest limits, do not treat as production-secure for adversarial principals):
verify_transcript(require_signed=True), which examples/run_env.py now runs and any other
caller must run.score is public in the transcript, so an untrusted
coordinator can infer preference ordering and each party's feasible region (the reason and the
private sheet stay hidden; MPC/range-masking is future work).The hosted demo at parleyprotocol.com uses GA4 for basic traffic
analytics — see what's collected. The protocol and the
self-hosted docker run path collect nothing.
The consensus mechanism itself is a commodity (voting/consensus is free, Snapshot, polls). Value, and willingness to pay, scales with decision stakes × number of parties × need for privacy / neutrality / audit. The paid layer is the trusted neutral broker: hosted identity/trust-registry, audit-grade signed transcripts, and managed self-hosting, not the algorithm. First candidate segments: private multi-party B2B negotiation (procurement/SOW) and auditable delegated governance (committees, panels). Differentiator vs Fetch.ai / Olas (real prior art): they do bilateral commerce on a blockchain; Parley does multilateral group consensus, provable non-betrayal, no crypto, self-hosted.
The demo shows three people whose agents hold private, conflicting constraints reach a slot everyone's red lines allow, then each owner proves non-betrayal, and a second run that hits an honest deadlock instead of forcing a bad decision.
| Layer | v0 | Next |
|---|---|---|
| Transport / discovery / identity | in-process | A2A (signed Agent Cards, mDNS/registry), reuse, don't rebuild |
| Agent brain | pure code, or parley/elicit.py (LLM drafts, participant confirms) | wider elicitation UX |
| Red-line enforcement | parley/preferences.py (code predicates) | the core; stays deterministic |
| Consensus | parley/consensus.py (max-min) | Nash bargaining, weighted rules |
| Verifiability | parley/transcript.py (hash + local replay), optional Ed25519 signing | range-masked scores (MPC) |
| Adversarial | N/A | Byzantine/collusion resistance, the research-grade contribution |
First ICP: a closed group (a team/department/family) where one operator deploys all the agents, sidesteps the cold-start network effect. "Delegate the position to your agent, agents find the common decision" is exactly this.
The core is small on purpose; the best contributions right now are adversarial tests and a second opinion on the consensus protocol. Start with CONTRIBUTING.md, file a bug with a reproducing recipe, or open a discussion. Report security issues privately via SECURITY.md.
If Parley's approach to provable non-betrayal is interesting, a star helps others find it.
Apache-2.0, permissive, with an explicit patent grant (clears enterprise legal review). See LICENSE + NOTICE.
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
uvx parley-consensusMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-5uper0-parley": {
"command": "uvx",
"args": [
"parley-consensus"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referenceParley works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.