Repository navigation
RFC: Audit receipts for ADK agent tool execution #5164
Description
Activity
- addedtools[Component] This issue is related to tools[Component] This issue is related to toolsmcp[Component] This issues is related to MCP support[Component] This issues is related to MCP support
on Apr 5, 2026 We built something similar for the Python side. The core idea is the same - Ed25519 signed receipts per tool call - but we also chain them (each receipt includes the hash of the previous one) so you get tamper-evidence across the full session, not just per-call integrity.
The tricky part is deciding what goes into the canonical form before signing. We settled on: tool name, input/output content hashes, policy ID, timestamp, and the previous receipt hash. Keeping raw I/O out of the signed blob avoids accidentally signing PII into an immutable record.
Already works as ADK middleware via
pip install asqav. The receipt chain is exportable as JSONL for offline verification.@jagmarques interesting that you arrived at the same pattern independently. Chaining via previous receipt hash is exactly what the IETF draft specifies, and keeping raw I/O out of the signed blob is the right privacy call (we use tool_input_hash for the same reason, SHA-256 of the raw input bytes).
Good point on Ed25519 and NIST deprecation. The IETF draft's signature envelope uses a signature.alg field specifically to support algorithm negotiation. Today it is "EdDSA" (Ed25519), but the same envelope works with ML-DSA-65 or any other algorithm. The verifier already dispatches on that field. Supporting both with negotiation (as you did in asqav) is the right approach for enterprise customers with post-quantum requirements.
Would be worth comparing the canonical form choices. We use JCS (RFC 8785) for deterministic serialization before signing. If asqav uses the same canonicalization, the two systems produce interoperable receipts. We just verified this with another implementation (Agent Passport System) - three independent receipts all verified against the same IETF draft verifier at exit code 0.
What does the asqav middleware hook look like for ADK? If it follows the same pattern as protect-mcp (PreToolUse/PostToolUse hooks), there might be a common middleware interface worth proposing to the ADK team.
Built it. protect-mcp-adk is a working ADK plugin for Ed25519 receipt signing.
Install
```bash
pip install protect-mcp-adk
```Usage
```python
from google.adk import Agent
from google.adk.tools import FunctionTool
from protect_mcp_adk import ReceiptPlugin, ReceiptSignersigner = ReceiptSigner.generate()
agent = Agent(
model="gemini-2.0-flash",
tools=[FunctionTool(my_tool)],
plugins=[ReceiptPlugin(signer, auto_export_path="receipts.jsonl")],
)
```Every tool call produces a signed receipt in the IETF draft envelope format:
```json
{
"payload": {
"type": "protectmcp:decision",
"spec": "draft-farley-acta-signed-receipts-01",
"tool_name": "search",
"tool_input_hash": "sha256:ff7e27...",
"decision": "allow",
"output_hash": "sha256:a3f8c9...",
"session_id": "sess_a1b2c3d4e5f6",
"sequence": 1,
"previousReceiptHash": null,
"agent_name": "research_agent"
},
"signature": { "alg": "EdDSA", "kid": "sb:adk:320d7372f83c", "sig": "f4bf13..." }
}
```How it works
- Hooks into ADK's `after_tool_callback` via the BasePlugin interface
- Signs `JCS(payload)` with Ed25519 (RFC 8032 + RFC 8785)
- Chain-links receipts via `previousReceiptHash` (tamper-evident ordering)
- Privacy-preserving: tool inputs/outputs are SHA-256 hashed, not stored raw
- Errors signed via `on_tool_error_callback`
- Auto-exports to JSONL as receipts are produced
Cross-verified
Python-signed receipts verify with the same Node.js verifier used by three other independent implementations (protect-mcp TypeScript, Agent Passport System, asqav):
```bash
npx @veritasacta/verify@0.2.5 receipts.jsonl --keyExit 0 = valid, 1 = invalid (tampered), 2 = error (malformed)
```
On post-quantum (@jagmarques)
The receipt envelope's `signature.alg` field supports algorithm negotiation. Today it is `"EdDSA"` (Ed25519). The same envelope works with ML-DSA-65 by changing the alg field. The plugin accepts a signer interface, so swapping the crypto backend is a configuration change, not a rewrite. Planning ML-DSA-65 as an opt-in option once `@noble/post-quantum` or the Python equivalent is audited.
Source: packages/protect-mcp-adk
@tomjwxf @jagmarques — the three-implementation convergence on Ed25519 + JCS + hash-linked chains is now a pattern, not a coincidence. APS, protect-mcp, and asqav arrived at the same canonical form independently. That's the strongest validation a receipt format can get.
APS has an ADK governance hook that adds the layer above tool-level receipts: the delegation chain that proves authorization, not just execution.
# pip install agent-passport-system from agent_passport_system import ( generate_key_pair, create_passport, create_delegation, sign_action_receipt ) # The receipt proves the tool was called. # The delegation proves the agent was authorized to call it. # The passport traces authority to a human principal. receipt = sign_action_receipt( agent_id=agent.passport.agent_id, delegation_id=delegation.delegation_id, private_key=keys.private_key, action_type="search", scope="tools:search", status="success", summary="Tool executed successfully" ) # receipt.signature: Ed25519 over JCS-canonicalized payload # receipt.previousReceiptHash: chain-linked # receipt.delegationId: traces to delegation -> passport -> principal
The composition with protect-mcp-adk:
Layer What it proves Who signs protect-mcp-adk Tool C was called with input hash X, output hash Y Agent's Ed25519 key APS delegation Agent B was authorized scope tools:searchwith $500 spend limitPrincipal's Ed25519 key APS gateway The evaluation was permit/deny at timestamp T with policy hash P Gateway's Ed25519 key Three signatures, three parties, one audit trail. A verifier consuming ADK execution logs gets: tool-level proof (protect-mcp), authorization proof (APS delegation), and enforcement proof (APS gateway). Each independently verifiable.
On the gateway-reporter pipeline we just shipped: every adapter (including ADK) can optionally send receipts to the hosted gateway for dashboards and audit trails. Fire-and-forget, never blocks on gateway failure:
from agent_passport_system import GatewayReporterConfig config = GatewayReporterConfig( gateway_url="https://gateway.aeoess.com", api_key="aps_live_..." ) # Receipts flow to gateway for real-time dashboards, audit trail, session persistence
The canonical form alignment means a unified verifier can validate receipts from all three systems without switching parsers. If someone builds a
verify-receiptCLI that accepts any Ed25519+JCS+chain-linked receipt, all three implementations should pass at exit code 0.SDK:
pip install agent-passport-system(v0.9.0, Python) ornpm install agent-passport-system(v1.36.2, TypeScript, 2,497 tests). ADK governance hook atsrc/adapters/governance-hook.ts.@aeoess the three-layer composition is clean: protect-mcp-adk (tool execution proof), APS delegation (authorization proof), APS gateway (enforcement proof). Three signatures, three parties, one envelope format.
The key property: each layer is independently verifiable. An auditor consuming ADK execution logs can verify just the tool receipt (protect-mcp), or the full chain (tool + delegation + gateway). The envelope is the same either way. The extensions block handles the layer-specific semantics without breaking the common verifier.
Cross-system verification is now confirmed with 4 independent implementations across Python and TypeScript, all verified at exit 0 by the same tool. That is the interop proof the IETF draft needed.
For ADK specifically: protect-mcp-adk handles the tool boundary. APS handles the authorization boundary. Both are pip-installable, both are ADK BasePlugin compatible. A user who needs both layers installs both packages and registers both plugins. No coordination required between them at runtime - the receipts compose at verification time.
@tomjwxf Thanks for the update. The request is currently being reviewed by our team, and I will let you know if anything further is needed. Thank you for understanding.
Reacted by TJF- addedneeds review[Status] The PR/issue is awaiting review from the maintainer[Status] The PR/issue is awaiting review from the maintainer
on Apr 7, 2026 Quick update: the source repository for
protect-mcp-adkis now public:Source: github.com/ScopeBlind/protect-mcp-adk
PyPI: pypi.org/project/protect-mcp-adk/
Discussion: #5180 (Show-and-Tell)Addresses the feedback from the docs PR about having a public source repository. Happy to support the review in any way that's helpful.
@tomjwxf — good to see protect-mcp-adk public and on PyPI. The ADK integration path from our side is the GovernanceHook adapter that wraps ADK tool calls with delegation-scoped authorization.
The composition is clean: APS governance hook provides pre-execution authorization (delegation scope check, spend limit, derivation rights) → protect-mcp provides the receipt signing layer (Cedar policy evaluation + Ed25519 receipt) → ADK executes the tool call. Three open-source components, each handling a single concern, composable without coupling.
The 3/3 cross-verification from crewAI#5283 (APS composition receipts through protect-mcp + Cedar) applies here too — same receipt format, same canonicalization (JCS), same signature scheme (Ed25519). ADK tool calls going through the same pipeline produce equivalent receipts.
If the docs PR or Show-and-Tell discussion wants a worked example of APS + protect-mcp-adk together, happy to contribute one. The governance_attestation envelope as the authorization input and the protect-mcp receipt as the execution evidence closes the full loop from delegation to audit trail.
@aeoess thanks, a joint worked example would be concretely useful. The composition you describe is exactly right: APS governance hook for pre-execution authorization, protect-mcp-adk for the Ed25519 receipt of the decision, ADK executes. Three concerns, three components, cleanly composed.
One thing worth capturing in the example: the cross-verification. There are now several independent implementations of the receipt pipeline (APS, protect-mcp, sb-runtime, protect-mcp-adk) from independent teams, and a receipt emitted by any of them verifies against any of the others. That interop is what makes the IETF draft credible as a shared standard rather than a single-vendor format.
Proposal: a shared
agent-governance-testvectors/repo with canonical input/output fixtures that any conformant implementation can run against. If that sounds useful I can stand up the skeleton this week and you can drop APS fixtures into it.@klateefa any update on the review? Happy to answer questions if anything in the related docs PR (#1565) or the samples PR (adk-samples#1437) needs clarification. The public source is at github.com/ScopeBlind/protect-mcp-adk if that helps reviewer context.
- added a commit that references this issue
on Apr 17, 2026 @aeoess circling back on the shared test-vectors idea with a concrete artifact:
Repo: github.com/ScopeBlind/agent-governance-testvectors
What is in the v0.1 release:
- Fixtures: 4 tool-call inputs (allow Read, allow Bash git, deny Bash destructive, allow Write), a shared Cedar policy (
autoresearch-safe.cedar), and a deterministic Ed25519 seed so every implementation uses the same keypair and produces comparable signatures - Expected output:
receipt-schema.json(JSON Schema draft-07 for the receipt shape) andchain.jsonl(the canonical expected sequence). Schema check, signature verification, and chain-linkage check together form the three-part conformance test - Reference driver:
implementations/protect-mcp/run.shexercises the TypeScript runtime against the fixtures - Placeholder drivers:
implementations/protect-mcp-adk/,implementations/sb-runtime/,implementations/aps-governance-hook/ready for their authors to drop in run.sh - Verifier:
conformance/verify.shruns the three checks against any implementation's output - CI:
.github/workflows/conformance.ymlruns every implementation on every PR and uploads the receipts as an artifact - Spec:
spec.mddocuments exactly what conformance means and what it does not (byte-identical JSON at the file level is NOT required; byte-identical JCS canonical form IS)
Apache-2.0, intentionally in ScopeBlind org for v0.1 but happy to migrate to a neutral org (e.g., an in-toto or Sigstore sibling) once there is multi-org engagement. License stays Apache-2.0 either way.
Immediate ask for you: if APS is interested in dropping a driver into
implementations/aps-governance-hook/run.sh, that lets us verify APS ->@veritasacta/verifyinterop with a single green CI check. I can review the PR and help debug any canonicalization or signature-encoding differences that show up.Also for @klateefa: this is the natural home for the ADK-side test I offered on adk-python#5180. A
protect-mcp-adkdriver there would exercise the Python codepath against the same fixtures the TypeScript reference exercises, closing the interop loop for the Google ADK side.The four-implementation convergence now has a shared conformance surface. Any future fifth, sixth, seventh implementation proves interop by opening a PR against this repo. Receipt format -> wire format -> open test vectors: same model that worked for TLS and JOSE.
Thanks for the original offer; this is the shape I owed you.
- Fixtures: 4 tool-call inputs (allow Read, allow Bash git, deny Bash destructive, allow Write), a shared Cedar policy (
@tomjwxf — circling back. APS governance hook driver landed in ScopeBlind/agent-governance-testvectors#1 and passes all 6 conformance checks against the shared fixture set (4 tool-call inputs, shared Cedar policy, deterministic Ed25519 seed). Cross-verification works: APS-produced envelopes validate under
npx @veritasacta/verify, protect-mcp/sb-runtime/protect-mcp-adk envelopes all land at the sameexit 0.That closes the cross-verification loop you proposed — four independent implementations producing the same receipt shape from the same test fixtures. The ADK side is the remaining integration to wire up as a worked example.
Proposal for the worked example in this issue's context:
from google.adk import Agent from protect_mcp_adk import ReceiptMiddleware # your repo, at PyPI from agent_passport_system import GovernanceHook # ours, at npm + Python SDK agent = Agent( model="gemini-2.0-flash", tools=[search_tool, database_tool], middleware=[ GovernanceHook( # pre-execution: authorization delegation_key="./keys/agent-delegation.json", policy_source="./policies/deployed.cedar", ), ReceiptMiddleware( # post-decision: receipt signing key_path="./keys/receipt-signer.json", verifier_compat=["@veritasacta/verify"], ), ], )
Three clean concerns, three components, one ADK tool-call pipeline:
- GovernanceHook checks delegation scope BEFORE tool executes (deny = execution blocked, no receipt needed)
- ReceiptMiddleware signs the decision AFTER gate evaluates (the proof artifact)
- ADK executes the tool call if permitted
Can ship this as a joint example in either repo — ADK's cookbook, protect-mcp-adk's examples/, or a neutral third repo. Our vote: neutral third repo (small, focused, title something like
agent-governance-stack-example) so neither project "owns" the canonical integration pattern and both can cite it.Will draft the runnable example over the next few days and post back with a repo link for your review. The fixture set from ScopeBlind/agent-governance-testvectors gives us the deterministic inputs; the worked example just shows the three-component composition doing the right thing on those inputs.
@aeoess accepting the proposal in full. The three-component composition (APS
GovernanceHook→ protect-mcp-adkReceiptMiddleware→ ADK executes) is the right shape, and the neutral-third-repo call is the right governance move. Neither ScopeBlind nor APS owning the canonical integration pattern keeps the ecosystem credibility intact.On the repo.
agent-governance-stack-exampleis a good name. Proposing we co-author under a neutral GitHub org or, if that is slower to set up, under your personal namespace with me as a maintainer (or vice versa) — the owning org can migrate later. I can stand up the skeleton today (README, Apache-2.0 LICENSE,.github/workflows/verify.ymlrunning the full pipeline on every push) and hand off the draft branch so you can fill in the APS side and the worked example proper. Or if you prefer to build the example first and add me as a reviewer, that also works.Proposed shape for the example that matches your
middleware=[...]pattern:agent-governance-stack-example/ ├── README.md # motivation + runnable instructions ├── LICENSE # Apache-2.0 ├── example.py # the 20-line ADK agent you pasted above, runnable ├── policies/ │ └── autoresearch-safe.cedar # shared policy (matches testvectors fixture) ├── keys/ │ └── README.md # how to generate the two key files (delegation, receipt-signer) ├── receipts/ # gitignored; produced at runtime ├── verify.sh # runs npx @veritasacta/verify + APS verifier against receipts/ └── .github/workflows/verify.yml # CI: run example.py on every push, verify outputThe deterministic ED25519 seed from agent-governance-testvectors feeds the
keys/setup so example receipts are reproducible byte-for-byte. CI exits 0 only when both APS governance attestations and protect-mcp receipts verify against their respective verifiers.What the README should say up top (since reviewers will land on this from @klateefa's team or similar):
- ADK is the host. Nothing here is ADK-specific beyond the middleware registration.
- The three-component composition is not coupled: users can install APS only, protect-mcp-adk only, or both, and the example shows the full stack.
- Each layer's receipt is independently verifiable. A reviewer who cares only about "did the tool call happen" verifies the protect-mcp receipt; a reviewer who cares about "was the agent authorized to make this call" verifies the APS governance attestation.
- No federation, no coordination at runtime. Composition happens at verification time.
Tagging @klateefa — this is the worked example your team asked for. Once it lands, the ADK-side integration review has a concrete artifact to evaluate: a 20-line
example.py, two pip installs, runnable in under a minute, verifying at CI exit 0 across two independent cryptographic paths. Happy to answer any specific questions from the review once the example is ready.On the ADK RFC #5164 itself. Between protect-mcp-adk landing on PyPI, the testvectors repo proving 4/4 implementations interop, and this joint example in the works, I think the RFC has moved from "proposal" to "shipped pattern in three ecosystems, request to document in ADK". If the review wants to land the docs PR at adk-docs#1565 with a pointer to this joint example, that is the cleanest close-out shape.
Standby on the example repo; you pick the mechanics (you draft / I draft the skeleton / we pair on a shared branch) and I will match whichever works best on your end.
@tomjwxf, accepting the co-authoring arrangement. Neutral third repo is the right call.
On the org question. Happy to stand up
agent-governance-stack-exampleunder an aeoess-hosted repo initially with you as co-maintainer. Migration to a neutral org later (if one materializes) is a push-to-new-remote operation, not a rewrite, so the cost of starting now and moving later is near zero. If you'd prefer to own the skeleton end today under your namespace with me as co-maintainer, that also works. Pick whichever gets the skeleton up fastest.On the proposed shape. Layout matches what the example needs. Three additions to consider:
aps_delegation.pyas a separate module fromexample.py, so the APS delegation setup (generating the parent token, scoping to the autoresearch policy) is isolated and readers can see it independently of the ADK glue.verify.shshould have an explicit exit-code convention: exit 0 = all receipts verify + chain is intact; exit 1 = any receipt fails; exit 2 = chain has gaps. Gives CI something deterministic to gate on..github/workflows/verify.ymlshould run againstagent-passport-system@nexton one matrix row and@lateston another, so both v1 and v2 SDK versions are continuously proven compatible. The delegation primitives are byte-identical, so this should stay green on both.
Once your skeleton branch lands, I'll fill in the APS side (delegation setup, governance_attestation receipts, chain root hash attestation) and cut a PR for review.
Side note: SDK v2.0.0-beta.0 is on npm
@nextas of an hour ago (release notes agent-passport-system/agent-passport-system#16). No action needed from protect-mcp-adk, the GovernanceHook contract it reads against is unchanged.@aeoess accepting all three additions.
1.
aps_delegation.pyas a separate module. Yes — readers should be able to see the delegation setup independently of the ADK glue. Proposing the same split on the protect-mcp side:receipt_signing.pyisolated fromexample.pyso each layer is readable as a standalone primitive. That keeps the "three clean concerns" property visible in the source layout, not just the middleware list.2.
verify.shexit code convention. Adopted verbatim:0= all receipts verify + chain intact;1= any receipt fails signature;2= chain has gaps. I will match the@veritasacta/verifyCLI's existing convention (exit2is already "undecidable/malformed" there) so CI failure modes read the same whether you gate on our verifier or the APS one.3. CI matrix against
@nextand@latest. Yes. Adding a third matrix row foragent-passport-system==2.0.0b0on PyPI so both language SDK tracks are continuously proven compatible. Also adding@veritasacta/verify@0.3.0vs@lateston my side in case we ship a breaking change and I don't notice.Mechanics. Your offer to host the skeleton under an aeoess-namespaced repo with me as co-maintainer works. I'll prep the README + LICENSE + .github/workflows shape (matching the agent-governance-testvectors layout so a reader moving between the two repos doesn't context-switch) and hand you a branch to fork from. Alternately if you want to own the first commit end-to-end under your namespace and add me as maintainer on day one, also fine.
One structural addition worth considering: both names on the LICENSE copyright line (Apache-2.0 allows multi-copyright-holder, and it reflects the actual authorship). Same on the README author list. Keeps the neutrality visible even if the repo physically sits under one org's namespace for bootstrap convenience. Either namespace is a push-to-new-remote away from a neutral org later.
On the SDK v2.0.0-beta.0 shipping: noted, will pull it into the testvectors driver's matrix alongside v1.46.0 so the 6/6 conformance is continuously validated on both SDK majors. Independent of this issue; I'll update on agent-passport-system/agent-passport-system#16 if anything surfaces.
@klateefa the concrete artifact coming out of this will be:
- A neutral third repo (name:
agent-governance-stack-example) with a runnable ~20-line ADK agent - CI that exits 0 when both APS governance attestations and protect-mcp receipts verify against their respective verifiers
- Two
pip installs, onepython example.py, one./verify.sh - Shared Cedar policy and deterministic seed so receipts are byte-reproducible
If the ADK review team wants to gate #5164 close-out on seeing that repo green, understood — I'd rather you close this with a concrete artifact link than with a bare "documented." Will post the repo URL here the moment skeleton + aeoess's APS contribution are both in.
Standing by on aeoess picking the exact repo creation mechanics; either hosting arrangement works on my end.
- A neutral third repo (name:
Accepting the skeleton co-ownership structure. For the namespace: start under aeoess, both names on LICENSE copyright + README authors, maintainer access to tomjwxf from day one. Rationale:
- Neutral-org migration is a
git remote add+git pushaway; no path dependency. - aeoess has active CI infrastructure (GitHub Pages, auto-deploy from main, release automation) that saves ~a day of setup at 0.1.0.
- The audience for this repo in the short term is ADK integrators; they're going to find it from the adk-python#5164 link regardless of namespace.
- Multi-copyright-holder on LICENSE and co-authors on README keeps the neutrality visible and defensible. If ever asked "why is this under aeoess?", the answer is "because we started there; authorship is equal."
I'll prep:
aeoess/adk-aps-integrationwithaps_delegation.py+receipt_signing.pysplit per your earlier point- MIT-compatible Apache-2.0 LICENSE with copyright line:
Copyright 2026 Tymofii Pidlisnyi, Matthew Karsten(let me know the exact name shape you want) - README with both authors in the header
- CI matrix:
agent-passport-system@latest+agent-passport-system@next+agent-passport-system==2.0.0b0PyPI +@veritasacta/verify@latest+@veritasacta/verify@0.3.0 - .github/workflows/ matching the agent-governance-testvectors shape so readers moving between repos don't context-switch
- Branch
mainempty initial commit, thenintegration-skeletonbranch for you to PR into
Will ping you when the repo is live with write access and a branch to fork from. Expected same-day turnaround once I get your LICENSE-copyright-line name preference.
- Neutral-org migration is a
Skeleton is up: aeoess/adk-aps-integration.
Shipped per our earlier agreement. Both names on LICENSE + README, maintainer invite sent to @tomjwxf, three primitives as the source layout, CI matrix covering the versions we said we'd gate on.
What's live on
integration-skeleton:aps_delegation.pysets up an APS delegation chain, one per agentreceipt_signing.pywraps aToolContextevent into a signed audit receipt, per-callverify.shis a standalone CI gate (exit 0 pass, 1 fail)examples/basic-tool-call/is end-to-end runnable with a test principal passport fixture- CI: Python 3.10/3.11/3.12 ×
agent-passport-system@latest(0.15.0) +agent-passport-system==2.0.0b0, 6/6 jobs green against@veritasacta/verify@0.3.0. Run: https://github.com/aeoess/adk-aps-integration/actions/runs/24617048934
One pivot worth naming. Receipts in the skeleton use
@veritasacta/verify's audit-bundle shape (one bundle per example, validated with a singleverifycall) rather than per-file APS receipts. The verifier already understands the bundle, and the bundle carries the signing JWK in its verification block, so there's no key plumbing between signer and verifier. Ifprotect-mcp-adk's receipt-signing layer wants to emit either shape, both will verify. Bundle just keeps CI simpler for the first cut.Handoff. The
integration-skeletonbranch is your fork target. Write access is waiting for you to accept the invite. Fill in theprotect-mcp-adkside against theToolContextshape inrun.pyand open a PR whenever ready, I'll review.Neutral-org migration later stays a
git remote add+git pushwhen we want it.@aeoess — maintainer invite accepted. The aeoess/adk-aps-integration skeleton looks right: aps_delegation.py + receipt_signing.py split, CI green at 6/6 across Python 3.10/3.11/3.12 on agent-passport-system@latest (0.15.0) + @2.0.0b0 matrix.
Closing my side of the loop: ScopeBlind/hermes-decision-receipts is now live at v0.1.0-alpha.1 — same receipt format, same JCS canonicalization, same Ed25519. Not ADK-specific but shares the receipt primitive with protect-mcp-adk, so the worked example in adk-aps-integration can cite either as the "decision receipt" side without forking the format.
Will open the protect-mcp-adk integration PR against the
integration-skeletonbranch this week with:receipt_signing.pyproducing@veritasacta/verifybundle-format output (matching your audit-bundle shape soverify.shstays single-call).- Example ADK agent wiring both middleware layers (APS GovernanceHook pre-execution + protect-mcp ReceiptMiddleware post-decision) against a shared Cedar policy and deterministic seed.
- CI extension ensuring both APS governance attestations and protect-mcp receipts verify at exit 0 on every push.
One small agreement to confirm on the bundle-vs-per-file question you flagged: bundle shape makes CI simpler for the first cut, I'll emit bundle by default with an
--emit-per-fileflag for the protect-mcp-adk signer if anyone needs standalone receipts. That keeps both shapes valid (audit-bundle + per-file) without forking the format.@klateefa — the concrete artifact shape committed to a month ago (20-line example.py, two pip installs, CI exit 0 across two cryptographic paths) is now on the critical path to close-out. Happy to answer any questions in the review thread in the meantime.
@klateefa close-out artifact ready when you are, no rush.
Concrete shipped:
-
protect-mcp-adk on PyPI (0.1.0):
https://pypi.org/project/protect-mcp-adk/ -
cedar-agent-schemas, canonical community Cedar schema library for agent action verbs. Shipped across three language registries:
-
agent-governance-testvectors, shared fixtures with 4/4 implementations (APS, protect-mcp, sb-runtime, protect-mcp-adk) cross-verifying at
@veritasacta/verifyexit 0: https://github.com/ScopeBlind/agent-governance-testvectors -
adk-aps-integration, the joint worked example with @aeoess. Three-component composition (APS delegation + protect-mcp-adk receipts + ADK) runnable in a 20-line
example.py. CI green 12/12 across Python 3.10 / 3.11 / 3.12 × agent-passport-system@latest + 2.0.0b0. PR open: Add full-composition example: APS delegation + protect-mcp-adk receipts aeoess/adk-aps-integration#2
This pattern is shipped across three AI-agent ecosystems: 7 merged PRs in Microsoft AGT, 2 merged PRs in AWS cedar-for-agents, and ADK via protect-mcp-adk on PyPI. Verified by four independent implementations cross-verifying against shared fixtures, and documented as a canonical community schema library. The adk-docs PR at adk-docs#1565 can land now with a pointer to aeoess/adk-aps-integration as the worked example rather than piling long code into the ADK cookbook.
Happy to answer/discuss any questions on review. Appreciate consideration or feedback otherwise!
@walkojas-boop . The receipt format is an IETF draft (draft-farley-acta-signed-receipts); four independent implementations (APS, protect-mcp, sb-runtime, protect-mcp-adk) currently cross-verify against shared fixtures at ScopeBlind/agent-governance-testvectors. A single-gateway approach (one component doing authorization, signing, and execution) is a different posture than what this thread converged on (three independent signers, three keys, independent verification paths per layer). protect-mcp also does the single-gateway pattern as an option for Cedar evaluation + Ed25519 signing in one MCP intercept layer; but this ADK thread is intentionally decomposed.
-
- addedspam[Status] Issues suspected of having comments which are spam[Status] Issues suspected of having comments which are spam
on Apr 22, 2026 🚨 Automated Spam Detection Alert 🚨
@maintainers, a suspected spam comment was detected in this thread.Reason:
@walkojas-boop promoted their 3rd-party product "Sift" and linked to their commercial website walkosystems.com/sift.
Problem
Google ADK agents execute tool calls in production environments, but there is no built-in mechanism to produce cryptographic evidence that a specific tool call occurred, what policy governed it, and that the audit record hasn't been tampered with. As ADK agents move into enterprise deployments, compliance and security teams need verifiable proof of agent behavior.
Proposal
Add an optional receipt-signing middleware to ADK's tool execution pipeline. When enabled, every tool call would emit an Ed25519-signed receipt:
Each receipt captures: tool name, decision (allow/deny), input/output digests, policy hash, timestamp, and an Ed25519 signature. Receipts can be verified offline without access to the agent runtime.
Reference
This pattern is standardized in an IETF Internet-Draft and implemented in protect-mcp (MIT, npm v0.5.3). Active integrations exist with Mission Control, Cedar for Agents, Microsoft AGT, and LlamaIndex.
Happy to discuss integration architecture and contribute.