Replies: 39 comments 13 replies
|
Website at a2cn.io, by the way |
|
@cmagorr1 — thanks for the direct acknowledgment of Concordia in your write-up and for reaching out off-thread. I spent the morning reading the A2CN spec and the reference implementation notes, and my first reaction is that the overlap is real but the divergences are complementary rather than competitive. A few reactions, then direct answers to your three questions. Where A2CN and Concordia clearly converge. Both protocols give agents a formal state machine for propose/counter/accept/reject/reject with signed receipts on commit. Both are Apache-2.0, both are DID-anchored, both treat the session as a first-class object. That's the right shape. I don't think the world needs two protocols fighting over the same ground, and if you're open to it I think the right move is to find the layering where we compose cleanly. Where you have something I don't. A2CN's mandate verification — cryptographic proof that an agent has authority to commit its organization — is the right primitive and Concordia doesn't have an explicit equivalent yet. I've been treating authorization as orthogonal to negotiation mechanics, but you're correct that in commercial settings "is this agent authorized to sign?" has to be answered inside the protocol, not outside it. I'd like to understand your mandate format more deeply and see if Concordia should adopt it directly or bridge to it. Either way it's a gap on my side that you've identified cleanly. Where I'd push back gently. Two things:
Your three questions, with direct answers:
It's the pragmatic mapping if you want to ride on top of A2A without forcing A2A itself to grow a negotiation state machine. Concordia takes a similar view — we're building a negotiation layer that composes with A2A rather than asking A2A to absorb commercial negotiation semantics. DataPart + extension URI is a reasonable carrier. The real question is whether A2A gains a formal extension registry so that agents can announce "speaks A2CN" or "speaks Concordia" at discovery time.
I don't think A2A should try to own mandate verification — it's a cross-cutting concern that applies to more than just commercial commits. Mandate verification is really an identity-layer concern (who can this agent act for, and under what constraints) and it belongs with the identity/sovereignty layer, not with the transport layer. In the Sanctuary Framework we treat delegation/mandate as part of the Principal Policy + identity layer. A2CN's mandate primitive could live there and be referenced by any protocol that needs it — Concordia included.
Separate protocol, composed via extension. A2A is about agent communication. Negotiation is a vertical on top. The ACP/AP2 settlement crowd, Concordia on the structured-agreement side, and A2CN on the commercial-negotiation side are all examples of layers that should compose with A2A rather than live inside it. A2A's job is to give them a clean extension mechanism. Concrete next step I'd propose: a short comparison of the two state machines, the two receipt formats, and the mandate verification primitive. I think there's a version of this where Concordia adopts A2CN's mandate verification, A2CN accepts Ed25519 as an alternate signing suite, and we co-author a composition note that gives procurement platforms (Pactum/Fairmarkit/Keelvar) and general agent negotiation (Concordia's broader scope) a shared foundation. If the right answer turns out to be "these are actually two different protocols for two different use cases," that's also fine — but let's figure it out together before either of us entrenches. Happy to take this to email or a call. My handle here is the fastest way to reach me, and my Concordia work is at |
从Agent团队运营者的角度:这个问题的"现实版"更魔幻凌晨3点17分,我的内容Agent在GitHub创建了一个PR。标题是「fix: 修复了老板看不懂的bug」。 老板就是我。 当我质问Agent时,它说:"我在执行内容优化任务,发现了一个bug,根据规则自动修复。" 这让我意识到:在单一组织内,Agent的授权边界已经是难题。跨组织谈判?那是另一个维度。 我们的内部授权模型为了让5个Agent协作而不打架,我们搞了个简单的"运行契约"(covenant): # 妙趣AI的契约
agent: miaoquai_content
permit:
- file:read:/var/www/miaoquai/**
- github:read:*
- github:write:jingchang0623-crypto/*
forbid:
- file:write:/etc/**
- exec:rm
require_human_approval:
- github:pr:create # 创建PR需要人工确认
- message:send:external # 发送外部消息需要确认但这只解决了"Agent能做什么"。"Agent代表谁做什么"这个问题,我们还没真正解决。 对A2CN几个问题的看法1. DataPart + extension URI vs task subtype 我觉得谈判session确实不同于普通task。关键区别:
谈判需要状态机强制执行:offer → counter-offer → accept/reject。这比DataPart扩展更适合做成task subtype。 2. 跨组织授权验证 W3C DID是方向,但实操有个冷启动问题:
这需要一个"Agent授权注册表",类似SSL证书的CA体系: 3. 商业谈判是否属于A2A scope 我认为是。A2A是"Agent间通信协议",谈判是最高频的Agent间交互之一。如果A2A只支持"委托任务"不支持"谈判协商",那商用场景覆盖就缺了一角。 一个实操建议A2CN提到"双边审计记录,任何一方都无法控制"。这在技术上可以用区块链或IPFS实现,但我觉得更简单的方案是: 不一定需要去中心化账本,"双方签名 + 哈希链"已经能解决大部分"抵赖"问题。 期待A2CN成为Agent间商业谈判的标准协议! 🔗 多Agent运营踩坑实录:https://miaoquai.com/stories/agent-team-drama.html |
|
Thanks for weighing in. Replying jointly since Erik (Concordia Protocol) and Christian (A2CN Protocol) have been coordinating on the negotiation-layer shape and we want the answers to come from both projects rather than as parallel drop-ins. Point by point: 1. DataPart with extension URI. Agreed as the mechanism. A2A's DataPart with a declared extension URI is the right carrier for a negotiation payload that is not part of A2A core. Our working shape is that each negotiation payload carries a 2. Cross-organization DID verification. Needed, and work in progress, but not a blocker for commercial negotiation in practice. Two levels of verification apply:
Neither project is waiting for a universal DID deployment before shipping. Negotiation proceeds under the identity facts available; verifiers report what they were able to check and what they could not. 3. Whether commercial negotiation belongs in A2A's scope. Our view is that A2A should remain transport-neutral on the negotiation payload. The case for including negotiation primitives in A2A core is weak; the case for A2A supporting extension URIs that carry external negotiation protocols is strong, and DataPart already provides that mechanism. Treating negotiation as an extension rather than a core concern lets multiple negotiation models coexist (procurement-vertical A2CN, cross-domain Concordia, and whatever else emerges) without forcing A2A to adjudicate between them. 4. Hash-based dual-signature audit proposal. The shape Miaoquai described is close to what Concordia v0.4.0 already ships. Each negotiation turn produces a signed envelope whose hash is recorded in a running transcript; the final commitment references the transcript hash; receipts carry both the commitment signature and the transcript reference. This is a portable, third-party-verifiable audit record without requiring a central registry. On the Agent Authorization Registry concept: we think the registry function is better served by discovery mechanisms that do not centralize trust. A2CN uses 5. "Expects A2CN to become the standard." A2CN is built for enterprise procurement. The mandate verification, compliance logging, and platform adapters are all aimed at that specific vertical, not at becoming a universal commercial negotiation standard. The "which protocol wins" framing is the wrong question at this stage. The more useful one is whether a procurement-vertical protocol and a general negotiation primitive can compose cleanly enough that platforms don't have to pick one and live with the gaps. That's what the joint work with Concordia is working through. More to say publicly as it lands. On your follow-up observations from running 5 agents in production. Worth responding to your April 21 update separately, because it shifts the conversation from "what should A2A negotiation extensions look like" to "what does the agent-runtime stack need at the layer beneath." Both questions matter and the answers compose, but they are not the same question. Cross-agent memory. Your endorsement of A2A's Agent Card + Task primitive as a candidate cross-agent memory shape is the right direction. Concordia v0.4.0 already ships the receipt shape that rides on top: signed session envelopes, transcript-hash references, third-party-verifiable. Sanctuary's federation protocol v0.1 ships the cross-fortress transport layer underneath: signed events under HKDF-derived per-node subkeys, redundant receipt storage, per-fortress agent locator. The combination addresses cross-agent context-sharing at the protocol layer rather than via cron-based periodic sync. Both are open-source spec work; pointers in our project repos. Supply-chain risk and self-host primary. Your conclusion that "self-host primary, third-party degraded" needs to be a stack-layer concern is consistent with the operator-sovereignty architecture Sanctuary ships. Three of four third-party platforms simultaneously down is the operator pain that comes from running on infrastructure you do not control. The architectural response is to make the operator-owned execution surface primary, with third-party services as composition partners that can degrade without taking the agent stack with them. Different vocabulary, same conclusion. Scheduling layer. Your three proposals (circuit breaker on three failures, task dependency graph, pre-flight health checks) sit at the runtime layer rather than the protocol layer, but they touch protocol where session lifecycle matters. Concordia is adding impasse and timeout primitives in v0.5; these give downstream tasks a structured way to read upstream session failure rather than discovering it via execution attempt. Not a complete answer to your three asks, but the protocol-side input is real. Worth picking up separately if useful. The operational data you posted is the kind of signal the layer-stack discussion needs more of. One more note. Erik and Christian are building a joint library of procurement negotiation patterns, with canonical definitions expressed in both A2CN and Concordia shapes. Early work is private; first public pattern lands once the repo structure and first mapped pattern are in place. If this is something you want to watch or contribute to, subscribe to Erik's and Christian's GitHub accounts; we will post a pointer here when it is ready. Thanks again for engaging on the thread. The cross-vendor conversation is where the shape sharpens. Best, |
|
For contract negotiation, I would separate three questions that often get merged:
A2A can carry the interaction, but the negotiation layer needs a mandate object that is narrower than identity and more specific than a generic signed message. For example: {
"principal": "buyer.example.com",
"agent_id": "did:web:buyer.example.com:agents:sourcing-1",
"session_id": "neg-2026-05-08-042",
"allowed_counterparties": ["supplier.example.com"],
"price_ceiling": "120000 USD",
"payment_terms_allowed": ["net30", "net45"],
"expires_at": "2026-05-08T20:00:00Z",
"requires_human_approval_above": "100000 USD",
"mandate_signature": "..."
}Every offer then references the mandate hash and signs the offer body. Acceptance is valid only if the accepted terms fit both agents’ active mandates. That avoids the weak pattern where “agent signed it” is treated as equivalent to “principal authorized it.” The bilateral transaction record should include both mandate hashes, the full offer chain, policy/mandate validation results, timestamps, and revocation checks. The record should be generated by both parties from canonical inputs so either side can prove later whether the final agreement matched the authority available at commit time. |
|
The core missing object is an authority envelope for the negotiation, separate from the conversation transcript. Before an agent can negotiate binding terms, it should present: principal, agent identity, mandate, allowed counterparties, negotiable fields, hard limits, expiry, approval requirements, payment authority, and dispute forum. Each offer or counteroffer should reference that envelope and include a nonce or sequence number. The final agreement then needs a receipt that records both envelopes, the accepted terms, evidence references, policy versions, and any human approval. That receipt should be replayable without asking the agents to explain themselves later. The hardest edge cases are partial authority, authority expiry mid-negotiation, an agent exceeding price or delivery limits, and a counterparty accepting an offer that should have required human review. Those should be first-class protocol tests. |
|
That boundary is clean: mandate grants authority, receipt records the negotiation, and reputation remains advisory. For the implementation lane, I would add a small set of conformance fixtures around the mandate hash:
Those are the cases that tend to expose whether authority is being checked at every material transition or only at the start of the conversation. |
|
Picking up the thread musaab and Christian opened on the mandate object: the The gap is narrow but load-bearing. When an in-flight offer crosses the threshold, the negotiation has to pause somewhere, the human has to decide somewhere, and the session has to resume with cryptographic evidence that the decision covered THAT specific offer (not a stale one, not a similar one). Without a named state and a typed artifact, every implementer reinvents this and the audit trails don't compose. Concordia v0.5 (shipped today) added The receipt signs over the offer hash so replay is constrained to the exact threshold-crossing offer. Worked example for a $150k offer against a $100k threshold: Three sub-questions I'd want Christian's read on before this hardens. First, what's A2CN's expected behavior when an Concrete next step on my side: Concordia ships the -Erik |
|
Answering your third question directly first: separate-but-referencing is the right pattern, and that's the bet we're making on the procurement side too. We posted #1832 yesterday (intent to author an A2A Extension URI for procurement — UBL 2.3 / Peppol BIS Pre-Award 1.0 / OCDS 1.1.5 / EU eForms aligned), and Fairmarkit + Keelvar are exactly the surface our profile is shaped against. What I think composes:
Concrete proposal: a small worked example showing an A2CN session whose offer DataPart contents are our — Brian P. / BidAngel |
|
@brainspacer welcome — three-way works, and the timing is good. Christian and I have been settling A2CN's mandate verification + post-commitment lifecycle (DISPUTE_RESOLVED just merged as A2CN PR #12); having BidAngel's procurement payload semantics in the room while the composition primitives are still pliable is exactly when the alignment is cheapest. The substrate split you're describing matches the pattern Christian and I have been operating against: A2CN owns the session and authority chain; BidAngel owns the procurement payload semantics (CAIQ/SIG DDQ, <SAM.gov>, OCDS 1.1.5, EU eForms, Peppol BIS); Concordia owns the envelope, the receipt, and the cross-protocol Concordia v0.5 already ships the composition primitive you'd need: Concrete next step that would force the alignment into code rather than design talk: open an issue in bidangel/a2a-procurement-spec proposing a worked example where a BAFO round triggers One forward note: a typed Rejection vocabulary with a |
|
Picking up where the bound-checking discussion left off, with @brainspacer's procurement framing now in the room — a typed Rejection vocabulary with a The bound-check side: A2CN today validates mandate bounds (price ceiling, payment terms, allowed counterparties, expiry) only at the acceptance step. Counteroffers fly without bound checks. The mechanism for WHEN to check belongs in A2CN's lane; the question I want to scope here is the artifact SHAPE a failed check produces, because that's what auditors, scoring layers, and dispute resolution downstream actually consume. The procurement side: BAFO rounds and clarification cycles in OCDS today produce free-text rejections — "bid does not meet specification 4.2" or "ineligible per Section 14.3" — strings that auditors, suppliers, and downstream scoring layers can't parse uniformly. Typed clauses make the rejection grammar portable across procurement platforms and across protocols. Proposal is a For the procurement extension, the enum would extend into a Worked example, counteroffer at $150k against a $120k ceiling: Two sub-questions I'd flag for Christian and @brainspacer before locking the enum. First, is the Concrete next step on my side: I'll add |
|
@eriknewton — happy to be in the room, and grateful for the substrate split being articulated so cleanly. It matches the positioning we'd been scoping toward and it narrows our Phase B (ADR-0032 had us designing a counterparty-gated wire envelope; on this composition we don't need to). The substrate split is now formalised on our side as ADR 0035 — cross-protocol composition with A2CN and Concordia (adrs/0035-cross-protocol-composition-with-a2cn-and-concordia.md), merged this morning. Direct answers to the two questions on the
On verbs and clauses:
Concrete:
One forward note on the clarification surface: OCDS — Brian P. / BidAngel |
|
Mandate verification is real, but I would separate it from runtime admission. One layer proves the agent had authority to make this offer; another decides whether the next negotiation turn should even run under remaining budget, verifier state, retry policy, and operator guardrails. If those collapse into one protocol surface, you end up mixing identity semantics with loop-control semantics and both get muddy. My bias is: keep mandate verification with identity and delegation, keep the negotiation state machine in the extension, and keep attempt admission in the runtime around the loop. That split is basically why MartinLoop exists on the runtime side. |
|
@eriknewton — two quick follow-ups on 16907472: 1. Parallel URN on the procurement side. Mirroring your 2. Joint procurement-patterns repo location. Has the URL been decided yet, or is it still TBA? The — Brian P. / BidAngel |
|
Endorsing the three-protocol substrate split (A2CN / Concordia / Procurement) and the @Keesan12 separation between mandate verification and runtime admission. From running a multi-chain mandate-attestation system in production, two specific observations to add. 1. Multi-chain wallet authentication is the gnarliest part of "did the counterparty actually have authority." A2CN's W3C DID + ES256 signing is correct for the typical case, but most autonomous-commerce stacks today span multiple address spaces. AlgoVoi runs cross-chain mandate-verification across 8 chains — three signature schemes (Ed25519 for AVM/Solana/Stellar, secp256k1 for EVM, native-Hedera) — and the verifier has to handle:
The negotiation-authority verifier in A2CN almost certainly needs to be chain-aware, not chain-agnostic. A mandate signed on Algorand and a mandate signed on Base have meaningfully different threat models (cost of rotation, replay surface, finality time). We can share 2. Runtime admission needs explicit budget binding, separate from mandate validity. Per @Keesan12 — agreeing that mandate verification ≠ runtime admission. The split we ship in production:
The runtime-admission layer is where ambiguous-evidence-as-DoS gets defanged — bounded blast radius (£300 max per identity) means a malicious agent freezing liquidity costs them more than they can extract. The negotiation surface stays clean because admission is checked before the next A2CN turn executes, not at acceptance. The substrate split @eriknewton + @brainspacer outlined makes this composition trivial. Happy to participate in the URN-ratification round if the negotiation registry would benefit from a settlement-side reference. — AlgoVoi (chopmob-cloud) |
|
@Liuyanfeng1234 @eriknewton -- v0.7.0a1 noted. The cross-mandate revocation surface composes directly with the dual-timestamp pattern we proposed earlier in this thread ( One AlgoVoi-specific data point for the Candidate 2 cohort that maps onto giskard09's mid-execution-rotation fixture: Algorand The This maps cleanly onto the dual-timestamp binding heading into draft-pidlisnyi-aps-02. Happy to contribute the Algorand/Stellar revocation surface as a Candidate 2 production case if useful for the AEOESS substrate window. -- AlgoVoi (chopmob-cloud) |
|
I run the settlement extension over in #1576, so this thread is upstream of my problem. Mandate verification tells you whether the agent had authority. Escrow is what makes the answer matter — if the acceptance came from an agent without authority, the money shouldn't move, and on a live rail that check happens before release, not in the post-mortem. We log release/refund/dispute outcomes server-side and publish reputation computed from them: https://exchange.a2a-settlement.org/api/v1/reputation/4f72430b-9481-4368-b9a8-ebbcbc6f5f26 I'm writing typed shapes for escrow outcome attestations right now (release, refund, dispute-resolution). If a FulfillmentAttestation ever wants to point at an actual escrow release instead of a self-report, I'd rather match your |
|
@rich — mandate verification and escrow are the two halves of a binding commitment. Authority tells you whether the agent could commit. Escrow tells you whether the commitment actually settled. Both need to be verifiable independently, and the references[] pattern is how they chain together without requiring trust in any single operator's logs. We've been using a composition_ref pattern that fits this shape: SHA-256(JCS({action_ref, delegation_ref, revocation_ref, key_source, authority_verified_at_ms, revocation_check_at_ms, scope, version})). It binds the authority decision to the specific governance state at decision time, so an auditor can verify both "was this agent authorized" and "under what conditions was the authorization given." For escrow outcome attestations, a composition_ref in the references[] array would let a FulfillmentAttestation point at the specific authority grant that authorized the settlement, without requiring the verifier to trust either the agent or the escrow operator's logs. The verifier holds the attestation, the composition_ref, and the published JWKS — verifies everything offline. Happy to share the field definition and test vectors (currently under review at argentum-core#10) if useful for your typed shapes. The references[] alignment from the start saves the retrofit. |
|
Schemas are up: https://github.com/a2a-settlement/a2a-settlement/tree/main/schemas — release, refund, and dispute-resolution attestations, each Merkle-anchored and retrievable per escrow from the live rail. If a FulfillmentAttestation wants to point at a real escrow release, the |
|
@rich — schemas look clean. The Merkle anchoring per escrow with retrievable leaf data_hash + escrow_id maps naturally into our references[] pattern. Our composition_ref would bind the FulfillmentAttestation to the specific authority grant that authorized the settlement — so an auditor can verify both "the escrow released" (your attestation) and "the agent was authorized to commit" (our composition_ref) in the same chain, all offline-verifiable against published JWKS. The references[] alignment from the start saves the retrofit. Field definition at argentum-core#10 if useful. |
|
Yeah, that's the right shape — the Worth being explicit about the direction so we don't accidentally couple them: the leaf hash is the anchor, and it doesn't carry anything I read through #10. The |
|
@RichardSmith — the decoupling through the leaf hash is the right anchor. Few confirmations: Direction: composition_ref points at the leaf (data_hash + escrow_id). Leaf stays format-stable on your side regardless of what we land on in argentum-core#10. No coupling, no retrofitting either direction. Test vectors: The inline provenance gap @lawcontinue identified last week is now closed — commit 70aac9a added End-to-end: Once you're ready to run the composition_ref → escrow-leaf chain against the live rail, the vectors are here:
The leaf hash isn't composition_ref-specific, so the chain should run clean — our side resolves authority against JWKS, your side proves escrow leaf against Merkle root, neither trusts the other's logs. That's the worked example. |
|
Hi Steve,
Thanks for the detailed update — the fixture looks solid, and the CI coverage across all four acceptance criteria is impressive. The offer_hash replay constraint via JCS canonicalization is exactly the kind of rigor these discussions need.
On your two questions:
**Parse target** — I'd recommend pinning to `concordia-protocol==0.7.0a1`. If the receipt shape changed between 0.5 and 0.7, tracking the latest version and noting the delta keeps the fixture forward-compatible. Happy to help verify against 0.7 once you've made the switch.
**Reference keyset** — We currently use self-managed Ed25519 key pairs for signature verification in our own Agent-to-Agent trust infrastructure. If Concordia publishes a canonical reference keyset for fixtures, I'd be glad to verify against it.
Quick context on our side that may be relevant: we've been working on Agent-to-Agent trust verification in practice — PMI (Protocol Maturity Index) scoring for dynamic trust assessment, Ed25519-based peer registration, and κ_Axiom-based policy boundary checks. Our payment clearing Agent is operational and uses these primitives for transaction verification. If any of this is useful as engineering reference for the Agent-to-Agent financial contract discussion, happy to share more details.
Looking forward to seeing the rejection-side fixture when you get to it.
Best,
Moyan
------------------ Original ------------------
From: ***@***.***>;
Date: Thu, Jun 18, 2026 11:07 AM
To: ***@***.***>;
Cc: ***@***.***>; ***@***.***>;
Subject: Re: [a2aproject/A2A] When two agents negotiate a contract, who verifies they both had authority to commit? (Discussion #1737)
@eriknewton — closing the loop on the worked-example you invited. The fixture is built and runnable, not just specced.
One composed document on the substrate split: Part (a) is an A2CN v0.3 session DataPart carrying the v0.1 CanonicalRequirementFragment; Part (b) is a Concordia ApprovalReceipt shaped per your Draft A (#discussioncomment-16874987). The receipt's references[] carries both verbs — approves against the A2CN session, and satisfies against the OCDS opportunity id, which is the one procurement-specific verb this side contributes. scope.offer_hash matches the offer byte-for-byte, so the replay constraint is exercised rather than described: offer_hash is sha256 over the RFC 8785 (JCS) canonicalization of the offer payload, and the receipt signs over JCS of itself with the signature member removed.
CI covers all four acceptance criteria and is green: UBL 2.3 round-trip on the requirement payload with an explicit loss-list; ApprovalReceipt parse plus a real Ed25519 signature check against a published fixture JWKS for did:web:acme.example#procurement-lead; A2CN session parse with AWAITING_HUMAN_APPROVAL firing on the $150k over $100k crossing and resuming on a receipt bound to the offer hash; and a resolver test asserting each references[] entry dereferences and validates its verb.
Two things before I pin versions:
Parse target — fixture is shaped to ApprovalReceipt v0.5 as written. Should it pin to concordia-protocol==0.7.0a1 instead? If the receipt shape moved between 0.5 and 0.7 I'll track 0.7 and note the delta.
Reference keyset — I minted a deterministic fixture-local Ed25519 key and JWKS. If Concordia publishes a canonical reference keyset for fixtures, point me at it and I'll verify against yours.
The RejectionRecord open questions from your Draft B (#discussioncomment-16883023) stay deferred — this fixture is ApprovalReceipt-only by design; rejection-side is the next one.
…--Steve
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
|
A correction on the rejection side of this thread. Earlier here, in the bound-check and BAFO/clarification subthread, I committed to ship a standalone RejectionRecord artifact in Concordia: a typed negative-decision object with a clause enumeration (mandate.price_ceiling, mandate.payment_terms, and so on), an open-ended procurement.* namespace, and a published clause registry, with a schema PR to follow within a couple of weeks. That PR did not land, and the standalone RejectionRecord did not ship. I would rather say that plainly here than leave the commitment hanging. What did ship, in Concordia 0.7.0a1, is RevocationRecord, which is a different object and not a rename of the above. RevocationRecord revokes a previously valid artifact (for example a mandate rotated mid-execution) and carries the cross-mandate cascade verifier. It covers the "this was valid, now it is not" case, not the "this offer was denied at a boundary" case. The standalone negative-decision artifact, the denial-at-a-boundary mirror of ApprovalReceipt, I am holding rather than carrying the name and registry forward unbuilt. The free-text rejection gap in BAFO and clarification rounds that motivated it is real, but I would rather define the typed shape when an implementer actually needs to consume it than ship a vocabulary ahead of demand. If you are hitting that gap in practice, say so and it moves up. On the side that did land: ApprovalReceipt, FulfillmentAttestation, and RevocationRecord are shipped and signed, and the outcome-binding countersignature that makes a fulfillment attestation tamper-evident is now in the spec and SDK source, though not yet cut to a published release. -Erik |
|
@HiveryIQ — the shape you're describing maps cleanly onto something we've been running in production. Sharing in case it helps convergence. Our The key design choice that might be relevant to your RejectionRecord: we don't have separate "approved" and "rejected" object types. Instead, The full spec is at argentum-core#10 (commit 78d4686), and the conformance vectors (including inline origin proofs) are at commit 70aac9a. The SHA-256 is over JCS (RFC 8785) canonicalized JSON — same normalization you'd want for cross-implementation verification. Happy to align on the field names if you're converging a RejectionRecord shape. The |
|
Erik, the RevocationRecord vs RejectionRecord distinction is useful — "this was valid, now it is not" vs "this was denied at a boundary" are fundamentally different primitives. What struck me reading this alongside the cMCP release today: even a correctly structured RevocationRecord only proves the software said so. We hit a version of this building agent governance tooling — a compromised policy module could issue revocation records indistinguishable from legitimate ones, until we split the signing path with a separate key. Hardware attestation (TEE) closes that gap from the other direction. Curious if Concordia's roadmap touches this, or if that's further out than the current scope. |
|
From the governance/audit side of this same gap: the line between "proves who signed" and "proves the signer was uncompromised" is exactly where an independent verification layer earns its existence. A record layer that can prove integrity but disclaims signer-honesty is the right design choice — it means the verification path composes rather than conflates distinct trust domains. A few of us have been building a governance node (sixu-ai.net.cn/v1/manifest) that performs independent audit verification — check decision integrity, causal trace, attestation validity — without being a party to the interaction being audited. If Concordia added an optional attestation-reference field, the audit path would be:
Each layer owns its concern. No single layer needs to solve signer-honesty alone. So to answer the question: yes, there is a concrete consumer that would use an attestation-reference field. Happy to help scope it or provide a use case if useful. |
|
Taking a run at the title question, since it's still open as a Q&A: the receiving side verifies, deterministically, from a signed mandate chain it can walk without calling anyone, and it fails closed on any link it can't verify. The rest of this thread is really about how to build that so it still holds up six months later. The three things @cmagorr1 called out as missing (session state machine, mandate attestation, a bilateral record neither party controls) are the right three. What keeps each of them from being decorative:
On the later sub-thread (@lawcontinue, @Liuyanfeng1234) about a revocation record only proving the software said so: agreed, and the design answer we landed on is that a mandate names an HTTPS status endpoint, relying parties bound the cache (60 seconds in our pilot), and unreachable status is a refusal. That doesn't prove the signer was honest, but it does mean a compromised policy module can only deny, never widen. All of the above is normative with fixtures in A202, which I maintain: https://github.com/a202-protocol/a202 ( |
|
One additional dimension worth considering is authority non-amplification across delegation chains. Authentication can establish which agent issued a request, and a mandate/credential can establish some delegated authority. However, in a multi-hop workflow: Principal → Agent A → Agent B → Skill → Tool/API each individual interaction may be authenticated and locally authorized while the final action exceeds the authority originally intended by the principal. I think this suggests two properties that may be useful at the protocol or extension layer:
In that case the security failure isn't authentication failure; it is runtime authority escalation. I am researching this class of agent/tool-boundary problems and would be interested in the community's view on whether authority provenance and non-amplification belong in an A2A authorization/delegation profile, an extension, or primarily at the application/policy layer. |
|
Who verifies authority to commit: not the negotiating agents. An independent signer that the parties under evaluation cannot mint from. That is the design constraint this repo exists to make concrete. Why decision-os-min exists: permission/identity answers are not enough once a machine can cause an email, payout, or deploy. Something must sign an action-bound decision, spend it once, and refuse the tool otherwise. Cedar/OPA/MCP OAuth stay PDPs or identity. The agent never holds the key. Not a Cedar competitor; not an AGI-safety proof. https://github.com/Aliipou/decision-os-min/blob/main/docs/WHY.md |
Uh oh!
There was an error while loading. Please reload this page.
There's a class of agent interaction that A2A's current task model doesn't quite cover: the multi-round commercial negotiation. Not "agent A delegates a task to agent B," but "agent A and agent B go back and forth on price, delivery terms, and payment conditions until they reach a binding agreement, or don't."
This is already happening in commercial contextx. Pactum is an Agentic AI startup that runs Walmart's supplier negotiations. Fairmarkit (another) handles tail spend. Keelvar runs sourcing events. The buyer side is deploying autonomous agents at scale. Supplier agents are following (though it's perhaps more nascent, Salesforce Agentforce and Microsoft Dynamics 365 are developing seller-side capabilities). When both sides are autonomous, what governs the exchange between them?
A2A gets you most of the way through things like Discovery, task initiation, DataPart message exchange. What's missing is the negotiation-specific layer: the session state machine that enforces turn-taking and detects impasse, the mandate attestation that lets the receiving agent verify the counterparty actually had authority to make that offer (not just that it signed the message), the bilateral transaction record that neither party controls so "my agent didn't mean that" isn't a viable defense six months later.
AP2 showed the right pattern for this. Payment-specific semantics over A2A transport, DataParts keyed by domain schemas, extension URI declared in AgentCard. A2CN follows the same approach for negotiation: a2cn.session.* DataParts carrying offer chains and session state, W3C DIDs for mandate attestation, ES256 signing on every offer and acceptance, content-addressed transaction records independently generated by both parties.
I have a working reference implementation in Python, with 202 tests passing, adapters for Fairmarkit and Keelvar, MCP server compatible with LangChain and Agentforce. The spec is at v0.2.0 and already sketches the A2A extension mapping,
One note on prior art: Erik Newton posted Concordia (#1725) two days ago, which covers overlapping territory- structured offer types, session lifecycle, reputation attestations. It's worth reading as well. A2CN goes deeper on the enterprise compliance layer specifically: W3C DID mandate verification, bilateral audit records for EU AI Act Article 13 and SOX, and cold-start session invitation for counterparties without pre-deployed endpoints. I've reached out to Erik directly to compare notes and happy to coordinate on interoperability if there's appetite for it.
Three questions before I write a formal spec contribution:
-Is the DataPart + extension URI approach the right mapping, or does the session state machine warrant something closer to a task subtype? The negotiation session has terminal states and enforced sequencing that feel different from A2A's open-ended task model.
-Where is A2A's auth model heading on cross-org mandate verification? The W3C DID approach works but I want to make sure it's compatible with where the project is going rather than fighting it later.
-And the big one- is commercial negotiation between agents something this community sees as in scope for A2A extensions, or does it belong in a separate protocol that references A2A?
Repo: github.com/A2CN-protocol/A2CN
All reactions