Skip to content

SDK vs spec: agent_recurrence.frequency is not evaluated; immediate execution skips the execution_date window #376

Open

Description

@baaakgun4543

What happened?

Two places where docs/ap2/payment_mandate.md and the SDK evaluator/tests seem to disagree. Before sending a patch, I'd like to confirm which side is intended.

1. payment.agent_recurrence.frequency is not evaluated

Spec (Agent Recurrence → Evaluation): the constraint "evaluates as true if the current Payment Mandate is sufficiently separated in time from the previous presentation to meet the frequency definition, and the max_occurrences limit is greater than or equal to the current occurrences."

SDK (ap2/sdk/constraints.py):

  • AgentRecurrenceEvaluator.evaluate checks only max_occurrences against MandateContext.total_uses.
  • frequency is never read.
  • calculate_period_start() and MandateContext.last_used_date exist but are unused.
  • calculate_period_start has no branch for BIWEEKLY or QUARTERLY. Both fall back to 0.0. It also uses local time (datetime.fromtimestamp), so period boundaries depend on the server's time zone.

Tests: agent_recurrence_tests.py::test_payment_agent_recurrence_under_limit expects a DAILY mandate used once a moment ago (last_used_date=time.time()) to pass a second use. Under the spec sentence above, that second use would fail.

Questions:

  1. Is frequency a minimum spacing between uses, as the spec says? Or is it only descriptive, with max_occurrences as the sole limit, as the tests say?
  2. If spacing is intended, should it be calendar periods (the calculate_period_start approach) or rolling intervals (e.g. ≥ 24h for DAILY)? And should boundaries be computed in UTC?

If spacing is intended, I can send a PR that:

  • enforces it using last_used_date;
  • adds BIWEEKLY and QUARTERLY;
  • uses UTC;
  • updates under_limit to reflect the spec.

2. Immediate execution and payment.execution_date

Schema: payment_mandate.execution_date: "When absent indicates immediate execution."

Spec (Execution Date → Evaluation): "The execution_date of the Payment Mandate MUST be later than or equal to not_before (if present) and earlier than or equal to not_after (if present)."

SDK: when execution_date is absent, the evaluator returns no violations. constraints_tests.py::test_payment_execution_date_missing_passes pins this, even for a window of 2025-01-01..2025-12-31 evaluated in 2026.

Question: should an immediate payment be checked against the window, using the current time? Or does the execution_date constraint deliberately apply only to scheduled payments, with immediate payments governed only by the mandate's exp?

  • If the latter, a sentence in the spec would prevent integrators from relying on the window to stop late immediate payments.
  • If the former, I can send a small PR that injects a clock into ExecutionDateEvaluator for testability.

Related

A separate PR fixes the string comparison of ISO 8601 bounds, and another fixes payment.budget minor-unit conversion. Neither changes the behaviour discussed here.

Code of Conduct

  • I agree to follow this project's Code of Conduct

Activity

  1. baaakgun4543 commented on Oct 14, 2026

    @baaakgun4543
    Author

    Update on question 2 (immediate execution vs. the execution_date window): #318 already proposes enforcing the window for immediate payments using the current time. That seems to answer it, pending a maintainer decision on that PR.

    Question 1 (agent_recurrence.frequency is never evaluated, while test_payment_agent_recurrence_under_limit pins the opposite of the spec sentence) is still open. I couldn't find an existing issue or PR for it.

    Separately, #378 fixes the string comparison of the execution-date bounds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions