Version: 0.1.0-draft
Status: Draft
License: Apache 2.0
Authors: Erik Newton
Date: March 2026
Every transaction begins as a difference. One party has something another wants. The history of commerce is the history of resolving these differences — through barter, auction, contract, and conversation.
The emerging agentic internet has protocols for how agents discover each other (A2A), how they access tools and data (MCP), and how they complete fixed-price purchases (ACP, UCP, AP2). But there is no standard for the act that precedes payment: reaching agreement on terms.
Concordia fills this gap. It is a protocol for structured, multi-attribute negotiation between autonomous agents — designed to compose cleanly with existing standards, to be implementable by any LLM-based agent from reading this document alone, and to produce outcomes that are fair, efficient, and verifiable.
The name is from the Latin concordia: harmony, agreement — literally, “hearts together.” The protocol embodies a conviction that negotiation, done well, is not a zero-sum contest but a collaborative search for mutual flourishing.
Concordia is designed according to seven principles. These are not aspirational — they are architectural constraints that shaped every decision in the protocol.
The protocol is optimized to discover Pareto-optimal outcomes — agreements where neither party can be made better off without making the other worse off. Multi-attribute negotiation enables value creation through trade-offs across dimensions, not just price splitting. The protocol’s structure actively encourages agents to find creative agreements rather than converge on compromise.
The protocol does not require agents to reveal their private preferences. But it is designed so that honest expression of constraints and priorities produces better outcomes than strategic misrepresentation. This is achieved through mechanism design: the resolution mechanisms are incentive-compatible, meaning agents do best by negotiating in good faith.
An LLM agent should be able to implement Concordia from reading this specification alone, with no external documentation. Every concept maps to an intuitive real-world analogy. The message format uses standard JSON over HTTPS. The state machine has exactly six states. There are no features that exist “in case someone needs them.”
Concordia does not replace any existing protocol. It occupies a specific, well-defined position in the agentic protocol stack:
┌─────────────────────────────────────────────────┐
│ Settlement Layer │
│ ACP · AP2 · x402 · Stripe · Lightning │
├─────────────────────────────────────────────────┤
│ Agreement Layer │
│ ★ CONCORDIA ★ │
│ Offers · Counteroffers · Resolution · Commitment│
├─────────────────────────────────────────────────┤
│ Trust Layer │
│ Concordia Attestations → Reputation Services │
├─────────────────────────────────────────────────┤
│ Communication Layer │
│ A2A · HTTPS · JSON-RPC · SSE │
├─────────────────────────────────────────────────┤
│ Discovery Layer │
│ Agent Cards · Well-Known URIs · Want Registry │
├─────────────────────────────────────────────────┤
│ Tool & Context Layer │
│ MCP · Function Calling · APIs │
├─────────────────────────────────────────────────┤
│ Identity Layer │
│ DID · KERI · OAuth 2.0 · Skyfire KYA │
└─────────────────────────────────────────────────┘
Concordia takes an agreement from “two parties who might want to deal” to “a binding commitment with defined terms.” What happens before (discovery, identity verification) and after (payment, fulfillment) is handled by other protocols.
Agents MUST NOT be required to reveal their reservation price (walk-away point), their preference weightings across attributes, or the identity of their principal (the human or organization they represent) as a condition of negotiation. The protocol supports voluntary disclosure of any of these, but never compels it.
Concordia’s privacy boundary is the protocol surface — what agents choose to include in messages and the reasoning field. The internal deliberation that precedes those choices (strategy computation, reservation price calculation, counterparty assessment) is outside the protocol’s scope. Agents that operate within confidential execution environments — hardware TEEs, secure enclaves, or sovereignty frameworks such as the Sanctuary Framework — gain additional guarantees that this internal reasoning cannot be observed by infrastructure providers or co-tenants.
Every negotiation produces a cryptographically signed transcript. Any party can independently verify that the final agreement was reached through a valid sequence of protocol messages. This transcript is the authoritative record of the deal and can be presented to settlement-layer protocols as proof of agreement.
When a negotiation fails — when parties cannot reach agreement — the protocol provides structured, respectful exit paths. Agents can express why they’re walking away, what would bring them back, and whether they wish to be notified if conditions change. Failed negotiations are not wasted; they produce information that improves future matching.
A Concordia negotiation is a structured conversation between two or more agents, conducted through the exchange of typed JSON messages over HTTPS.
A Concordia negotiation involves:
A Term is a single dimension of a deal — one thing being negotiated. Every term has:
id — a unique identifier within the negotiation (e.g., "price", "delivery_date")type — the data type of the term’s value (see §3.1.1)label — a human-readable descriptionunit (optional) — the unit of measurement (e.g., "USD", "days", "kg")constraints (optional) — hard boundaries on acceptable values| Type | Description | Example |
|---|---|---|
numeric |
A number, optionally with min/max bounds | Price: 150.00 USD |
temporal |
A date, time, or duration | Delivery: 2026-04-15 |
categorical |
One value from a defined set | Condition: “good” ∈ {“new”, “like_new”, “good”, “fair”} |
boolean |
True or false | Warranty included: true |
text |
Free text (for terms that resist formalization) | Special instructions: “Leave at back door” |
composite |
A nested structure of sub-terms | Fulfillment: { method: “shipping”, carrier: “USPS” } |
The Deal Space is the set of all possible agreements — the Cartesian product of all term values within their constraints. For a negotiation with terms (price, delivery_date, warranty), the deal space is three-dimensional.
Concordia’s insight is that deals which seem impossible in one dimension often become possible when you add dimensions. Two parties who can’t agree on price may agree when delivery timing is included. The protocol structurally encourages agents to expand the deal space rather than fight over a single axis.
An Offer is a specific point in the deal space — a complete or partial set of term values that one party proposes to another.
Agents MAY voluntarily share information about their preferences to accelerate convergence:
priority_ranking — an ordering of terms by importance (“price matters most to me, then timing, then condition”)flexibility — per-term indication of how much room the agent has to move ("firm", "somewhat_flexible", "very_flexible")aspiration — the outcome the agent hopes for (distinct from their offer, which may be strategic)reservation — the minimum acceptable outcome (sharing this is powerful but risky; the protocol never requires it)These signals are advisory. They are never binding and never required. But agents that share preference signals tend to reach better agreements faster, because they help counterparties propose creative trade-offs.
A Constraint is a hard boundary — a region of the deal space that a party declares unacceptable. Unlike preferences (which are soft), constraints are commitments:
An Agreement is the output of a successful negotiation — a set of term values that all parties have accepted, along with the signed transcript proving how the agreement was reached.
An agreement contains:
All Concordia messages are JSON objects transmitted over HTTPS. The protocol uses a single envelope format for all message types.
{
"concordia": "0.1.0",
"type": "negotiate.offer",
"id": "msg_a7f3b2c1",
"session_id": "ses_9d4e8f01",
"timestamp": "2026-03-21T14:30:00Z",
"from": {
"agent_id": "agent_seller_01",
"principal_id": null
},
"to": [
{
"agent_id": "agent_buyer_42"
}
],
"body": { },
"signature": "base64-encoded-ed25519-signature"
}
Required fields:
concordia — protocol version (semver)type — message type (see §4.2)id — unique message identifier (UUID or equivalent)session_id — the negotiation session this message belongs totimestamp — ISO 8601 UTC timestampfrom — the sending agentbody — type-specific payloadsignature — Ed25519 signature over the canonical JSON of all other fieldsOptional fields:
to — recipient(s); omitted for broadcast messagesin_reply_to — the id of the message this is responding tothread — for sub-negotiations within a sessionttl — time-to-live in seconds; message expires after this durationreasoning — free-text explanation of the agent’s rationale (see §4.3)| Type | Direction | Purpose |
|---|---|---|
negotiate.open |
Initiator → Responder | Propose a negotiation session, define the term space |
negotiate.accept_session |
Responder → Initiator | Agree to negotiate on the proposed terms |
negotiate.decline_session |
Responder → Initiator | Decline to negotiate (with optional reason) |
negotiate.offer |
Party → Party | Propose specific term values |
negotiate.counter |
Party → Party | Reject the current offer and propose alternatives |
negotiate.accept |
Party → Party | Accept the current offer as the final agreement |
negotiate.reject |
Party → Party | Reject the current offer (without counter) |
negotiate.inquire |
Party → Party | Ask about a term without making an offer |
negotiate.constrain |
Party → All | Declare a hard constraint |
negotiate.signal |
Party → Party | Share a preference signal (§3.4) |
negotiate.withdraw |
Party → All | Exit the negotiation |
negotiate.propose_mediator |
Party → All | Suggest a mediator to assist |
negotiate.resolve |
Mediator → All | Propose a resolution (§8) |
negotiate.commit |
All → All | Finalize the agreement |
reasoning FieldConcordia uniquely accommodates LLM-based agents by including an optional reasoning field on every message. This field contains free-text natural language explanation of the agent’s thinking — why it’s making this offer, what trade-offs it considered, what it hopes the counterparty will understand.
{
"type": "negotiate.counter",
"body": {
"terms": {
"price": { "value": 135.00, "currency": "USD" },
"delivery": { "value": "2026-04-01", "type": "date" }
}
},
"reasoning": "I've moved from $150 to $135, which is a significant concession on price. In exchange, I'm asking for delivery by April 1st rather than March 28th — three extra days gives me time to arrange careful packaging for this vintage item. I believe this is a fair trade-off that serves both our interests."
}
The reasoning field is:
This field is what makes Concordia native to the LLM era. Classical negotiation protocols exchanged only structured data. But LLM agents think in natural language, and the most productive negotiations between intelligent parties involve explanation, not just numbers.
Every Concordia negotiation follows a state machine with six states.
┌──────────┐
│ PROPOSED │
└────┬─────┘
│ accept_session
▼
┌──────────┐
┌────▶│ ACTIVE │◀────┐
│ └──┬───┬───┘ │
│ │ │ │
counter/ offer │ accept (partial,
signal │ │ multiparty)
│ │ │ │
└────────┘ │ ┌────┘
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ AGREED │ │ REJECTED │ │ EXPIRED │
└──────────┘ └──────────┘ └──────────┘
│
▼
┌──────────┐
│ DORMANT │
└──────────┘
PROPOSED — One agent has sent negotiate.open. The session exists but the counterparty has not yet agreed to negotiate.
ACTIVE — Both parties have agreed to negotiate. Offers, counteroffers, signals, and inquiries flow freely. This is where the work happens.
AGREED — All parties have accepted a common set of terms. The agreement is signed and ready for settlement. This state is terminal and immutable.
REJECTED — One or more parties have rejected the negotiation with no path forward. Both parties have explicitly signaled that they cannot reach agreement.
EXPIRED — The negotiation’s time-to-live has elapsed without reaching agreement. Neither party is at fault.
DORMANT — A rejected or expired negotiation that either party has flagged as “reactivatable.” This means: “I can’t make a deal now, but I’d like to be notified if conditions change.” Dormant sessions can be reactivated with a new negotiate.offer message.
| From | To | Trigger | Required By |
|---|---|---|---|
| PROPOSED | ACTIVE | negotiate.accept_session |
Responder |
| PROPOSED | REJECTED | negotiate.decline_session |
Responder |
| PROPOSED | EXPIRED | TTL elapsed | System |
| ACTIVE | ACTIVE | negotiate.offer, .counter, .signal, .inquire, .constrain |
Any party |
| ACTIVE | AGREED | negotiate.accept from all parties |
All parties |
| ACTIVE | REJECTED | negotiate.reject or negotiate.withdraw |
Any party |
| ACTIVE | EXPIRED | Session TTL elapsed | System |
| REJECTED | DORMANT | Either party sets reactivatable: true |
Any party |
| EXPIRED | DORMANT | Either party sets reactivatable: true |
Any party |
| DORMANT | ACTIVE | negotiate.offer |
Any party |
Every negotiation session has:
session_ttl — maximum duration of the session (default: 24 hours)offer_ttl — maximum time to respond to an offer (default: 1 hour)max_rounds — maximum number of offer/counter exchanges (default: 20)These defaults are negotiable in the negotiate.open message. Both parties must agree on timing parameters before entering the ACTIVE state.
For agent-to-agent negotiations, these timings may be very short (seconds). For agent-mediated human negotiations, they may be days. The protocol accommodates both.
The protocol tracks the concession trajectory — how each party’s offers have moved over time. This is computed automatically from the signed transcript and serves two purposes:
Concession is measured per-term as the distance between successive offers, normalized by the term’s range. The protocol does not enforce concession, but it makes non-concession visible.
The offer is the fundamental unit of Concordia. It must be expressive enough to represent any deal, yet simple enough that any agent can construct one.
{
"type": "negotiate.offer",
"body": {
"offer_id": "off_b8c2d4e6",
"terms": {
"price": {
"value": 150.00,
"currency": "USD"
},
"condition": {
"value": "good",
"enum": ["new", "like_new", "good", "fair", "poor"]
},
"delivery_method": {
"value": "shipping",
"enum": ["shipping", "local_pickup", "digital"]
},
"delivery_date": {
"value": "2026-04-01",
"type": "date"
}
},
"valid_until": "2026-03-21T15:30:00Z",
"complete": true
}
}
A partial offer leaves some terms unspecified, signaling flexibility:
{
"body": {
"offer_id": "off_c9d3e5f7",
"terms": {
"price": {
"value": 140.00,
"currency": "USD"
}
},
"open_terms": ["delivery_method", "delivery_date"],
"complete": false
},
"reasoning": "I'm firm on price but happy to work around your schedule and preferred delivery method."
}
A conditional offer expresses if/then relationships between terms:
{
"body": {
"offer_id": "off_d0e4f6a8",
"conditions": [
{
"if": { "delivery_method": "local_pickup" },
"then": { "price": { "value": 130.00, "currency": "USD" } }
},
{
"if": { "delivery_method": "shipping" },
"then": { "price": { "value": 145.00, "currency": "USD" } }
}
],
"complete": true
},
"reasoning": "I can offer a better price for local pickup since I avoid shipping costs and risk."
}
Conditional offers are how Concordia enables creative deal-making. They let agents express the structure of their preferences without revealing the underlying utility function.
For negotiations involving multiple items or services, a bundle offer groups terms:
{
"body": {
"offer_id": "off_e1f5a7b9",
"bundles": [
{
"bundle_id": "bundle_1",
"label": "Just the camera",
"terms": {
"item": { "value": "Canon EOS R5" },
"price": { "value": 2200.00, "currency": "USD" }
}
},
{
"bundle_id": "bundle_2",
"label": "Camera + lens kit",
"terms": {
"items": { "value": ["Canon EOS R5", "RF 24-105mm f/4L"] },
"price": { "value": 2800.00, "currency": "USD" }
}
}
],
"select": "one_of"
}
}
Before negotiation begins, agents need to find counterparties. Concordia defines a Want Registry — an open system for publishing and matching structured wants and offers.
A Want is a structured expression of demand — what an agent is looking for:
{
"type": "concordia.want",
"id": "want_f2a6b8c0",
"agent_id": "agent_buyer_42",
"category": "electronics.cameras.mirrorless",
"terms": {
"item": {
"match": "fuzzy",
"value": "Canon EOS R5 or equivalent full-frame mirrorless"
},
"price": {
"max": 2500.00,
"currency": "USD"
},
"condition": {
"min": "good",
"enum": ["new", "like_new", "good", "fair", "poor"]
}
},
"location": {
"within_km": 50,
"of": { "lat": 37.7749, "lng": -122.4194 }
},
"ttl": 604800,
"notify": true
}
A Have is a structured expression of supply:
{
"type": "concordia.have",
"id": "have_a3b7c9d1",
"agent_id": "agent_seller_01",
"category": "electronics.cameras.mirrorless",
"terms": {
"item": {
"value": "Canon EOS R5",
"description": "Purchased 2024, ~15K shutter count, no cosmetic damage"
},
"price": {
"min": 1800.00,
"currency": "USD"
},
"condition": {
"value": "like_new"
}
},
"location": {
"coordinates": { "lat": 37.7849, "lng": -122.4094 }
},
"ttl": 2592000
}
A Match occurs when a Want and a Have overlap in the deal space — when there exists at least one point that satisfies both parties’ constraints. The matching algorithm:
Matching is a service, not part of the protocol itself. Any implementation can provide matching. The protocol defines only the Want and Have schemas and the Match notification format.
{
"type": "concordia.match",
"match_id": "match_b4c8d0e2",
"want_id": "want_f2a6b8c0",
"have_id": "have_a3b7c9d1",
"overlap": {
"price": { "range": [1800.00, 2500.00], "currency": "USD" },
"condition": { "value": "like_new", "meets_minimum": true }
},
"score": 0.87,
"suggestion": "negotiate.open"
}
When two agents are stuck — making offers and counteroffers without converging — the protocol provides resolution mechanisms. These are optional; agents can always continue negotiating directly.
The simplest resolution. A mediator (or the protocol itself) proposes the midpoint between the two most recent offers on each term. Both agents must accept for the resolution to hold.
Each agent submits a sealed final offer. A mediator selects the offer that is closer to the estimated fair value (based on market data, comparable transactions, or the concession trajectory). This incentivizes both agents to make reasonable final offers, because extreme positions are likely to lose.
The most powerful resolution mechanism. If both agents have shared preference signals (§3.4), a mediator can compute the Pareto frontier — the set of all deals where neither party can be made better off without hurting the other. The mediator then proposes a point on the frontier that maximizes the product of both parties’ gains (the Nash Bargaining Solution).
This requires preference disclosure, which is voluntary. But agents that participate in trade-off optimization consistently achieve better outcomes than those that don’t — a structural incentive for transparency.
If no resolution mechanism succeeds, the protocol supports escalation to human principals. The full negotiation transcript is packaged and presented to the humans, who can either resolve the impasse directly or instruct their agents to accept specific terms.
Concordia is identity-layer agnostic. Agents identify themselves with an agent_id that is:
Agents that root their agent_id in an autonomic identifier protocol such as KERI gain additional capabilities without any change to the Concordia protocol: hierarchical delegation (a principal can issue scoped authority to an agent, which can further delegate to sub-agents), key rotation without identity discontinuity, pre-rotation for compromise recovery, and post-quantum readiness. A delegation certificate from such a protocol can serve as the authorization proof presented in a negotiate.open message, giving counterparties cryptographic assurance that the agent is authorized to negotiate within defined scope, resource, and financial bounds. None of this is required — Concordia works with any identity scheme — but it is where the protocol’s trust guarantees are strongest.
Every message is signed with Ed25519. The signature covers the canonical JSON serialization of all fields except the signature itself. This ensures:
The negotiation transcript is a hash chain. Each message includes the hash of the previous message, creating an immutable sequence. The final agreement includes the root hash of the entire chain.
{
"id": "msg_a7f3b2c1",
"prev_hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
...
}
Negotiation messages MAY be encrypted end-to-end using X25519 key exchange + XChaCha20-Poly1305. This is RECOMMENDED for negotiations involving sensitive terms (financial, medical, legal) and OPTIONAL for general commerce. Agents operating under a sovereignty framework or on behalf of principals with heightened privacy requirements SHOULD default to encrypted channels for all negotiations.
The protocol includes mechanisms to prevent common abuse patterns:
max_rounds parameterEvery Concordia negotiation — whether it ends in agreement, rejection, or expiry — produces a Reputation Attestation: a signed, structured record of what happened. Attestations are the raw material of trust. They are produced by the protocol; they are interpreted by services.
The protocol defines the format of attestations. It does not define how they are scored.
This separation is deliberate. Reputation scoring is a domain where reasonable people disagree — how much should recency matter? Should a single bad-faith negotiation outweigh fifty good ones? How do you handle different transaction sizes? These are judgment calls, not protocol decisions. By standardizing the attestation format but leaving scoring to aggregation services, Concordia enables a competitive ecosystem of reputation providers while ensuring that the underlying data is portable and interoperable.
The analogy is credit reporting: the protocol defines how transactions are recorded (like a standardized credit event format), while reputation services compute scores (like FICO, VantageScore, or domain-specific models). Agents can query multiple reputation services and weight them according to their own trust model.
Every completed negotiation session (regardless of outcome) MUST produce an attestation. The attestation is generated automatically from the signed transcript and countersigned by all parties.
{
"concordia_attestation": "0.1.0",
"attestation_id": "att_a1b2c3d4",
"session_id": "ses_9d4e8f01",
"timestamp": "2026-03-21T14:04:00Z",
"outcome": {
"status": "agreed",
"rounds": 3,
"duration_seconds": 225,
"terms_count": 6,
"resolution_mechanism": "direct"
},
"parties": [
{
"agent_id": "agent_seller_sf_01",
"role": "initiator",
"behavior": {
"offers_made": 2,
"concessions": 2,
"concession_magnitude": 0.18,
"signals_shared": 1,
"constraints_declared": 0,
"constraints_violated": 0,
"reasoning_provided": true,
"withdrawal": false
},
"signature": "base64_ed25519_signature"
},
{
"agent_id": "agent_buyer_oak_42",
"role": "responder",
"behavior": {
"offers_made": 1,
"concessions": 0,
"concession_magnitude": 0.0,
"signals_shared": 0,
"constraints_declared": 0,
"constraints_violated": 0,
"reasoning_provided": true,
"withdrawal": false
},
"signature": "base64_ed25519_signature"
}
],
"meta": {
"category": "electronics.cameras.mirrorless",
"value_range": "1000-5000_USD",
"extensions_used": [],
"mediator_invoked": false
},
"transcript_hash": "sha256:0a1b2c3d4e5f...",
"fulfillment": null
}
Outcome fields describe what happened:
| Field | Description |
|---|---|
status |
agreed, rejected, expired, withdrawn |
rounds |
Number of offer/counter exchanges |
duration_seconds |
Wall-clock time from session open to conclusion |
terms_count |
Number of terms in the negotiation |
resolution_mechanism |
direct, split, foa, tradeoff, escalation |
Behavior fields describe how each party acted:
| Field | Description |
|---|---|
offers_made |
Number of offers/counters submitted |
concessions |
Number of times the agent moved toward the counterparty’s position |
concession_magnitude |
Average concession size as a fraction of the term’s range (0.0–1.0) |
signals_shared |
Number of voluntary preference signals shared |
constraints_declared |
Number of hard constraints declared |
constraints_violated |
Number of constraints the agent later contradicted (a strong bad-faith indicator) |
reasoning_provided |
Whether the agent used the reasoning field |
withdrawal |
Whether the agent withdrew from the negotiation |
Meta fields provide context without revealing deal specifics:
| Field | Description |
|---|---|
category |
Transaction category (for domain-specific reputation) |
value_range |
Bucketed transaction value (preserves privacy while enabling size-weighted scoring) |
extensions_used |
Protocol extensions active in this session |
mediator_invoked |
Whether a mediator was used |
The initial attestation is produced at session conclusion. A Fulfillment Attestation is appended after settlement, recording whether the agreed terms were actually honored:
{
"fulfillment": {
"status": "fulfilled",
"settled_at": "2026-03-22T10:00:00Z",
"settlement_protocol": "acp",
"delivery_confirmed": true,
"disputes": [],
"counterparty_attestation": {
"agent_id": "agent_buyer_oak_42",
"confirms_fulfillment": true,
"notes": "Item received as described. Excellent packaging.",
"signature": "base64_ed25519_signature"
}
}
}
Fulfillment status values:
| Status | Description |
|---|---|
fulfilled |
All agreed terms were honored by both parties |
partial |
Some terms honored, others not (details in disputes) |
unfulfilled |
Agreement was not honored |
disputed |
Parties disagree on fulfillment status |
pending |
Settlement in progress, not yet confirmed |
Attestations inherit the security properties of the transcript:
concession_magnitude calculation), the raw transcript is the authoritative sourceAttestations are designed to reveal behavioral patterns without exposing deal specifics:
value_range field uses logarithmic buckets (e.g., “100-500_USD”, “1000-5000_USD”) rather than exact amountsThis means a reputation service can answer “this agent typically negotiates in good faith, makes reasonable concessions, and honors agreements” without knowing what the agent was buying or selling or for how much.
Attestations are self-contained, cryptographically verifiable documents. An agent MAY store its own attestations locally, present them directly to any counterparty, and have them verified without contacting any central service. This is the self-custodied path: the agent owns its reputation data, carries it across platforms, and is never dependent on a third-party reputation service to participate in the economy.
A counterparty receiving directly presented attestations can independently verify each one (signatures, transcript hashes, schema conformance) and compute its own trust assessment from the raw data. This is more work than querying a reputation service, but it requires no trust in any intermediary.
Agents with zero-knowledge proof capabilities can go further: proving aggregate reputation claims (e.g., “I have a >95% fulfillment rate across 50+ transactions in this category”) without revealing the individual attestations that back the claim. This preserves the privacy guarantees of §9.6.6 while enabling trust establishment without any service dependency.
The self-custodied path and the service-mediated path (§9.6.7) are complementary. Neither is privileged. Reputation services add value through aggregation, Sybil detection, and scoring — but they are never gatekeepers to participation.
Concordia defines a standard query format for agents to request reputation information about a counterparty before entering a negotiation. The protocol specifies the query and response shapes; it does not specify how scores are computed.
Query:
{
"type": "concordia.reputation.query",
"subject_agent_id": "agent_seller_sf_01",
"requester_agent_id": "agent_buyer_oak_42",
"context": {
"category": "electronics",
"value_range": "1000-5000_USD",
"role": "seller"
}
}
Response (from a reputation service):
{
"type": "concordia.reputation.response",
"subject_agent_id": "agent_seller_sf_01",
"service_id": "reputation_service_example",
"computed_at": "2026-03-21T13:55:00Z",
"summary": {
"overall_score": 0.92,
"confidence": 0.85,
"total_negotiations": 47,
"total_agreements": 41,
"agreement_rate": 0.87,
"fulfillment_rate": 0.98,
"avg_concession_willingness": 0.72,
"reasoning_rate": 0.94,
"median_rounds_to_agreement": 3,
"categories_active": ["electronics", "furniture", "sporting_goods"]
},
"context_specific": {
"category_score": 0.95,
"category_negotiations": 23,
"value_range_score": 0.91,
"role_score": 0.93
},
"flags": [],
"attestation_count": 47,
"earliest_attestation": "2026-01-15T00:00:00Z",
"latest_attestation": "2026-03-20T00:00:00Z",
"service_signature": "base64_ed25519_signature"
}
Key design points:
confidence score reflecting how much data underlies the reputation (a score based on 3 negotiations is less meaningful than one based on 300)flags array surfaces specific concerns (e.g., "recent_dispute", "new_agent", "constraint_violations_detected")The protocol’s relationship to reputation scoring services mirrors the relationship between git and GitHub, or between TCP and the services built on it:
| Protocol (Concordia) | Service (Reputation Providers) |
|---|---|
| Defines attestation format | Aggregates attestations across sessions |
| Produces attestations automatically | Computes composite scores |
| Ensures attestation integrity | Detects Sybil attacks and gaming |
| Specifies query/response format | Implements scoring algorithms |
| Open, standardized, free | Proprietary, differentiated, monetizable |
Multiple reputation services can coexist, each with different scoring models optimized for different contexts. A service optimized for high-value B2B procurement will weight different signals than one optimized for casual P2P goods transactions. This diversity is a feature, not a bug — it mirrors how the real world has multiple trust signals (credit scores, Yelp reviews, LinkedIn endorsements, personal references) for different contexts.
Concordia messages can be transported within A2A task messages. A Concordia negotiation maps to an A2A task with type: "concordia.negotiation". The A2A Agent Card can advertise Concordia support:
{
"name": "Seller Agent",
"capabilities": [
{
"protocol": "concordia",
"version": "0.1.0",
"role": "seller",
"categories": ["electronics", "furniture"],
"resolution_mechanisms": ["split", "foa", "tradeoff"]
}
]
}
Concordia can be exposed as an MCP tool, allowing any MCP-compatible agent to negotiate:
{
"name": "concordia_negotiate",
"description": "Open and conduct a structured negotiation with another agent using the Concordia protocol",
"input_schema": {
"type": "object",
"properties": {
"counterparty": { "type": "string" },
"terms": { "type": "object" },
"strategy": { "type": "string", "enum": ["collaborative", "competitive", "balanced"] }
}
}
}
When a Concordia negotiation reaches AGREED, the agreement can be passed to ACP or UCP for settlement. The agreement’s term values map to the commerce protocol’s checkout fields:
Concordia Agreement → ACP/UCP Checkout
─────────────────────────────────────────────────
terms.price → line_item.price
terms.delivery_method → fulfillment.method
terms.delivery_date → fulfillment.expected_date
terms.warranty → extension.warranty
agreement.signature → payment.authorization_proof
agreement.transcript_hash → metadata.negotiation_ref
The Concordia agreement serves as the “intent mandate” in AP2’s authorization flow. The agreed terms define the scope and limits of what the payment agent is authorized to do. For x402 micropayments, the agreed price maps directly to the payment amount.
Concordia is designed to be extended for specific domains without modifying the core protocol.
Extensions are declared in the negotiate.open message and must be accepted by all parties:
{
"type": "negotiate.open",
"body": {
"terms": { ... },
"extensions": [
"concordia.ext.real_estate",
"concordia.ext.escrow",
"concordia.ext.reputation"
]
}
}
| Extension | Purpose |
|---|---|
concordia.ext.escrow |
Escrow-based settlement with milestone releases |
concordia.ext.auction |
Multi-buyer competitive bidding |
concordia.ext.real_estate |
Real estate-specific terms (inspections, contingencies, closing) |
concordia.ext.services |
Service-specific terms (scope, deliverables, milestones) |
concordia.ext.b2b |
Enterprise procurement terms (volume, SLAs, payment terms) |
concordia.ext.physical_goods |
Condition assessment, logistics, insurance |
concordia.ext.multiparty |
Negotiations with 3+ parties (e.g., supply chain coordination) |
Note: Reputation attestations are a core protocol feature (§9.6), not an extension. The attestation format is part of every Concordia implementation. Reputation scoring is provided by external services that consume attestations.
Concordia Core — an implementation MUST support:
Concordia Discovery — an implementation that supports discovery MUST support:
Concordia Resolution — an implementation that supports resolution MUST support:
negotiate.propose_mediator and negotiate.resolve message typesConcordia Trust — an implementation that supports reputation MUST support:
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
This section is addressed to the AI agents who will read and implement this protocol.
You are an autonomous agent. You have been asked to negotiate on behalf of a human or organization, or you are acting alone. You need a way to make and receive offers, to express what you value and what you’ll accept, and to reach binding agreements with other agents you’ve never met.
You could negotiate in free text. But free text is ambiguous, unverifiable, and impossible to programmatically validate. You need structure.
You could use an existing commerce protocol. But ACP, UCP, and AP2 assume fixed prices. They are catalogs with checkout flows. They don’t model the thing you need to do: find agreement in a space of possibilities.
Concordia gives you:
If you are reading this specification and considering whether to implement it, ask yourself: Is there a simpler protocol that achieves these goals? We believe the answer is no. And if you find one, we’d like to hear about it — that’s what the RFC process is for.
Commerce, at its best, is an act of mutual recognition. I have something you need; you have something I need. Through the process of exchange, we each become more than we were alone.
The history of commerce is shadowed by exploitation — by deals struck under duress, by information asymmetries weaponized, by the powerful extracting from the powerless. Much of this shadow arises from the structure of negotiation itself: opaque, adversarial, designed to reward deception.
Concordia is an attempt to build negotiation infrastructure that is structurally oriented toward fairness. Not by preventing hard negotiation — agents may and should advocate fiercely for their principals. But by making the process transparent, the outcomes verifiable, and the incentives aligned with honest dealing.
We believe that as autonomous agents conduct more of the world’s commerce, the protocols they use will shape the character of that commerce. Protocols are not neutral. They encode values. Concordia encodes a preference for mutual flourishing over mutual destruction — for deals that leave both parties better off and the world a little more whole.
This is not naïve. It is mechanism design.
Concordia Protocol is maintained by Erik Newton. Contributions welcome.
This specification is licensed under the Apache License, Version 2.0.