# AI agent payment policy template
# Published by Flominzo (https://flominzo.com/resources/ai-agent-payment-policy-template)
#
# A vendor-neutral starting point for deciding what an AI agent may pay, to whom,
# up to what limits, and who approves. Every value below is an EXAMPLE: replace it
# with your own. This template is not legal or compliance advice; review it with
# your risk, finance and compliance owners before an agent is allowed to pay.
#
# Principle: the agent never holds spending authority in its prompt. The payment
# layer enforces this policy outside the model, and denies when in doubt.

policy:
  id: "pol-supplier-payments-001"          # example: a stable identifier for this policy
  version: 3                               # example: increase on every change; keep old versions
  status: "active"                         # draft | active | suspended | retired
  description: "Pay approved supplier invoices from the operating account"  # example
  owner: "head-of-finance@example.com"     # example: the person accountable for this policy
  approvers:                               # example: people who can approve payments above thresholds
    - "controller@example.com"
    - "cfo@example.com"

agent:
  id: "agent-ap-assistant"                 # example: the agent's own identity, never a shared user account
  operated_by: "finance-operations"        # example: the team responsible for the agent
  environment: "production"                # sandbox | production
  can_change_this_policy: false            # the agent must never edit its own limits

scope:
  purposes:                                # example: what the agent may pay for
    - "supplier_invoice"
  categories_blocked:                      # example: what it may never pay
    - "payroll"
    - "refund"
    - "crypto"
  rails_allowed:                           # example: payment rails the agent may use
    - "bank_transfer"
  currencies_allowed:                      # example
    - "GBP"
    - "EUR"
  source_accounts:                         # example: the accounts money may leave from
    - "operating-account-gbp"

counterparties:
  mode: "allow_list"                       # allow_list: pay only listed payees
  new_payee_cooling_period_hours: 48       # example: new or changed bank details wait before first payment
  allow_list:                              # example entries
    - name: "Example Textiles Ltd"
      account_reference: "GB00EXMP00000000000001"   # example only, not a real account
      max_per_payment: 5000
    - name: "Example Logistics GmbH"
      account_reference: "DE00EXMP0000000000000002" # example only, not a real account
      max_per_payment: 2500

limits:
  currency: "GBP"                          # example: currency the caps are expressed in
  per_payment_max: 5000                    # example
  daily_max: 20000                         # example: across all payments by this agent
  monthly_max: 150000                      # example
  max_payments_per_day: 25                 # example
  budget_reservation: "atomic"             # reserve budget before sending, so concurrent agents cannot overspend

approvals:
  by_amount:                               # example tiers: who must approve, by amount
    - up_to: 1000
      approval: "none"
    - up_to: 5000
      approval: "one_approver"
    - above: 5000
      approval: "denied"                   # above the per-payment cap, the agent cannot pay
  by_reversibility:
    irreversible_rails_require_approval: true   # instant or final payments need a person to approve
    new_payee_requires_approval: true
  approval_timeout_hours: 24               # example: an approval that doesn't arrive in time counts as a refusal

validity:
  valid_from: "2026-10-01T00:00:00Z"       # example
  expires_at: "2027-03-31T23:59:59Z"       # example: authority ends automatically
  allowed_hours_utc: "07:00-19:00"         # example: no agent payments outside these hours

revocation:
  who_can_revoke:                          # example
    - "head-of-finance@example.com"
    - "security-oncall@example.com"
  procedure: "Suspend the policy; pending intents are cancelled where the provider allows, and in-flight ones are tracked to a final outcome."
  target_time_minutes: 5                   # example: how fast revocation must take effect

failure_behaviour:
  on_check_error: "deny"                   # fail closed: if a limit, allow-list or approval check errors, do not pay
  on_check_timeout: "deny"
  on_policy_missing_or_expired: "deny"
  alert_to: "finance-ops-alerts@example.com"   # example

idempotency:
  one_key_per_intent: true                 # one idempotency key per agent step and payment
  retry_rule: "status_query_before_retry"  # after a timeout, ask the provider what happened; never resend blindly
  unknown_outcome: "investigate"           # an UNKNOWN result is resolved by lookup or evidence, not by paying again

audit:
  record_fields:                           # recorded for every decision, approved or denied
    - "policy_id"
    - "policy_version"
    - "agent_id"
    - "task_or_request_id"
    - "payee"
    - "amount_and_currency"
    - "decision"                           # allowed | needs_approval | denied, with the rule that decided
    - "approver_and_time"
    - "idempotency_key"
    - "provider_reference"
    - "final_outcome"
  retention_years: 7                       # example: follow your own record-keeping rules

reconciliation:
  required: true
  match_against:                           # an agent payment is finished only when the evidence agrees
    - "provider_status"
    - "settlement_file"
    - "bank_statement"
  unexplained_difference: "open_exception_with_owner"

review:
  cadence: "monthly"                       # example: review limits, payees and denied attempts
  reviewers:
    - "head-of-finance@example.com"
    - "risk@example.com"
  last_reviewed: "2026-09-29"              # example
