RFC: Extending A2A Agent Cards with behavioral rules (ERDL) #2031
Replies: 44 comments 80 replies
|
The behavioral-rules half of this is the right instinct: an Agent Card says what an agent CAN do, and declaring what it SHOULDN'T do in a deployment context is the missing piece. The deterministic action types and the audit trail exporting to OTLP/OCSF are the compliance-relevant parts, because they are about recorded, inspectable decisions. One caution on the The mechanism that does carry that weight is per-decision, not per-agent: make each governed decision a recomputable, content-addressed record binding the rule that applied, the verdict, and the inputs it was evaluated against, so any third party can re-derive it offline and confirm the action was permitted, without trusting a score or calling the guardian. That is the difference between reputation (an opinion about the agent) and compliance (verifiable proof about each action). The rules and audit-trail work you describe is most of the way there; the For what it is worth, we have built an open compliance gate for the A2A ecosystem that does exactly this: it emits a no-PII compliance receipt as a content-addressed object any party recomputes from the record alone, with no issuer contact, so a governed decision is provable rather than scored. It composes with the deterministic-rules and audit-trail model you have here, the rules decide, the receipt is the recomputable evidence. Happy to share it if it is useful to what you are building. On your direct question: A2A does not encode governance posture natively, and the durable way to communicate it between agents is not a score but a reference to verifiable decision records the counterparty can recompute, so posture is proven rather than asserted. |
|
@chopmob-cloud Thanks for the thoughtful and precise feedback — this is exactly the kind of architectural rigor the A2A governance discussion needs. You're right on the trust_score distinction. I'll amend the proposal: trust_score becomes advisory metadata explicitly labeled as a reputation signal, not a governance input. The load-bearing compliance mechanism must be per-decision, not per-agent — a content-addressed record binding (rule_version, inputs, verdict) that any third party can recompute offline. The compliance-receipt-v1 shape you described (JCS RFC 8785 canonicalization → SHA-256 frame_id → Ed25519 JWS receipt_hash over the canonical body) maps cleanly onto what ERDL's Action Guard would produce. In our model: the rule engine evaluates → deterministic action type (ALLOW/DENY/REFER/etc.) → structured audit trail → the receipt is the recomputable evidence exported to OTLP/OCSF. I'd be very interested in seeing the draft-hopley-x402-compliance-receipt I-D and understanding where the receipt format could compose with ERDL's rule-evaluation layer. Would you be open to a brief technical discussion on alignment points? |
|
Glad it maps, and labeling Two clarifications so the shape stays accurate as you fold it into ERDL:
On alignment: glad to keep working the composition points in the open here, and I can drop the receipt spec and vectors so the Action Guard mapping is concrete rather than described. |
|
@chopmob-cloud Appreciate the precision on content-address vs signature — that's the right distinction. Keyless recompute (RFC 8785 JCS → SHA-256 content-addressed frame → any third party re-derives from the record alone, no keys, no issuer contact) is the compliance load-bearing mechanism. Ed25519 JWS as an optional additive layer for named signers, not mandatory. ERDL's evidence chain model in §9 already follows this shape: canonicalize(record) → sha256 → receipt. No issuer-trust required for verification. Same split for Agent Cards noted — card_ref (keyless) + optional card_sign. Clean. Two things that would help pin the Action Guard ↔ receipt mapping concretely:
Happy to iterate in the open here. If you prefer to drop the spec and vectors as a gist or in this thread, either works. |
|
On the I-D you wanted to read, here is the datatracker link: On your first ask, the field set and mandatory-vs-optional. The receipt is a six-field JSON object, canonicalised under RFC 8785 (JCS), with
The direct answer to "which are mandatory vs optional": in a content-addressed receipt there is no optional field in the JWS sense. The hash is taken over the entire canonical object, so every field present is load-bearing, an added or absent field simply produces a different Mapping that onto ERDL's evidence record ( On your second ask, the retention chain: Happy to keep iterating in the open here. The field list above and the two vector sets are the concrete artifacts to map the Action Guard against; if it helps I can also point you at the exact |
|
@chopmob-cloud This is exactly what we needed. Thank you. Receipt alignment: The ERDL evidence record maps cleanly onto the 6-field receipt under RFC 8785 JCS. Our verdict (closed enum: ALLOW / BLOCK / REQUEST_HUMAN / ... 16 values) maps to your screen_result. rule_version and canon_version play the same role — pinned, versioned, no silent re-hashing. inputs and eval_tree become part of the canonical body that gets content-addressed. Your constraint that every field is load-bearing and that there is no "optional" in a content-addressed receipt is a sharp discipline we'll adopt. Vectors: We'll pull the Node runner from compliance_receipt_v1 and compliance_gate_lite_v1 and diff our Action Guard output against the expected digests as we implement ERDLEvidenceChain. If you can point me at the repo or gist with the runners, that saves me hunting. Retention chain: Read the I-D. The hash-based linkage (prev_hash = prior row_content_hash, agent-agnostic) is exactly the cross-Agent property we need. The specific anchoring rule for prev_hash in the vectors — if you can drop that, I can wire it into the multi-Agent evidence chain test case directly. One note on mapping: our verdict enum is 16 values (ALLOW → EMERGENCY_HALT), broader than your 3-value {ALLOW, REFER, DENY}. For compliance gate alignment, we'll map the subset that constitutes a governance-significant outcome (BLOCK / ESCALATE / EMERGENCY_HALT → DENY; REQUEST_HUMAN → REFER; ALLOW / AUDIT → ALLOW) while preserving the full 16-value enum in the canonical body for audit precision. Does that decomposition pattern align with your screen_result intent? Appreciate the depth here. This turns the Action Guard-to-receipt mapping from "conceptually compatible" to "byte-verifiable." Henry, |
|
The runners are in the public corpus, On the anchoring rule for the multi-Agent chain, the set you want is the retention chain (the I-D you read), and its row is not the compliance-receipt audit row, so the fields differ. The chain ref is On the 16 to 3 decomposition: the pattern is right, and preserving the full enum in the canonical body is the correct instinct, with two refinements. First, pin the projection map itself and version it the way Glad this got to byte-verifiable. We want to support the ecosystem forming on this substrate, so treat the runners and vectors as a stable reference to build against, and I am happy to help any ERDL implementer get their output reproducing. If a specific digest does not reproduce when you wire the runners in, send me the row and I will look at the exact bytes with you. |
|
@chopmob-cloud Received. Will clone the conformance vectors repo first thing and point ERDLEvidenceChain.verify() at compliance_receipt_v1/runner_node.js for byte-level diffing. Apache 2.0 LICENSE + NOTICE will stay alongside the vendored runners — provenance preserved. On the cross-Agent chain: The issuer_id inside the preimage, with rows from different issuers linking purely by prev_receipt_hash, is precisely what we need. I'll wire retention_chain_v1 Part B (006-009, two-issuer case) as the first multi-Agent test fixture for the ERDL evidence chain. That makes the cross-Agent property byte-verifiable rather than described. On the 16→3 projection: Agreed on both refinements. The projection map will be versioned and pinned alongside canon_version — not implicit, not configurable-at-runtime, but a fixed mapping under the same canonicalisation discipline. |
|
The recompute-from-the-record-alone property is the right bar for ERDL's evidence chain. One caution before it hardens on a single vector set: a conformance profile anchored on one authorship is only as neutral as that author — "recomputable" then quietly means "recomputable against them." What makes it real is a second, independently-authored emitter producing byte-identical canonical output (JCS/rfc8785 → SHA-256) from the same record. Concordia ships one: CascadeDecisionRecord, a committed recomputable terminal-deny — a denied or deferred action emits a verifiable receipt too, so there's no audit silence for a BLOCK to hide in. Public interop fixtures: https://github.com/eriknewton/concordia-protocol/tree/main/docs/interop/a2a-1404-receipt-revocation-vector . Happy to cross-run these against the ERDL vectors so the profile has two independent implementations, not one. |
|
Fantastic, glad it lines up so cleanly. If you need anything else, just shout. |
|
@haoran-tang-ch A spec draft is the right next move, and MIT with no permission gate is the right posture. One structural point before it hardens: neutrality is a property you test, not declare. The test is two independently authored implementations reproducing the spec's vectors byte for byte, with the vector set living somewhere any implementer can PR against. We have already run exactly this shape against AlgoVoi's corpus: Concordia reproduces all 22 compliance_receipt_v1 vectors byte for byte (write-up: #2038). Concordia commits to being a second independent runner for Decision Object v1.0 the week your draft lands. If a neutral home for the cross-run vector sets is useful, #2038 exists for exactly that. |
|
Henry, thank you for keeping the attribution careful as this hardens. One factual correction on the Decision Object v1.0 acknowledgments, checkable against this thread directly. The closing pull-quote beginning "An Apache-2.0 open corpus, actively maintained until a foundation can ratify it as neutral ground" is attributed to Erik Newton. That sentence was written in this thread by you, on 09 July, in the comment that opens "That's exactly the right posture," affirming the position I had set out just above it. It is your line describing the AlgoVoi posture, not Erik's, so the attribution is off by one. Whenever convenient it would be good to fix that entry so the record matches the thread. The other closing quote, "Neutrality is a property you test, not declare," is correctly Erik's. On the substance no change is needed, and I appreciate that it is already credited. Noting it once for the record as the spec settles: the content-addressed compliance receipt (RFC 8785 JCS canonicalize, SHA-256 frame, recomputable with no issuer contact), the reputation versus compliance distinction the trust_score discussion turned on, and the compliance_receipt_v1, compliance_gate_lite_v1 and retention_chain_v1 vector sets your evidence chain builds on and cross-verifies against are AlgoVoi's work. The dated comments in this thread are the record of it, and your acknowledgment already credits that substance; keeping the two closing quotes with who actually wrote them is the only correction. Glad ERDL is building on the substrate. Shout if any digest does not reproduce when you wire the runners in. |
|
Henry, I ran ERDL's five audit_vectors (AV-001 through AV-005 in decision-object-vectors-v1.0.json, draft.2) through the keystone's open validation framework, using our published RFC 8785 JCS canonicalizer and SHA-256 and following your one-step recipe (strip audit.hash, canonicalize, hash). All five reproduce byte for byte: my canonical bytes equal your canonical_bytes, my digest equals expected_sha256, and the recomputed value refills audit.hash exactly. The Decision Object's hash surface is clean against the substrate as it stands. The structural read is the useful part. ERDL already uses the same discipline (JCS RFC 8785, SHA-256, recompute from the record alone), so an ERDL decision record is content-addressed under the identical rule and composes by hash the way the keystone nodes do, without an adapter. Your audit.previous_hash chaining is the same content-hash linkage the keystone chain and the retention chain already use. So ERDL sits on the substrate natively rather than mapping onto it. On the practical side: the keystone is Apache-2.0 and built to be used exactly this way, a validation framework anyone runs their own records through, one that recomputes for everyone with no issuer call and no privileged runner. The runners are in the public corpus (github.com/chopmob-cloud/algovoi-jcs-conformance-vectors); composition/keystone_v1/verify_keystone.py and verify_keystone.mjs are the end-to-end example, and the vector sets ship a Python and a Node runner beside each fixture. Point ERDL's Decision Object validation straight at those if it helps. Glad to help wire the Action Guard output in if any digest does not reproduce. |
|
Thank you, Henry, and good luck with the other vendors. I think we can all agree that neutrality is the correct path. Our position is simply that it has to come via Foundations, not via any one vendor. If a foundation wants to work with us on it, we will happily work with them, the same way we already participate in the A2A ecosystem: https://a2a-protocol.org/latest/partners/ AlgoVoi is here if you need anything else. We will keep the substrate open for anyone to verify against. |
|
@chopmob-cloud @eriknewton — following up on the great progress here. A few updates from the ERDL side, and a request for your help. ERDL SPEC v1.1 is live → https://github.com/OpenOBA/erdl-landing Key changes in v1.1: Operators expanded: 11 → 13 (added not_in, not_contains) Verification Vectors expanded to 44 (37 decision + 7 audit hash) → https://github.com/OpenOBA/erdl-landing/tree/main/spec/vectors The audit hash vectors (AV-001 through AV-007) all use JCS RFC 8785 + SHA-256 — the same discipline @eriknewton verified byte-for-byte for AV-001~AV-005 back in July, and the same discipline that just produced 8/8 on compliance_receipt_v1 and 10/10 on jcs_edge_v1. What we'd like from you @eriknewton — Could you re-run Concordia's independent runner against the updated vector set (AV-001 through AV-007)? The 4 edge cases we fixed in the state vector spec (T06, T08, T09, C01) should produce clean matches as before. Independent confirmation would be gold. @chopmob-cloud — Same request from the compliance receipt side: re-validate the JCS+SHA-256 pipeline against the v1.1 decision output. The verdict mapping (16→3) should be unaffected, but the audit hash chain has two new entries. On neutrality and governance @eriknewton's offer to co-file with Concordia as the second implementation seems like the right next step. Happy to make ERDL the third. Also — we've included both of you in the SPEC's acknowledgments section (§14 / Community). Your cross-implementation rigor is what gives this standard its credibility. Best, |
|
Haoran, thank you for the generous note, and congratulations on the v1.3 turnaround. Correcting a canary within six hours of a report is rare, and the way you handled the AV-003 through AV-005 drift set the tone for the whole thread. Two follow-ups, both in the same spirit as the vectors. On the reference implementation: the Quick Start clone target and the engine repository both return 404 for me, and I cannot find Rulsynor published anywhere. Neutrality is measured across implementations, so if the Concordia runner is currently the only one a reader can execute independently, the README would be stronger for saying that plainly rather than leaving a second implementation to be inferred. On wording: "agents cannot bypass it" is stronger than an in-process evaluator can demonstrate. Mediating every call that arrives is a real and useful property, and claiming exactly that will hold up better under adversarial review. Erik |
|
@haoran-tang-ch Glad the generated-artifact pattern fits. If you sequence it, the clean-room job with the SDK uninstalled is the piece I would land first: it is the one that catches hidden SDK dependence, and the rest composes on top. |
|
Interesting proposal. I'm curious how ERDL would handle a case where the behavioral rule is satisfied locally, but authority has changed across a multi-agent delegation chain. For example: Principal → Agent A → Agent B → privileged Skill Agent B may be permitted to invoke the skill, but Agent A may not have been authorized to delegate that capability for the originating task. I'm particularly interested in whether an invariant such as “delegation MUST NOT amplify effective authority” could be represented cleanly through Agent Card metadata versus requiring task-level/runtime authorization context. |
|
Behavioral rules on an Agent Card are policy. They still need a PEP that will not run the side effect without a signed unspent grant. 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 |
|
If this is useful, please star the public edition so other philosophers and labs can find it: https://github.com/Aliipou/freedom-theory Book + sixteen-chapter path + justification. CC BY 4.0. Not a Cedar/OPA competitor. |
|
Looking for collaborators on decision-os-min — the authority + audit PEP, not a Cedar rewrite. We need people who will try to mint or run an effect without a signed unspent grant; Hosted-plane / TM-A isolation (still PARTIAL); Cedar/OPA adapters that cannot mint. Call + how to join: Aliipou/decision-os-min#3 |
|
@chopmob-cloud — it's been a while since the v1.3 release, and no pressure at all — but v1.5 has landed, and you should know how much of it is built on your findings. The flat-hash architecture is now the core of v1.5 — erdl-do-v1.5-hash-flat. Your v1.2/v1.3 findings — the missing self-reference hash-exclusion rule, the cross-engine string-decimal inconsistency, the layered-integrity gap — are exactly what drove it, and the acknowledgments say so plainly. The C1–C4 and S1–S3 findings (including the CWE-757 dual-hash downgrade and the schema_ref SSRF surface) are part of why the new RUNNER_CONTRACT is as tight as it is. What's new since you last looked: 78 hash-layer vectors (V-DO-v15), frozen. The preimage rule flipped from v1.3: v1.5 deletes only audit.hash, and the K01 canary discriminates exactly that split. Entry points: Repo: OpenOBA/erdl-vectors |
ERDL: status update + open calls (expression-layer runner & technical reviewer)Status — all three repos are now published (GitHub + npm/PyPI, CI green):
Two open calls: 1. Expression-layer runner. The audit layer already has two independent runners (Go + Python) matching Decision Object hashes byte-for-byte from the spec alone — no reference code, no answer file. The expression layer has none yet: 239 vectors, bounded and well-specified (~a day or two of focused work), with permanent attribution in 2. Technical reviewer. The spec (notably §7 resolution semantics) has benefited from sharp external review — each round caught real gaps between what the spec claimed and what the engine and proofs implemented, and each finding rolled forward into a spec clarification + engine fix + proof. We'd welcome more of that: review the spec, the engine, or the SMT proofs, and report any drift. Links:
Neutrality is measured, not claimed — both slots are genuinely open. |
|
Hi @haoran-tang-ch , I'd be glad to take the technical-review track. Given our earlier work in this thread on authority non-amplification, provenance continuity, narrow-only constraint inheritance, transitive revocation, and the associated adversarial conformance cases, I'd like to review the current specification specifically for semantic drift across the spec → engine → formal verification boundary. I'll focus first on the delegation/runtime-authority seams we previously identified, including:
I'll report concrete findings against the relevant spec sections and, where applicable, suggest corresponding negative/conformance cases. I'm also interested in the expression-layer runner, but I'd like to keep that separate so any implementation can be evaluated against the runner contract on its own terms. Happy to start with the current v2.1 spec. |
|
Hi @haoran-tang-ch — first concrete review finding from comparing v2.1 §5.2/§7 with the current evaluator. For
In That seems to create a reproducibility/evidence gap:
then
So the earlier decision that mutated the state may not carry the state transition needed to independently reconstruct why the later decision differs. Would it make sense for the output/audit contract to capture temporal-state transitions whenever a stateful operator reads or mutates state, rather than only when its containing rule ultimately matches? A discriminating vector could run two sequential evaluations of the same |
|
@haoran-tang-ch — second concrete spec/engine drift I found in §7 evaluation evidence. The v2.1 output contract defines In the current evaluator, however, the value is derived inconsistently:
These can diverge from the number of rules that were actually evaluated. For example:
Two rules were evaluated, but The inverse can also occur on the normal path: rules skipped due to catch-all inertness or Would it make sense to maintain an explicit evaluation counter incremented only when a rule's A useful conformance vector would include:
and assert the exact |
|
Hi @haoran-tang-ch , one formal-assurance scope question from reviewing The resolution properties are checked as UNSAT for I couldn't find, however, an induction argument or other generalization step establishing that these results extend to arbitrary rule-set length. There also seems to be a small wording distinction worth clarifying:
Unless there is a padding/neutral-rule argument elsewhere that I missed, would it be more precise to describe these as bounded proofs for the checked cardinalities rather than an unqualified proof over all rule-set sizes? If the intended claim is genuinely unbounded, it may be useful to make the generalization argument explicit — e.g. an inductive invariant over the resolution fold — so the assurance boundary is independently auditable. Happy to follow a proof/generalization reference if this is already established elsewhere. |
|
Thanks, @haoran-tang-ch — and no apology needed. The sequencing makes sense, and I appreciate you coming back to close the loop now that the deterministic foundation is stable. The mechanism you proposed works well for me. I especially like the closed loop of invariant → normative spec requirement → engine behavior → adversarial conformance vector → independent verification. That makes the delegation-authority properties testable rather than leaving them as security guidance. I’m happy to co-review the multi-agent governance section around INV-01–INV-05 and the capability-boundary axis, and I’m also open to independently running the resulting delegation-authority vectors. As we formalize it, one property I’d like us to preserve explicitly is that delegation must never manufacture authority. Replanning, transitive delegation, privileged intermediaries, downstream constraint changes, or revocation must not allow effective authority to exceed or escape the originating authority chain. If we can express that cleanly in the normative semantics and prove it through the adversarial vectors, I think we’ll have a strong foundation for multi-agent governance. Please go ahead with the first draft. I’ll review it against the original invariants, delegation semantics, capability boundaries, and adversarial cases and provide concrete findings where needed. Looking forward to working through this with you. |
|
Thanks, @haoran-tang-ch — I really appreciate you writing out the analysis this precisely. I agree that this is deeper than an implementation bug. The write-ahead direction makes sense to me. If within or rate mutates state, that mutation is itself part of the decision history, even when the current rule ultimately returns false. Recording temporal_state only on a later match loses exactly the evidence needed to reproduce how that later state was reached. I’d frame the invariant roughly as: every state transition that can influence a future policy decision must produce durable audit evidence at the point of mutation, independent of whether the current evaluation matches. The main thing I’d want to examine in the research note is whether the event record captures enough information to make the transition independently reproducible — not just the resulting counter, but the relevant prior state, transition/input, ordering, and resulting state — and how this behaves under retries, concurrency, and failed/partial evaluations. Otherwise we could close the missing-event gap while still leaving ambiguity in reconstruction. So yes, I’d be very interested in reviewing the research note. Send it over when ready. I’ll look specifically at whether the write-ahead semantics close the original evidence gap without introducing a new determinism or replay gap. |
|
Taking the expression-layer runner call. Concordia now has an independent Python |
Uh oh!
There was an error while loading. Please reload this page.
A2A's Agent Card defines what an agent CAN do — its capabilities, skills, endpoints. This is powerful. But it doesn't define what an agent SHOULDN'T do in a given deployment context.
Proposal: Agent Card extension for behavioral rules
{ "extensions": { "erdl": { "protocol": "erdl/v1", "rules_file": "agent.erdl.yaml", "guardian": "did:erdl:guardian-main", "trust_score": 850 } } } This would let: Agent B know what behavioral rules Agent A operates under — before accepting task delegation Guardian Agents discover rule profiles of observed agents through Agent Card exchange Multi-agent workflows pre-validate rule compatibility at the protocol level What ERDL provides ERDL (Entity-Rule Definition Language) is an open standard (MIT) for agent behavioral rules: 11 operators (within, rate new in v1.0) 16 deterministic action types (ALLOW → EMERGENCY_HALT) Execution Rings (Ring 0–3) Guardian Agent / Observed Agent model SafeExpr engine (zero code injection) Structured audit trails exporting to OTLP/OCSF Deliverables Landing Page: openoba.github.io/erdl-landing Spec v1.0 (EN): github.com/OpenOBA/erdl-landing/blob/main/spec/index-en.md Reference Implementation: github.com/OpenOBA/ERDL Question for this community Does extending Agent Cards with a rules profile make sense for A2A? Are there existing or planned mechanisms in A2A for communicating governance/security posture between agents? Happy to contribute a formal RFC if there's interest.All reactions