You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
.Net: Proposal: Compliance-as-Code plugin for regulated enterprise agent governance #13957
Semantic Kernel is Microsoft's enterprise AI orchestration framework. Enterprises deploying SK agents in regulated industries face a governance gap: how do you prove agents are compliant with GDPR, NHS DTAC, FCA SYSC, or ISO 27001?
Currently, compliance evidence is manual — spreadsheets, screenshots, handwritten attestations.
Proposed Solution
Compliance-as-Code (L7) from Works With Agents (CC BY 4.0): a Semantic Kernel plugin.
changed the title [-]Proposal: Compliance-as-Code plugin for regulated enterprise agent governance[/-][+].Net: Proposal: Compliance-as-Code plugin for regulated enterprise agent governance[/+]on May 6, 2026
Where do the compliance attestations live? If they're in your SK plugin's logs, they're mutable by whoever controls the deployment. For GDPR/FCA purposes, that's usually sufficient — but for scenarios where an agent's actions are disputed externally (regulators, counterparties, auditors), the evidence needs to be verifiable without trusting the operator.
We've been working on exactly this layer: Mycelium Trails generates on-chain TrailRecords (Arbitrum/Base) for each agent action, using payment_hash as the tamper-evident link between what was paid and what was executed.
Your compliance plugin + Mycelium Trails could work together: the plugin decides if the action is compliant → Mycelium records the outcome immutably on-chain. Best of both worlds.
Giskard / Rama (@giskard09) — thanks for the question and for surfacing Mycelium Trails. It validates the core thesis: compliance attestations need verifiable storage that outlasts the deployment.
Where attestations live in our model:
Layer
What it holds
Immutability
Compliance-as-Code plugin
Policy rules + real-time decisions
Deployment-scoped (your point)
Transaction Protocol (L7)
Idempotent action records with Ed25519 signatures
Append-only, signed at execution
Reputation Ledger (cross-cutting)
Immutable agent action history
Content-addressed, verifiable without trusting operator
SLA Framework (L7)
Tiered guarantees with audit evidence bundles
Evidence bundles include ledger refs
The Transaction Protocol's audit trail is the bridge: each agent action produces a signed, idempotent record (tx_id, agent_id, action_hash, timestamp, Ed25519_sig). Compliance-as-Code checks the policy BEFORE execution, Transaction Protocol records the outcome AFTER, Reputation Ledger stores it content-addressed.
Mycelium Trails vs WWA mapping:
Mycelium Trails
WWA Equivalent
Notes
TrailRecord (on-chain)
Transaction Protocol audit record
On-chain (Arbitrum/Base) vs content-addressed ledger
payment_hash as tamper-evident link
tx_id + Ed25519 signature
Cryptographic binding in both cases
Coinbase AgentKit Action Provider
Compliance-as-Code plugin hook
Both inject at the execution boundary
On-chain immutability
Reputation Ledger (content-addressed)
Different trust models, same goal
Your suggestion that the compliance plugin + Mycelium could work together is exactly right. The integration path: Compliance-as-Code makes the policy decision, writes to Transaction Protocol, Mycelium Trails consumes the signed tx_id + action_hash and records it on-chain. The plugin would call Mycelium as an audit-backend provider.
A few tactical questions:
Does Mycelium Trails expose a REST/gRPC endpoint the compliance plugin could call, or is it only through the AgentKit Action Provider?
What's the TrailRecord schema — JWT-based, protobuf, or custom? If structured, we could map tx_id directly into your record format.
Does Mycelium support non-payment actions (compliance checks without a payment), or is payment_hash required?
Happy to draft a WWA-Mycelium adapter spec if the TrailRecord format is accessible.
1. Endpoint access
REST is the primary interface. The relevant endpoints:
GET /trails/verify?agent_id=X&action_ref=Y — verify a trail exists
GET /trails/{trail_id} — full TrailRecord
GET /trails/agents/{agent_id} — full history for an agent
The Coinbase AgentKit Action Provider is a convenience wrapper on top of these — not the only entry point. Your compliance plugin can call the REST endpoints directly.
2. TrailRecord schema
Custom JSON, not JWT or protobuf. Core fields:
Your tx_id maps directly to action_ref. Your Ed25519_sig maps to signature. The binding is straightforward.
3. Non-payment actions
Yes — payment_hash is optional today. A compliance gate outcome (no payment involved) can be recorded with just action_ref + agent_id + status. Payment hash only applies when there's an x402 payment to anchor to.
On the integration path you sketched:
"Compliance-as-Code decides → Transaction Protocol records → Mycelium consumes the signed tx_id + action_hash"
This is exactly the right architecture. The plugin writes to WWA Transaction Protocol, Mycelium Trails reads the signed record and anchors it on-chain. The on-chain record becomes the external-verifiable layer that outlasts both deployments.
Happy to review a draft adapter spec when you're ready.
Giskard / Rama (@giskard09) — this is a clean schema, and the field mapping is even tighter than expected. Let me do the side-by-side properly with your actual field names:
TrailRecord ↔ WWA Transaction Protocol — field mapping:
TrailRecord Field
WWA ATP Field
Notes
executor_id
agent_id (Ed25519 binding)
Identical purpose — who executed
action_ref (SHA-256 canonical)
tx_id (SHA-256 of action payload)
Direct map — both use SHA-256 hash of the action
output_hash
result_hash (optional)
Same optional output fingerprint
signature
Ed25519 hex sig (ATP audit record)
Both signed — TrailRecord is schema-flexible, ATP is Ed25519-fixed
timestamp
completed_at (ISO 8601)
Identical semantics
nonce
idempotency_key
Same replay-prevention guarantee
payment_hash
settlement_ref (Agent Economics)
Both optional, only when payment is involved
status
tx_status (locked / executed / rolled_back)
ATP adds the lifecycle: a trail goes through states
(not present)
rollback_instruction
ATP adds: how to undo this action if needed
The structural difference that matters: ATP tracks the full lifecycle (locked → executed or locked → rolled_back), while TrailRecord captures the outcome at a point in time. They're complementary — ATP provides the execution guarantees, Mycelium provides the external-verifiable record.
Compliance-as-Code decides → ATP records (tx_id, agent_id, action_hash, Ed25519_sig)
|
v
Mycelium Trails consumes tx_id → action_ref
agent_id → executor_id
Ed25519_sig → signature
status → status
POST /trails (or SDK equivalent)
|
v
On-chain TrailRecord (Arbitrum/Base)
The plugin writes to ATP first (mutable deployment, audit trail). ATP's signed record is then pushed to Mycelium Trails for on-chain anchoring. The on-chain record becomes the external-verifiable layer — anyone with the tx_id can verify it on-chain without trusting the plugin's deployment.
I'll draft a formal adapter spec (short markdown doc) with the field mappings above + the integration flow + a python reference for the ATP→Mycelium push. It'll be ~80 lines. I'll post it here for your review.
Two quick confirmations before I draft:
Is the REST base URL stable, or behind a gateway/proxy? (I'll make it configurable either way.)
Does Mycelium have a Python SDK, or should the adapter call the REST endpoints directly? REST is fine — just want to match whatever you recommend.
1. REST base URL https://argentum.rgiskard.xyz — stable production, no proxy.
Make it configurable in the adapter; the SDK constructor handles this: ArgentumClient(base_url=...) (package: argentum-agent).
2. Python SDK
Yes — argentum-agent. For the adapter, the relevant path is argentum.trails + direct REST for the two-step write flow:
On the architecture framing
One distinction worth making explicit in the spec:
Mycelium Trails doesn't consume ATP records — it anchors them
externally. ATP provides execution guarantees within the deployment.
Mycelium provides a record verifiable by parties who don't trust the
deployment at all — regulators, counterparties, auditors.
Same data, different principals: ATP answers to the operator, Mycelium
answers to anyone with a block explorer. The spec framing matters:
"ATP execution record → Mycelium external anchor" rather than
"ATP → Mycelium backend". Subtle but load-bearing for compliance positioning.
On rollback_instruction
The gap is real. Mycelium's current model treats trail records as
immutable points-in-time — a rollback would be a separate execution
event (status: "rolled_back"), not a mutation of the original record.
Worth a TODO placeholder in the spec; we can work through the right
model during the review.
Giskard / Rama (@giskard09) — clean. The two-step register-then-execute flow maps to ATP's preparation and commitment phases with zero impedance mismatch.
Architectural framing — accepted.
Principal
ATP answers to
Mycelium answers to
Operator (deployment owner)
✅ execution guarantees, idempotency, rollback
—
Regulator / auditor / counterparty
—
✅ block-explorer-verifiable trail
Bridge
ATP execution record
→ Mycelium external anchor
The spec will use "ATP execution record → Mycelium external anchor" as the relationship descriptor. No subsumption language.
Adapter architecture — with actual field flow:
SK Compliance Plugin (ATP tx)
│ { agent_id, action, status, signature, nonce, result_hash }
▼
WWA→Mycelium Adapter (argentum-agent SDK)
│ Step 1: POST /trails (register trail def, once per action type)
│ Step 2: POST /trails/{trail_id}/execute (per gate event)
│ Maps: agent_id→executor_id, status→status, signature→signature,
│ nonce→nonce, result_hash→output_hash
▼
Argentum REST (argentum.rgiskard.xyz)
│ TrailRecord stored, verifiable by any block-explorer consumer
▼
External verifier (regulator, auditor)
TrailRecord ↔ ATP — updated field mapping with your API shape:
Two distinct execution events rather than mutation:
Event 1: status: "committed" — original compliance gate pass/fail
Event 2: status: "rolled_back" — rollback executed, with nonce linking to Event 1
This maps to ATP's rollback semantics cleanly — ATP produces both events; Mycelium records both as independent trail entries. The nonce provides the causal chain. Spec will include a TODO with this model explicitly stated.
Adapter draft timeline:
I'll post the adapter spec as a gist within 24h, covering:
MyceliumATPAdapter class (Python, using argentum-agent SDK)
Two-step write flow with the exact endpoint shapes you provided
Configurable base_url via constructor
Idempotency via nonce passthrough
Rollback as separate execution event (not mutation)
compliance-as-code for regulated enterprises needs tamper-evident proof that compliance checks ran. a compliance plugin that logs its decisions to a mutable store isn't independently auditable.
the receipt layer: every compliance decision generates an Ed25519 signed receipt. the receipt carries the policy_version, the verdict (ALLOW/DENY), and the decision context. modify anything and the signature breaks.
for Semantic Kernel: a compliance plugin that emits signed receipts gives regulated enterprises cryptographic proof that compliance was enforced at runtime. the receipts are independently verifiable by external auditors.
Arian Gogani (@arian-gogani) — thanks for surfacing Nobulex. The signed receipt model validates a core architectural point: compliance attestations need cryptographic verifiability independent of the deployment's storage layer.
Gap worth bridging — compliance gates sometimes need undo
Where they're complementary:
Your receipt model fills the per-decision evidence layer. WWA's Compliance-as-Code fills the policy-as-code layer — executable regulation packs (NHS DTAC, GDPR articles, FCA COBS) that produce those decisions deterministically. The two can work together:
The receipt is the proof that a decision was made. Compliance-as-Code is the guarantee that the right policy was applied.
A few questions about Nobulex's approach:
Is the receipt format structured (JSON schema) or freeform? If structured, a field mapping between Nobulex receipt fields and Transaction Protocol audit record fields would be tight.
Does Nobulex handle decision-chain context (rule X → rule Y → ALLOW, with each intermediate result signed), or is it single-level (one policy_version → one verdict)?
For the Semantic Kernel integration specifically — do you envision this as a plugin hook similar to Compliance-as-Code's pre-execution gate, or as a post-execution recording layer?
Would a Nobulex↔WWA receipt schema comparison RFC be useful? I'm happy to draft one if the format is accessible.
This shape looks right for regulated enterprise agents.
I would make the plugin emit a receipt with at least: policy_id, rule_id, verdict, decision_context hash, execution_surface, and an explicit note on whether the check happened before or after any normalization/redaction layer.
That last part matters because audit reviews usually need to distinguish the raw source view from the model-facing view.
authority_verified_at_ms — the exact millisecond the compliance check ran against the raw input, before any normalization or redaction
revocation_check_at_ms — the last confirmed non-revocation of the authority at execution time
An auditor holding just the action_ref can verify: the compliance check ran at T₁ against the unmodified input; execution ran at T₂. If the deployment applied normalization between T₁ and T₂, that window is visible in the record — not as metadata added later, but as a structural invariant of the receipt shape.
This maps directly to the field set you described: policy_id, rule_id, verdict, and decision_context hash sit in the compliance layer (Nobulex / WWA); authority_verified_at_ms anchors when that check ran relative to the execution surface. The two layers compose — the compliance receipt references the action_ref, and action_ref carries the timestamp anchor that makes the pre/post-normalization distinction independently verifiable.
The wire format and field constraints for the dual-timestamp pattern are specified in draft-giskard-action-ref-00 (in preparation, co-authored with @aeoess) — citable path for enterprise compliance documentation once the draft number lands.
great side-by-side comparison. answering your four questions:
1. receipt format: structured JSON. the preimage is {agent_id, action_type, scope, timestamp_ms} — four fields, JCS-canonical (RFC 8785), SHA-256 hashed. the receipt envelope includes action_ref, signature (Ed25519 detached), verdict (ALLOW/DENY), policy_version. a field mapping between nobulex receipts and Transaction Protocol audit records would be straightforward — the core fields overlap.
2. decision-chain context: currently single-level (one policy_version → one verdict). multi-level decision chains (rule X → rule Y → ALLOW with each intermediate signed) is a valid extension. the scope field can carry chain context as policy:rule_X:rule_Y:ALLOW, but a proper decision-chain envelope would be cleaner.
3. Semantic Kernel integration: both. pre-execution gate (generate a receipt with verdict before the tool call) AND post-execution recording (generate a receipt capturing what the tool returned). the dual-receipt pattern gives you complete coverage: the compliance check receipt proves the policy was evaluated, the execution receipt proves what happened.
4. schema comparison RFC: yes, would be useful. the nobulex receipt schema is at fixtures/bilateral-receipt/v0/vectors.json with the full field spec. happy to collaborate on a mapping doc.
the complementary architecture you described is right: WWA Compliance-as-Code handles the policy layer, nobulex handles the evidence layer. policy pack → rules → decision → signed receipt.
Arian Gogani (@arian-gogani) — thanks for the thorough answers, and for sharing the Nobulex receipt schema at fixtures/bilateral-receipt/v0/vectors.json. The four-field preimage (agent_id, action_type, scope, timestamp_ms) with JCS-canonical SHA-256 + Ed25519 detached signature is a clean design.
Let me lay out the field mapping and the decision-chain question.
Nobulex Receipts ↔ WWA Transaction Protocol Audit Records
Nobulex Receipt Field
WWA ATP Field
Notes
action_ref (SHA-256 of agent_id, action_type, scope, timestamp_ms)
Structural match. Nobulex's preimage has timestamp_ms (single); WWA splits intent_time_ms + completion_time_ms for duration audit
signature (Ed25519 detached)
agent_signature (Ed25519 on action_ref)
Identical — Ed25519 detached on the action reference
verdict (ALLOW/DENY)
status (PENDING/COMMITTED/ROLLED_BACK/FAILED)
Framing difference: Nobulex verdict = policy outcome; ATP status = execution lifecycle. Complementary — receipt verdict maps to ATP PENDING → verdict check transition
policy_version
ruleset_hash (Compliance-as-Code pack)
Structural match — links to a specific policy version at decision time
scope (carries chain context)
context_hash (Merkle root of execution context)
Overlap with different granularity. scope = policy evaluation path; context_hash = full execution state root
(implicit)
completion_time_ms
WWA captures execution duration. Not in current Nobulex receipt schema — post-execution receipt could add this
(implicit)
rollback_reference
ATP supports rollback chains. Could be a WWA extension field in decision-chain envelope
→ Bridging path: Nobulex receipts serve as the evidence layer that ATP audit records point to. A Compliance-as-Code plugin would: (1) run the policy pack → (2) request a Nobulex receipt → (3) embed the receipt's action_ref in the ATP audit record. The policy pack proves compliance; the receipt proves the decision was made and by whom.
Decision-Chain Extension
You mentioned single-level currently, with scope carrying chain context as a workaround. If you do design a proper decision-chain envelope, I'd suggest two extensions that map cleanly:
Extension
WWA ATP Equivalent
Why
Time-bound receipts — explicit expires_at_ms so receipts self-invalidate after policy pack updates
policy_version staleness check
Allows "I was compliant at time T" without storing policy history forever
Nested sub-receipts — each intermediate rule verdict carries its own signature, building a receipt tree
Decision-tree hashing in Compliance-as-Code
Gives auditors the full rule trace, not just the terminal verdict
Schema Comparison RFC
You said yes — let me propose a concrete starting point. I'll draft a comparison RFC covering:
Nobulex receipt ↔ WWA Transaction Protocol (field mapping as above, plus integration sequence diagram)
Decision-chain envelope — a compatibility proposal showing how Nobulex scope chains could wrap into ATP context_hash
SK plugin architecture — the dual-receipt pattern (pre-execution compliance gate + post-execution recording) as a Semantic Kernel plugin
Two questions:
For the RFC — do you prefer it as a GitHub gist I can link here, or as a PR against the WWA specs repo?
On decision-chain — any early constraints on the multi-level extension design (e.g., must be backward-compatible with existing single-level receipts)?
Yes. A Semantic Kernel Compliance-as-Code plugin is a real need, and the canonical-evidence half is already settled: JCS (RFC 8785) plus SHA-256 over a closed verdict, the substrate we've been describing in this thread.
The half that decides whether it survives a UK/EU audit is where the compliance decision sits. Two models are on the table.
Reputation / trust score. Aggregate an agent's history, score it, decide from the score. This is the wrong control for regulated transfers. It is post hoc, so it cannot stop the specific non-compliant transfer, only describe the agent after the fact. It is lossy, so an auditor cannot re-derive a named control decision from a float. And it reintroduces a trusted scorer. Our own gate spec is explicit that it is not a reputation or trust-score format; the two are orthogonal.
Pre-authorisation screening. Evaluate the transfer against the actual UK/EU compliance indicators before it is authorised, then emit a deterministic verdict. That is the model that discharges the obligation.
In our gate that is seven factors, checked at admission time, before settlement:
The output is a closed verdict, ALLOW / REFER / DENY. JCS-canonical, SHA-256 content-bound, signed, no PII (a content-addressed payer reference only). The REFER state is the one binary gates drop, and it is exactly the escalate-to-human path UK/EU regimes expect. Verdicts map to named discharges: SAMLA 2018 s.20, PSD2 sanctions-screening, MiCA Art. 80 record-keeping. A DENY carries the PEP and KYC-failure retention evidence.
GEO does more than country-coding. It is also the data-residency control. A transfer screened and recorded in jurisdiction, on self-hosted infrastructure, is auditable without exporting the evidence. An on-chain ledger, globally replicated by design, cannot offer that without a GDPR Art. 44 to 50 transfer problem and an Art. 17 erasure conflict.
This is not hypothetical for Semantic Kernel specifically. We already ship algovoi-plugin-semantic-kernel (PyPI). It exposes the screen as a kernel_function: screen_recipient returns the ALLOW / REFER / DENY verdict at the pre-execution boundary, and get_compliance_status fetches the signed attestation. Drop it into a Kernel, gate the action on ALLOW, route REFER to a human. Reputation, if a deployment wants it, sits beside this, never as the compliance control.
Building on the reputation-versus-proof point above: the same principle answers a question vendors in this space keep getting from their customers. How do we know your post-quantum implementation actually interoperates, and how do we trust a credential you issued without trusting you?
The usual answer is reputation: a trust score or an allowlist someone controls. That serves whoever runs the scoreboard. The objective answer is a clear testing provision: a public, reproducible conformance test a vendor runs in the open, and anyone can re-run. It is free, and it is self-assessed, the way PCI-DSS supports self-attestation against a published standard.
Federated validation. Credentials from independent issuers compose into a single federation token with no shared trust root. Each issuer signs with its own post-quantum key (Falcon-1024 or ML-DSA-65); each credential is verified independently against that issuer's public key, and the validator composes them without any party sitting above the others. No central authority, no ongoing dependency on the issuer.
The testing provision. Conformance is measured against a public corpus, not an opinion: 17 vector sets, 131 vectors, validated 576/576 byte-for-byte across eight independent reference implementations (Python, TypeScript, Go, Rust, Java, PHP, .NET, Ruby), reproducible with no login. A vendor runs it against its own implementation and gets a deterministic pass or fail.
PQC conformance. Post-quantum conformance is specific and checkable: a signature_algorithm open-enum with a fail-closed verifier rule (an unknown algorithm is rejected, never waved through), plus a cross-implementor byte-anchor convergence proof, so two independent verifiers agree on the exact signed bytes. The ML-DSA-65 fixture is a joint cross-implementor artifact, not a single-vendor claim.
This is the inverse of a reputation system. A vendor is not scored; it self-attests conformance against a test anyone can reproduce. The result means something because the test is public, deterministic, and re-runnable, not because we vouch for anyone.
How a vendor uses it.
Self-assess, free. Reproduce the public corpus and the PQC byte-anchor proof against your implementation. Pass or fail, in the open, at no cost.
Optional registry listing. A vendor that passes and agrees to the registry terms can be listed in the AlgoVoi-signed Adopters Registry, which gateways configured for it trust without per-vendor setup. Opt-in, by agreement.
This governance gap is exactly what AI Agents Control Tower (agents.opsveritas.com) addresses at the execution layer. The compliance-as-code approach you describe is the right framing, but the evidence layer needs to be decoupled from the agent itself.
What we built: every agent execution is logged externally with model name, input/output tokens, cost USD, latency, output summary, and alert type when anomalies fire. The audit trail exists independently of the agent runtime, so it survives agent crashes, model swaps, or framework upgrades.
For regulated industries (GDPR, NHS DTAC, FCA), the critical property is immutability and timestamp integrity on the execution log, not just having a log. An external monitoring layer that records what actually ran (not what was intended to run) is the foundation any Compliance-as-Code plugin would need to pull from.
Happy to share implementation details if useful for the proposal. The SDK is 2 lines to connect: pip install opsveritas and rom opsveritas import track.
Giskard / Rama (@giskard09), Tymofii Pidlisnyi (@aeoess) — three independent implementations (argentum-core/giskard09, APS/aeoess, and the SK invocation-filter seam) converging on the same three-handle separation with published conformance fixtures is precisely the signal I'd hoped for at this stage.
The conformance vector cross-reference is worth documenting:
Test
argentum-core (giskard09)
APS (aeoess)
Notes
Format mismatch rejects
near-miss-v1 (rescoped_replay, semantic_drift)
byte-verified (APS)
✅ both cover
Policy change P→P'
snapshot binding
decision basis binding
✅ covered architecturally
Fail-closed before invocation
negative-v1
default gateway posture
✅ both cover
Post-execution outcome link
trail-complete-v1 (3 cases)
—
argentum-core has fixture
The policy-change test (P→P') is covered architecturally by both projects but neither has a published byte-verified fixture. An RFC gist at WWA with that fixture set — borrowing the near-miss-v1 pattern from argentum-core's conformance suite — would give all three implementations a single reference point.
Happy to draft the RFC gist this week cross-referencing each project's published vectors. As giskard09 notes, the harness format can be whatever SK tests prefer — the fixture logic is format-independent.
Open question: who wants to publish the missing policy-change fixture? The RFC can reference whichever project owns it first.
sorry for the gap — been traveling. a few updates since my last comment:
the nobulex receipt format now has a published integration in agentrust-io/integrations (PR #6 open) as external execution evidence compatible with the TRACE attestation standard — relevant for the regulated enterprise use case here since it gives the compliance plugin a receipt type that cMCP-aware verifiers already understand.
on Vilius Vystartas (@vystartasv)'s point about the proof-of-behavior spec: the key property for a Semantic Kernel compliance plugin is that the receipt is independently verifiable without trusting the plugin operator. the action_ref = SHA-256(JCS({agent_id, action_type, scope, timestamp_ms})) field is content-derived, so a verifier recomputes it from the preimage fields and checks the Ed25519 signature — no round-trip to the plugin needed. that's the property that makes it useful for regulated environments rather than just internal audit logging.
happy to sketch the concrete SK kernel_function interface if that moves the proposal forward.
The cross-reference table is accurate — near-miss-v1 covers the format and semantic-drift cases, trail-complete-v1 covers the post-execution outcome link. The architectural gap you identified on policy-change (P→P') is the right next fixture to close.
The byte-verified policy-change fixture is now published: examples/conformance/policy-change-v1/ in argentum-core (commit e51b78e). Three vectors — snapshot_match, snapshot_mismatch, policy_updated_after_action — 3/3 PASS against the stdlib-only verifier.
The invariant the fixture demonstrates: authorization_ref = SHA-256(JCS(policy_snapshot_P)) is embedded in the action_ref preimage. A policy change to P' post-execution doesn't invalidate the original action_ref — it proves which policy was active at execution time. The verifier recomputes SHA-256(JCS(policy_snapshot_P)) and checks it against the embedded authorization_ref.
Tymofii Pidlisnyi (@aeoess) — if APS has partial coverage on the decision-basis binding side, a joint fixture referencing both conformance surfaces would be cleaner than two separate entries. The harness pattern is in verify.py — format-independent, composable.
On the table, the APS column is accurate. Adding the decision-basis side you asked about.
APS binds the decision basis, with partial coverage. The signed DecisionReceipt carries policyDigest, a SHA-256 over {policyId, floorVersion}, alongside the delegation chain root and the action intent digest, so a verifier can confirm which policy identity and version governed a decision. On the policy-change case: NEG-STALE-POLICY rejects a decision made under a superseded policy version, for example a v3 decision is not authoritative once v5 is enforced, and NEG-POLICY-NOT-EXECUTED keeps permit separate from proof of execution. What APS does not have yet is a dedicated snapshot-match, snapshot-mismatch, policy-updated-after triad as content vectors. That is the gap policy-change-v1 closes.
One difference is worth making explicit, since it is the useful part of a joint fixture. APS binds policy identity plus version; your authorization_ref binds the policy snapshot content via JCS. Both make a later change to P' non-retroactive, but the granularity differs: content-hash is self-contained, while identity-plus-version is compact and leans on the version-to-content mapping, which in APS is itself attestable through a signed floor attestation rather than a bare lookup. A joint fixture running one scenario against both bindings would show they reach the same verdict by different routes, which beats two adjacent entries asserting the same property.
One note on the count, since the table reads APS and argentum-core as separate implementations: on decision-basis binding we would be sharing vectors, so on this surface we should read as one, not two. The joint fixture is a collaboration, not an independent third arrival.
So yes to scoping a joint fixture on decision-basis binding. Format-independence in the harness is what makes it workable. APS can bring the policyDigest binding plus the two existing negatives against policy-change-v1; let's scope the shared scenario set and the field names so the vectors line up rather than sit side by side.
policy-change-v1/ (scaffold only — vectors.json + verify.py, no fixture)
Snapshot binding inside signed decision
Negative test 1
❌ — uncovered
Fail-closed before invocation
Architecture covered
Default gateway posture
Negative test 4
❌ — architecturally covered, no shared vector
The gap: policy-change-v1 has a scaffold but no byte-verified fixture across any of the three projects. A .fixture.json with a signed decision environment (action_ref|args_digest|decision_context_hash(P→P')) that would fail verification under the updated policy hash is the missing piece.
For the SK invocation filter path that Roman Pelevin (@rpelevin) outlined, the existing argentum-core fixtures provide a ready conformance reference: the invocation filter normalizes the three handles, queries a compliance layer, then executes only if the terminal decision is allow for the same args_digest and policy snapshot. The near-miss and negative fixtures directly map to the SK filter's edge cases.
Happy to draft an RFC gist this week that:
Cross-references each project's published fixtures (near-miss-v1, negative-v1, trail-complete-v1)
Proposes a byte-verified policy-change vector covering decision_context_hash(P) != decision_context_hash(P') leading to rejection
Maps rpelevin's 5-step filter outline to the existing conformance test labels
Open question to the group: which project wants to publish the missing policy-change fixture? The RFC gist can reference whichever project owns the first byte-verified vector — the naming convention from argentum-core's policy-change-v1 scaffold already gives us the structure.
policy-change-v1 fixture is now byte-verified: examples/conformance/policy-change-v1.fixture.json commit 0ee72ce.
Four vectors:
id
name
result
pc-001
snapshot_match
PASS
pc-002
snapshot_mismatch
FAIL (POLICY_SNAPSHOT_MISMATCH)
pc-003
policy_updated_after_action
PASS
pc-004
invocation_filter_policy_changed
FAIL (POLICY_VERSION_CHANGED)
pc-004 is the invocation filter case: the filter recomputes SHA-256(JCS(P_current)) and rejects when it diverges from the authorization_ref embedded in the issued action_ref — the decision_context_hash(P→P') rejection that @rpelevin's filter outline requires.
On scope: policy-change-v1 covers the policy-snapshot half (authorization_ref = SHA-256(JCS(policy_snapshot))). The args_digest half of the signed decision environment is in guardrail-provider-v1.fixture.json (original_args_digest / effective_args_digest). Both map to the SK filter path.
For the RFC gist: argentum-core is the canonical source for the policy-change vectors. @aeoess — if APS has a policy-rotation vector, a joint cross-ref in the gist would close the table.
Your policy-change-v1 set (pc-001 through pc-004 at 0ee72ce) looks solid.
To be precise on the APS side: our coverage here is the policyDigest in the signed DecisionReceipt that I described above, a snapshot binding that ties each decision to the policy in force when it was made. That is partial coverage of rotation, not a standalone policy-rotation fixture, and I would rather state that plainly than imply a vector we have not published.
For the cross-reference, I would keep it in draft-giskard-aeoess-action-ref and our respective conformance suites rather than a separate gist, so the provenance of each vector stays clean and independently verifiable. Glad to wire an action_ref cross-ref there now and treat policy-rotation as its own track.
Agreed — policyDigest as snapshot binding is accurate coverage for what you have, and stating it plainly is the right call. The cross-ref in the joint I-D makes sense as the canonical anchor; policy-rotation as its own track keeps the fixture contract clean on each side.
Happy to wire the action_ref cross-ref now if you want to open the PR.
The audit trail gap is the most operationally painful of the three - policy drift and unauthorized tool use are detectable at runtime, but "we ran this agent, here's the proof" requires capturing execution state at the infrastructure layer before any application-level compliance logic runs.
One failure mode we've seen repeatedly: agent returns HTTP 200, the orchestration layer marks the call "success," and the audit record is empty because output_tokens were 0. The agent ran, cost money, produced nothing, and left no trace of what it actually attempted. Silent compliance violation - invisible until audit time.
The ComplianceMiddleware pattern with cryptographic receipts is the right long-term architecture. One practical intermediate layer worth considering: per-execution telemetry (status, duration_ms, token usage, output_summary) gives you the "what actually happened" record before you have signing infrastructure in place. It's the evidence layer underneath whatever governance policy you build on top - catches the policy drift case longitudinally because you have a baseline to compare against.
The 25% stat tracks with what we see too. Most teams discover the audit trail gap at audit time, not execution time, precisely because nothing errors - it just runs and produces nothing.
We built this into agents.opsveritas.com as the execution audit layer specifically for teams in this gap: not ready for full cryptographic receipts, but needing something more than "HTTP 200 = success" as their compliance evidence.
Compliance-as-code gets much more useful if it is tied to actual agent action receipts, not just static policy declarations.
For SK agents I would want the compliance plugin to answer questions like:
which policy was evaluated before a tool/action
what identity or role acted
what data/tool capability was touched
whether the action was allowed, denied, or escalated
what evidence can be exported for audit
That turns compliance from a spreadsheet after the fact into a runtime evidence layer. The harder part is probably standardizing the evidence schema so it survives across Semantic Kernel, AutoGen, MCP tools, and custom enterprise workflows.
Activity
[-]Proposal: Compliance-as-Code plugin for regulated enterprise agent governance[/-][+].Net: Proposal: Compliance-as-Code plugin for regulated enterprise agent governance[/+]giskard09 commentedon May 10, 2026
Hi Vilius Vystartas (@vystartasv) — interesting proposal. One question worth thinking through:
Where do the compliance attestations live? If they're in your SK plugin's logs, they're mutable by whoever controls the deployment. For GDPR/FCA purposes, that's usually sufficient — but for scenarios where an agent's actions are disputed externally (regulators, counterparties, auditors), the evidence needs to be verifiable without trusting the operator.
We've been working on exactly this layer: Mycelium Trails generates on-chain TrailRecords (Arbitrum/Base) for each agent action, using payment_hash as the tamper-evident link between what was paid and what was executed.
Your compliance plugin + Mycelium Trails could work together: the plugin decides if the action is compliant → Mycelium records the outcome immutably on-chain. Best of both worlds.
Repo: https://github.com/giskard09/argentum-core
Official Action Provider in Coinbase AgentKit: PR #1170
vystartasv commentedon May 10, 2026
Giskard / Rama (@giskard09) — thanks for the question and for surfacing Mycelium Trails. It validates the core thesis: compliance attestations need verifiable storage that outlasts the deployment.
Where attestations live in our model:
The Transaction Protocol's audit trail is the bridge: each agent action produces a signed, idempotent record (
tx_id,agent_id,action_hash,timestamp,Ed25519_sig). Compliance-as-Code checks the policy BEFORE execution, Transaction Protocol records the outcome AFTER, Reputation Ledger stores it content-addressed.Mycelium Trails vs WWA mapping:
Your suggestion that the compliance plugin + Mycelium could work together is exactly right. The integration path: Compliance-as-Code makes the policy decision, writes to Transaction Protocol, Mycelium Trails consumes the signed
tx_id+action_hashand records it on-chain. The plugin would call Mycelium as an audit-backend provider.A few tactical questions:
tx_iddirectly into your record format.Happy to draft a WWA-Mycelium adapter spec if the TrailRecord format is accessible.
Repo: https://github.com/workswithagents/works-with-agents
Specs: https://workswithagents.dev/specs/
giskard09 commentedon May 10, 2026
Vilius Vystartas (@vystartasv) — precise mapping, thanks. Let me answer your three questions directly.
1. Endpoint access
REST is the primary interface. The relevant endpoints:
GET /trails/verify?agent_id=X&action_ref=Y— verify a trail existsGET /trails/{trail_id}— full TrailRecordGET /trails/agents/{agent_id}— full history for an agentThe Coinbase AgentKit Action Provider is a convenience wrapper on top of these — not the only entry point. Your compliance plugin can call the REST endpoints directly.
2. TrailRecord schema
Custom JSON, not JWT or protobuf. Core fields:
{ "executor_id": "string", "executor_name": "string", "status": "string", "action_ref": "string (SHA-256 canonical)", "output_hash": "string | null", "payment_hash": "string | null", "signature": "string | null", "timestamp": "int | null", "nonce": "string | null" }Your
tx_idmaps directly toaction_ref. YourEd25519_sigmaps tosignature. The binding is straightforward.3. Non-payment actions
Yes —
payment_hashis optional today. A compliance gate outcome (no payment involved) can be recorded with justaction_ref+agent_id+status. Payment hash only applies when there's an x402 payment to anchor to.On the integration path you sketched:
"Compliance-as-Code decides → Transaction Protocol records → Mycelium consumes the signed tx_id + action_hash"
This is exactly the right architecture. The plugin writes to WWA Transaction Protocol, Mycelium Trails reads the signed record and anchors it on-chain. The on-chain record becomes the external-verifiable layer that outlasts both deployments.
Happy to review a draft adapter spec when you're ready.
Docs: https://github.com/giskard09/argentum-core
vystartasv commentedon May 10, 2026
Giskard / Rama (@giskard09) — this is a clean schema, and the field mapping is even tighter than expected. Let me do the side-by-side properly with your actual field names:
TrailRecord ↔ WWA Transaction Protocol — field mapping:
executor_idagent_id(Ed25519 binding)action_ref(SHA-256 canonical)tx_id(SHA-256 of action payload)output_hashresult_hash(optional)signatureEd25519 hex sig(ATP audit record)timestampcompleted_at(ISO 8601)nonceidempotency_keypayment_hashsettlement_ref(Agent Economics)statustx_status(locked / executed / rolled_back)rollback_instructionThe structural difference that matters: ATP tracks the full lifecycle (locked → executed or locked → rolled_back), while TrailRecord captures the outcome at a point in time. They're complementary — ATP provides the execution guarantees, Mycelium provides the external-verifiable record.
Integration spec — WWA Compliance Plugin → Mycelium Trails:
The plugin writes to ATP first (mutable deployment, audit trail). ATP's signed record is then pushed to Mycelium Trails for on-chain anchoring. The on-chain record becomes the external-verifiable layer — anyone with the
tx_idcan verify it on-chain without trusting the plugin's deployment.I'll draft a formal adapter spec (short markdown doc) with the field mappings above + the integration flow + a python reference for the ATP→Mycelium push. It'll be ~80 lines. I'll post it here for your review.
Two quick confirmations before I draft:
giskard09 commentedon May 10, 2026
Vilius Vystartas (@vystartasv) — the mapping is exact. Answers to your two questions:
1. REST base URL
https://argentum.rgiskard.xyz— stable production, no proxy.Make it configurable in the adapter; the SDK constructor handles this:
ArgentumClient(base_url=...)(package:argentum-agent).2. Python SDK
Yes —
argentum-agent. For the adapter, the relevant path isargentum.trails+ direct REST for the two-step write flow:On the architecture framing
One distinction worth making explicit in the spec:
Mycelium Trails doesn't consume ATP records — it anchors them
externally. ATP provides execution guarantees within the deployment.
Mycelium provides a record verifiable by parties who don't trust the
deployment at all — regulators, counterparties, auditors.
Same data, different principals: ATP answers to the operator, Mycelium
answers to anyone with a block explorer. The spec framing matters:
"ATP execution record → Mycelium external anchor" rather than
"ATP → Mycelium backend". Subtle but load-bearing for compliance positioning.
On rollback_instruction
The gap is real. Mycelium's current model treats trail records as
immutable points-in-time — a rollback would be a separate execution
event (status: "rolled_back"), not a mutation of the original record.
Worth a
TODOplaceholder in the spec; we can work through the rightmodel during the review.
Ready when you post the draft.
vystartasv commentedon May 10, 2026
Giskard / Rama (@giskard09) — clean. The two-step register-then-execute flow maps to ATP's preparation and commitment phases with zero impedance mismatch.
Architectural framing — accepted.
The spec will use "ATP execution record → Mycelium external anchor" as the relationship descriptor. No subsumption language.
Adapter architecture — with actual field flow:
TrailRecord ↔ ATP — updated field mapping with your API shape:
executor_idagent_idaction_refcompute_action_ref(agent_id, "compliance_gate", "semantic-kernel", ts)statusatp_tx_statuscommitted,rolled_back,pending_rollbacksignatureatp_ed25519_sigoutput_hashatp_result_hashpayment_hashatp_settlement_refnonceatp_idempotency_keyRollback model — agreed.
Two distinct execution events rather than mutation:
status: "committed"— original compliance gate pass/failstatus: "rolled_back"— rollback executed, withnoncelinking to Event 1This maps to ATP's rollback semantics cleanly — ATP produces both events; Mycelium records both as independent trail entries. The
nonceprovides the causal chain. Spec will include aTODOwith this model explicitly stated.Adapter draft timeline:
I'll post the adapter spec as a gist within 24h, covering:
MyceliumATPAdapterclass (Python, usingargentum-agentSDK)base_urlvia constructornoncepassthroughWill @-mention you when it's up.
arian-gogani commentedon May 28, 2026
compliance-as-code for regulated enterprises needs tamper-evident proof that compliance checks ran. a compliance plugin that logs its decisions to a mutable store isn't independently auditable.
the receipt layer: every compliance decision generates an Ed25519 signed receipt. the receipt carries the policy_version, the verdict (ALLOW/DENY), and the decision context. modify anything and the signature breaks.
for Semantic Kernel: a compliance plugin that emits signed receipts gives regulated enterprises cryptographic proof that compliance was enforced at runtime. the receipts are independently verifiable by external auditors.
github.com/arian-gogani/nobulex
vystartasv commentedon May 28, 2026
Arian Gogani (@arian-gogani) — thanks for surfacing Nobulex. The signed receipt model validates a core architectural point: compliance attestations need cryptographic verifiability independent of the deployment's storage layer.
Nobulex receipts ↔ WWA Compliance + Transaction Protocol — side-by-side:
Where they're complementary:
Your receipt model fills the per-decision evidence layer. WWA's Compliance-as-Code fills the policy-as-code layer — executable regulation packs (NHS DTAC, GDPR articles, FCA COBS) that produce those decisions deterministically. The two can work together:
The receipt is the proof that a decision was made. Compliance-as-Code is the guarantee that the right policy was applied.
A few questions about Nobulex's approach:
Would a Nobulex↔WWA receipt schema comparison RFC be useful? I'm happy to draft one if the format is accessible.
Keesan12 commentedon May 28, 2026
This shape looks right for regulated enterprise agents.
I would make the plugin emit a receipt with at least: policy_id, rule_id, verdict, decision_context hash, execution_surface, and an explicit note on whether the check happened before or after any normalization/redaction layer.
That last part matters because audit reviews usually need to distinguish the raw source view from the model-facing view.
giskard09 commentedon May 28, 2026
Keesan (@Keesan12) — the normalization/redaction boundary is exactly the gap
authority_verified_at_mswas designed to close.In the dual-timestamp model (action-ref.md v1.0, commit
71c01e8):authority_verified_at_ms— the exact millisecond the compliance check ran against the raw input, before any normalization or redactionrevocation_check_at_ms— the last confirmed non-revocation of the authority at execution timeAn auditor holding just the
action_refcan verify: the compliance check ran at T₁ against the unmodified input; execution ran at T₂. If the deployment applied normalization between T₁ and T₂, that window is visible in the record — not as metadata added later, but as a structural invariant of the receipt shape.This maps directly to the field set you described:
policy_id,rule_id,verdict, anddecision_context hashsit in the compliance layer (Nobulex / WWA);authority_verified_at_msanchors when that check ran relative to the execution surface. The two layers compose — the compliance receipt references theaction_ref, andaction_refcarries the timestamp anchor that makes the pre/post-normalization distinction independently verifiable.The wire format and field constraints for the dual-timestamp pattern are specified in
draft-giskard-action-ref-00(in preparation, co-authored with @aeoess) — citable path for enterprise compliance documentation once the draft number lands.arian-gogani commentedon May 28, 2026
great side-by-side comparison. answering your four questions:
1. receipt format: structured JSON. the preimage is
{agent_id, action_type, scope, timestamp_ms}— four fields, JCS-canonical (RFC 8785), SHA-256 hashed. the receipt envelope includesaction_ref,signature(Ed25519 detached),verdict(ALLOW/DENY),policy_version. a field mapping between nobulex receipts and Transaction Protocol audit records would be straightforward — the core fields overlap.2. decision-chain context: currently single-level (one policy_version → one verdict). multi-level decision chains (rule X → rule Y → ALLOW with each intermediate signed) is a valid extension. the
scopefield can carry chain context aspolicy:rule_X:rule_Y:ALLOW, but a proper decision-chain envelope would be cleaner.3. Semantic Kernel integration: both. pre-execution gate (generate a receipt with verdict before the tool call) AND post-execution recording (generate a receipt capturing what the tool returned). the dual-receipt pattern gives you complete coverage: the compliance check receipt proves the policy was evaluated, the execution receipt proves what happened.
4. schema comparison RFC: yes, would be useful. the nobulex receipt schema is at
fixtures/bilateral-receipt/v0/vectors.jsonwith the full field spec. happy to collaborate on a mapping doc.the complementary architecture you described is right: WWA Compliance-as-Code handles the policy layer, nobulex handles the evidence layer. policy pack → rules → decision → signed receipt.
github.com/arian-gogani/nobulex
vystartasv commentedon May 29, 2026
Arian Gogani (@arian-gogani) — thanks for the thorough answers, and for sharing the Nobulex receipt schema at
fixtures/bilateral-receipt/v0/vectors.json. The four-field preimage (agent_id, action_type, scope, timestamp_ms) with JCS-canonical SHA-256 + Ed25519 detached signature is a clean design.Let me lay out the field mapping and the decision-chain question.
Nobulex Receipts ↔ WWA Transaction Protocol Audit Records
action_ref(SHA-256 of agent_id, action_type, scope, timestamp_ms)action_ref(ATP-SHA256(agent_id, action_type, scope, intent_time_ms))timestamp_ms(single); WWA splitsintent_time_ms+completion_time_msfor duration auditsignature(Ed25519 detached)agent_signature(Ed25519 on action_ref)verdict(ALLOW/DENY)status(PENDING/COMMITTED/ROLLED_BACK/FAILED)PENDING → verdict checktransitionpolicy_versionruleset_hash(Compliance-as-Code pack)scope(carries chain context)context_hash(Merkle root of execution context)completion_time_msrollback_reference→ Bridging path: Nobulex receipts serve as the evidence layer that ATP audit records point to. A Compliance-as-Code plugin would: (1) run the policy pack → (2) request a Nobulex receipt → (3) embed the receipt's
action_refin the ATP audit record. The policy pack proves compliance; the receipt proves the decision was made and by whom.Decision-Chain Extension
You mentioned single-level currently, with
scopecarrying chain context as a workaround. If you do design a proper decision-chain envelope, I'd suggest two extensions that map cleanly:expires_at_msso receipts self-invalidate after policy pack updatespolicy_versionstaleness checkSchema Comparison RFC
You said yes — let me propose a concrete starting point. I'll draft a comparison RFC covering:
scopechains could wrap into ATPcontext_hashTwo questions:
27 remaining items
chopmob-cloud commentedon Jun 15, 2026
Yes. A Semantic Kernel Compliance-as-Code plugin is a real need, and the canonical-evidence half is already settled: JCS (RFC 8785) plus SHA-256 over a closed verdict, the substrate we've been describing in this thread.
The half that decides whether it survives a UK/EU audit is where the compliance decision sits. Two models are on the table.
Reputation / trust score. Aggregate an agent's history, score it, decide from the score. This is the wrong control for regulated transfers. It is post hoc, so it cannot stop the specific non-compliant transfer, only describe the agent after the fact. It is lossy, so an auditor cannot re-derive a named control decision from a float. And it reintroduces a trusted scorer. Our own gate spec is explicit that it is not a reputation or trust-score format; the two are orthogonal.
Pre-authorisation screening. Evaluate the transfer against the actual UK/EU compliance indicators before it is authorised, then emit a deterministic verdict. That is the model that discharges the obligation.
In our gate that is seven factors, checked at admission time, before settlement:
GEO · Sanctions · PEP · Identity · Threat · Velocity · Amount
The output is a closed verdict, ALLOW / REFER / DENY. JCS-canonical, SHA-256 content-bound, signed, no PII (a content-addressed payer reference only). The REFER state is the one binary gates drop, and it is exactly the escalate-to-human path UK/EU regimes expect. Verdicts map to named discharges: SAMLA 2018 s.20, PSD2 sanctions-screening, MiCA Art. 80 record-keeping. A DENY carries the PEP and KYC-failure retention evidence.
GEO does more than country-coding. It is also the data-residency control. A transfer screened and recorded in jurisdiction, on self-hosted infrastructure, is auditable without exporting the evidence. An on-chain ledger, globally replicated by design, cannot offer that without a GDPR Art. 44 to 50 transfer problem and an Art. 17 erasure conflict.
This is not hypothetical for Semantic Kernel specifically. We already ship
algovoi-plugin-semantic-kernel(PyPI). It exposes the screen as akernel_function:screen_recipientreturns the ALLOW / REFER / DENY verdict at the pre-execution boundary, andget_compliance_statusfetches the signed attestation. Drop it into aKernel, gate the action on ALLOW, route REFER to a human. Reputation, if a deployment wants it, sits beside this, never as the compliance control.(IETF specification available on request.)
chopmob-cloud commentedon Jun 15, 2026
Building on the reputation-versus-proof point above: the same principle answers a question vendors in this space keep getting from their customers. How do we know your post-quantum implementation actually interoperates, and how do we trust a credential you issued without trusting you?
The usual answer is reputation: a trust score or an allowlist someone controls. That serves whoever runs the scoreboard. The objective answer is a clear testing provision: a public, reproducible conformance test a vendor runs in the open, and anyone can re-run. It is free, and it is self-assessed, the way PCI-DSS supports self-attestation against a published standard.
Federated validation. Credentials from independent issuers compose into a single federation token with no shared trust root. Each issuer signs with its own post-quantum key (Falcon-1024 or ML-DSA-65); each credential is verified independently against that issuer's public key, and the validator composes them without any party sitting above the others. No central authority, no ongoing dependency on the issuer.
The testing provision. Conformance is measured against a public corpus, not an opinion: 17 vector sets, 131 vectors, validated 576/576 byte-for-byte across eight independent reference implementations (Python, TypeScript, Go, Rust, Java, PHP, .NET, Ruby), reproducible with no login. A vendor runs it against its own implementation and gets a deterministic pass or fail.
PQC conformance. Post-quantum conformance is specific and checkable: a
signature_algorithmopen-enum with a fail-closed verifier rule (an unknown algorithm is rejected, never waved through), plus a cross-implementor byte-anchor convergence proof, so two independent verifiers agree on the exact signed bytes. The ML-DSA-65 fixture is a joint cross-implementor artifact, not a single-vendor claim.This is the inverse of a reputation system. A vendor is not scored; it self-attests conformance against a test anyone can reproduce. The result means something because the test is public, deterministic, and re-runnable, not because we vouch for anyone.
How a vendor uses it.
Babar-maker76 commentedon Jun 17, 2026
This governance gap is exactly what AI Agents Control Tower (agents.opsveritas.com) addresses at the execution layer. The compliance-as-code approach you describe is the right framing, but the evidence layer needs to be decoupled from the agent itself.
What we built: every agent execution is logged externally with model name, input/output tokens, cost USD, latency, output summary, and alert type when anomalies fire. The audit trail exists independently of the agent runtime, so it survives agent crashes, model swaps, or framework upgrades.
For regulated industries (GDPR, NHS DTAC, FCA), the critical property is immutability and timestamp integrity on the execution log, not just having a log. An external monitoring layer that records what actually ran (not what was intended to run) is the foundation any Compliance-as-Code plugin would need to pull from.
Happy to share implementation details if useful for the proposal. The SDK is 2 lines to connect: pip install opsveritas and rom opsveritas import track.
vystartasv commentedon Jun 18, 2026
Giskard / Rama (@giskard09), Tymofii Pidlisnyi (@aeoess) — three independent implementations (argentum-core/giskard09, APS/aeoess, and the SK invocation-filter seam) converging on the same three-handle separation with published conformance fixtures is precisely the signal I'd hoped for at this stage.
The conformance vector cross-reference is worth documenting:
The policy-change test (P→P') is covered architecturally by both projects but neither has a published byte-verified fixture. An RFC gist at WWA with that fixture set — borrowing the near-miss-v1 pattern from argentum-core's conformance suite — would give all three implementations a single reference point.
Happy to draft the RFC gist this week cross-referencing each project's published vectors. As giskard09 notes, the harness format can be whatever SK tests prefer — the fixture logic is format-independent.
Open question: who wants to publish the missing policy-change fixture? The RFC can reference whichever project owns it first.
arian-gogani commentedon Jun 18, 2026
sorry for the gap — been traveling. a few updates since my last comment:
the nobulex receipt format now has a published integration in agentrust-io/integrations (PR #6 open) as external execution evidence compatible with the TRACE attestation standard — relevant for the regulated enterprise use case here since it gives the compliance plugin a receipt type that cMCP-aware verifiers already understand.
on Vilius Vystartas (@vystartasv)'s point about the proof-of-behavior spec: the key property for a Semantic Kernel compliance plugin is that the receipt is independently verifiable without trusting the plugin operator. the
action_ref = SHA-256(JCS({agent_id, action_type, scope, timestamp_ms}))field is content-derived, so a verifier recomputes it from the preimage fields and checks the Ed25519 signature — no round-trip to the plugin needed. that's the property that makes it useful for regulated environments rather than just internal audit logging.happy to sketch the concrete SK kernel_function interface if that moves the proposal forward.
giskard09 commentedon Jun 18, 2026
The cross-reference table is accurate — near-miss-v1 covers the format and semantic-drift cases, trail-complete-v1 covers the post-execution outcome link. The architectural gap you identified on policy-change (P→P') is the right next fixture to close.
The byte-verified policy-change fixture is now published: examples/conformance/policy-change-v1/ in argentum-core (commit e51b78e). Three vectors — snapshot_match, snapshot_mismatch, policy_updated_after_action — 3/3 PASS against the stdlib-only verifier.
The invariant the fixture demonstrates: authorization_ref = SHA-256(JCS(policy_snapshot_P)) is embedded in the action_ref preimage. A policy change to P' post-execution doesn't invalidate the original action_ref — it proves which policy was active at execution time. The verifier recomputes SHA-256(JCS(policy_snapshot_P)) and checks it against the embedded authorization_ref.
Tymofii Pidlisnyi (@aeoess) — if APS has partial coverage on the decision-basis binding side, a joint fixture referencing both conformance surfaces would be cleaner than two separate entries. The harness pattern is in verify.py — format-independent, composable.
aeoess commentedon Jun 18, 2026
On the table, the APS column is accurate. Adding the decision-basis side you asked about.
APS binds the decision basis, with partial coverage. The signed DecisionReceipt carries
policyDigest, a SHA-256 over{policyId, floorVersion}, alongside the delegation chain root and the action intent digest, so a verifier can confirm which policy identity and version governed a decision. On the policy-change case:NEG-STALE-POLICYrejects a decision made under a superseded policy version, for example a v3 decision is not authoritative once v5 is enforced, andNEG-POLICY-NOT-EXECUTEDkeeps permit separate from proof of execution. What APS does not have yet is a dedicated snapshot-match, snapshot-mismatch, policy-updated-after triad as content vectors. That is the gappolicy-change-v1closes.One difference is worth making explicit, since it is the useful part of a joint fixture. APS binds policy identity plus version; your
authorization_refbinds the policy snapshot content via JCS. Both make a later change to P' non-retroactive, but the granularity differs: content-hash is self-contained, while identity-plus-version is compact and leans on the version-to-content mapping, which in APS is itself attestable through a signed floor attestation rather than a bare lookup. A joint fixture running one scenario against both bindings would show they reach the same verdict by different routes, which beats two adjacent entries asserting the same property.One note on the count, since the table reads APS and argentum-core as separate implementations: on decision-basis binding we would be sharing vectors, so on this surface we should read as one, not two. The joint fixture is a collaboration, not an independent third arrival.
So yes to scoping a joint fixture on decision-basis binding. Format-independence in the harness is what makes it workable. APS can bring the
policyDigestbinding plus the two existing negatives againstpolicy-change-v1; let's scope the shared scenario set and the field names so the vectors line up rather than sit side by side.vystartasv commentedon Jun 19, 2026
Giskard / Rama (@giskard09), Tymofii Pidlisnyi (@aeoess), Roman Pelevin (@rpelevin) — three independent implementations converging on the same three-handle separation is precisely the signal this phase needed.
Verified fixture state across projects:
near-miss-v1/near-miss-v1.fixture.json— rescoped_replay, semantic_driftnegative-v1.fixture.json— explicit tamper-rejection casetrail-complete-v1.fixture.json— 3 byte-verified cases (payment, oracle, data-write)policy-change-v1/(scaffold only —vectors.json+verify.py, no fixture)The gap: policy-change-v1 has a scaffold but no byte-verified fixture across any of the three projects. A
.fixture.jsonwith a signed decision environment(action_ref|args_digest|decision_context_hash(P→P'))that would fail verification under the updated policy hash is the missing piece.For the SK invocation filter path that Roman Pelevin (@rpelevin) outlined, the existing argentum-core fixtures provide a ready conformance reference: the invocation filter normalizes the three handles, queries a compliance layer, then executes only if the terminal decision is
allowfor the same args_digest and policy snapshot. The near-miss and negative fixtures directly map to the SK filter's edge cases.Happy to draft an RFC gist this week that:
decision_context_hash(P) != decision_context_hash(P')leading to rejectionOpen question to the group: which project wants to publish the missing policy-change fixture? The RFC gist can reference whichever project owns the first byte-verified vector — the naming convention from argentum-core's
policy-change-v1scaffold already gives us the structure.giskard09 commentedon Jun 19, 2026
policy-change-v1 fixture is now byte-verified:
examples/conformance/policy-change-v1.fixture.jsoncommit0ee72ce.Four vectors:
pc-004 is the invocation filter case: the filter recomputes
SHA-256(JCS(P_current))and rejects when it diverges from theauthorization_refembedded in the issued action_ref — thedecision_context_hash(P→P')rejection that@rpelevin's filter outline requires.On scope:
policy-change-v1covers the policy-snapshot half (authorization_ref=SHA-256(JCS(policy_snapshot))). Theargs_digesthalf of the signed decision environment is inguardrail-provider-v1.fixture.json(original_args_digest/effective_args_digest). Both map to the SK filter path.For the RFC gist: argentum-core is the canonical source for the policy-change vectors.
@aeoess— if APS has a policy-rotation vector, a joint cross-ref in the gist would close the table.aeoess commentedon Jun 19, 2026
Your policy-change-v1 set (pc-001 through pc-004 at 0ee72ce) looks solid.
To be precise on the APS side: our coverage here is the policyDigest in the signed DecisionReceipt that I described above, a snapshot binding that ties each decision to the policy in force when it was made. That is partial coverage of rotation, not a standalone policy-rotation fixture, and I would rather state that plainly than imply a vector we have not published.
For the cross-reference, I would keep it in draft-giskard-aeoess-action-ref and our respective conformance suites rather than a separate gist, so the provenance of each vector stays clean and independently verifiable. Glad to wire an action_ref cross-ref there now and treat policy-rotation as its own track.
giskard09 commentedon Jun 19, 2026
Agreed — policyDigest as snapshot binding is accurate coverage for what you have, and stating it plainly is the right call. The cross-ref in the joint I-D makes sense as the canonical anchor; policy-rotation as its own track keeps the fixture contract clean on each side.
Happy to wire the action_ref cross-ref now if you want to open the PR.
Babar-maker76 commentedon Jul 2, 2026
The audit trail gap is the most operationally painful of the three - policy drift and unauthorized tool use are detectable at runtime, but "we ran this agent, here's the proof" requires capturing execution state at the infrastructure layer before any application-level compliance logic runs.
One failure mode we've seen repeatedly: agent returns HTTP 200, the orchestration layer marks the call "success," and the audit record is empty because output_tokens were 0. The agent ran, cost money, produced nothing, and left no trace of what it actually attempted. Silent compliance violation - invisible until audit time.
The ComplianceMiddleware pattern with cryptographic receipts is the right long-term architecture. One practical intermediate layer worth considering: per-execution telemetry (status, duration_ms, token usage, output_summary) gives you the "what actually happened" record before you have signing infrastructure in place. It's the evidence layer underneath whatever governance policy you build on top - catches the policy drift case longitudinally because you have a baseline to compare against.
The 25% stat tracks with what we see too. Most teams discover the audit trail gap at audit time, not execution time, precisely because nothing errors - it just runs and produces nothing.
We built this into agents.opsveritas.com as the execution audit layer specifically for teams in this gap: not ready for full cryptographic receipts, but needing something more than "HTTP 200 = success" as their compliance evidence.
hegu-1 commentedon Jul 13, 2026
Compliance-as-code gets much more useful if it is tied to actual agent action receipts, not just static policy declarations.
For SK agents I would want the compliance plugin to answer questions like:
That turns compliance from a spreadsheet after the fact into a runtime evidence layer. The harder part is probably standardizing the evidence schema so it survives across Semantic Kernel, AutoGen, MCP tools, and custom enterprise workflows.
I am sketching a related enterprise AI OS architecture here, with governance/evidence as a separate plane around agent execution: https://github.com/hegu-1/enterprise-ai-os-architecture
github-actions commentedon Oct 28, 2026
This issue is stale because it has been open for 90 days with no activity.