feat: cross-merchant budget enforcement sample#252
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a sample implementation demonstrating the budget enforcement gap in cross-merchant scenarios and provides a solution via an external budget authority. Feedback focuses on improving numerical precision by using round() for currency conversions, optimizing the performance of hold lookups to avoid O(N) complexity, ensuring unique identifiers by using full UUIDs, and enhancing type safety by replacing mixed-type dictionaries with dataclasses.
|
All gemini-code-assist feedback addressed in b547f68 (currency rounding, O(1) hold lookups, full UUIDs, dataclasses). Lint failure is pre-existing Biome, unrelated to this PR — other 3 checks green. Per CONTRIBUTING.md, "contributions going forward are to the samples and sdk only" — this is a sample. @holtskinner anything blocking review from the team side? |
…decision Aligns the cross-merchant budget enforcement sample with the canonical budget_authority verb set being crosswalked across AP2, Cycles, and APS in aeoess/agent-governance-vocabulary. Verbs: - authorize() -> reserve() - refund() -> release() (pre-commit return of unspent reservation) - query() -> query_budget() (budget snapshot) Decision shape: - approved: bool -> decision: Decision (ALLOW / ALLOW_WITH_CAPS / DENY) - This retail sample emits ALLOW or DENY only. ALLOW_WITH_CAPS is canonical for divisible / metered budgets (Cycles, runcycles.io). Callers that cannot accept partial fulfillment MUST treat ALLOW_WITH_CAPS as DENY (safe default). Types renamed for consistency: Hold -> Reservation, AuthorizeResult -> ReserveResult, HoldStatus -> ReservationStatus (REFUNDED -> RELEASED). Demo behavior preserved: Merchant A reserves \$60 (ALLOW), Merchant B denied at \$60 (budget exceeded), Merchant B retries at \$35 (ALLOW). Final state: \$95 spent of \$100 budget. References: - ACP google-agentic-commerce#231 three-layer model (passport / budget authority / rail) - Cycles (runcycles.io) - independent reserve/commit/release impl - aeoess/agent-governance-vocabulary - crosswalk in progress (AAIF donation trajectory documented)
Adds aeoess, crosswalked, goodmeta, runcycles to custom-words for cspell to accept the rename PR's references to upstream verb-set crosswalk and reference implementations.
|
@Ectsang quick heads up: before merging Reason: avoiding overlap with APS's delegation-authority layer. The verb set is about spend control and reservations, not general agent authority. The six verbs and decision shape are unchanged. The No deadline. Just wanted to keep the terminology change visible here. |
…dget reservation Adds a colocated specification document defining the protocol pattern that cross_merchant_budget.py implements: - 9 sections covering scope, definitions, MUST/SHOULD requirements for Budget Authority, Verifying Parties, and Shopping Agents - Six canonical verbs (reserve/commit/release/refund/query_budget/ query_reservation) with the four-verb subset implemented here - Three-value Decision shape (ALLOW/ALLOW_WITH_CAPS/DENY) with safe default rule (treat ALLOW_WITH_CAPS as DENY unless partial- fulfillment-capable) - Registration as Mandate Constraint type "budget_reservation_v1" via AP2 specification.md §371 extension point - Six open questions listed honestly (discovery/trust, dispute integration, cross-rail composition, multi-asset budgets, reservation expiry, signed reservation attestations) Sits alongside the Python sample. Does not modify AP2 wire format, JWT claims, or Mandate signature scheme. MUSTs apply to deployments that opt into the budget_reservation_v1 Constraint type. Vocabulary aligns with crosswalk/budget_reservation.yaml in aeoess/agent-governance-vocabulary. Cycles cited as independent production implementation with ALLOW_WITH_CAPS exercised. Refs google-agentic-commerce#207, google-agentic-commerce#252, ACP google-agentic-commerce#231.
Adds a sample demonstrating the cross-merchant budget enforcement gap from #207 and a solution using an external budget authority.
Part 1 shows the problem: two merchants evaluate
BudgetEvaluatorindependently, each with its ownMandateContext. The agent overspends ($120 on a $100 budget).Part 2 shows the fix: an external authority with four verbs (authorize, commit, refund, query) based on the discussion in #207. The authorize call atomically checks and holds budget, preventing race conditions.
No external dependencies. Runs with
python cross_merchant_budget.py.