Skip to content

feat: cross-merchant budget enforcement sample#252

Open
Ectsang wants to merge 6 commits into
google-agentic-commerce:mainfrom
Ectsang:samples/cross-merchant-budget
Open

feat: cross-merchant budget enforcement sample#252
Ectsang wants to merge 6 commits into
google-agentic-commerce:mainfrom
Ectsang:samples/cross-merchant-budget

Conversation

@Ectsang
Copy link
Copy Markdown

@Ectsang Ectsang commented May 1, 2026

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 BudgetEvaluator independently, each with its own MandateContext. 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.

@Ectsang Ectsang requested a review from a team as a code owner May 1, 2026 04:51
@Ectsang Ectsang changed the title samples: cross-merchant budget enforcement scenario feat: cross-merchant budget enforcement scenario May 1, 2026
@Ectsang Ectsang changed the title feat: cross-merchant budget enforcement scenario feat: cross-merchant budget enforcement sample May 1, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread code/samples/python/scenarios/cross-merchant-budget/cross_merchant_budget.py Outdated
Comment thread code/samples/python/scenarios/cross-merchant-budget/cross_merchant_budget.py Outdated
Comment thread code/samples/python/scenarios/cross-merchant-budget/cross_merchant_budget.py Outdated
Comment thread code/samples/python/scenarios/cross-merchant-budget/cross_merchant_budget.py Outdated
Comment thread code/samples/python/scenarios/cross-merchant-budget/cross_merchant_budget.py Outdated
Copy link
Copy Markdown

@gazaliyalade-hue gazaliyalade-hue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ectsang
Copy link
Copy Markdown
Author

Ectsang commented May 11, 2026

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?

Ectsang added 2 commits May 12, 2026 07:12
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants