Policy rules reference

Sandbox live. Create a free sandbox workspace at agentic-sandbox.pinkwallet.com (test credentials only; no money moves). Production is not yet available.

A policy is an ordered list of rules plus three circuit breakers. Every payment request is checked the same way: breakers first, then rules top to bottom, first match decides, and anything no rule covers is blocked. This page is the schema behind the plain-language rules you see in the console and in Policy Copilot.

Evaluation order

  1. Agent registered? An unknown key gets nothing: no card, no transfer, no error detail.
  2. Agent active? A paused agent is blocked on its next request.
  3. Monthly budget. Spent this month plus this amount must not exceed the agent's budget.
  4. Company daily ceiling. All agents together, per day.
  5. Vault balance. The agent's vault must hold the amount.
  6. Rules, top to bottom. First match wins.
  7. Default: block.

The rule object

{
  "id": "r14",
  "name": "Supplier payment without a matching PO: blocked",
  "note": "PO must exist in the ERP",
  "agents": [
    "a_proc"
  ],
  "payee": "approved",
  "min": 0,
  "max": null,
  "window": "tx",
  "action": "block",
  "absent": "po"
}
FieldValuesMeaning
agents"*" or a list of agent idsWhich agents the rule covers.
payeeany · approved · new · cat:<category> · list of payee idsapproved = on the payee list; new = not on it; cat:ads, cat:cloud, cat:api, cat:supplier, cat:contractor, cat:hardware, cat:logistics, cat:refund, cat:creator, cat:duty, cat:saas, cat:gov, cat:payroll; cat:blocked matches gift cards, crypto exchanges, cash-like and gambling by name.
min / maxnumbers in USD-equivalent; max: null = no upper boundInclusive range the measured value must fall in.
windowtx · day · monthWhat is measured: this payment alone, the agent's spend today plus this payment, or the agent's spend this month plus this payment.
actionallow · ask · blockask needs approvers.
approvers{people:[ids], n} or {group: id, n}Named people, or a quorum of a group (for example 2 of 3 executives).
requires / absenta flagThe rule matches only if the request (or the payee) carries the flag / does not carry it. Flags: po, sow, ticket, scan, statement, brief, renewal, dupInvoice, payeeChanged, repeatCustomer, deposit.
currencyUSD · EUR · GBP · HKD · SGD · JPYRule applies only to payments in that currency.
outsideHours[start, end] in 24hRule applies only when the request's local hour is outside the window, for example [6, 23] for night-time controls.

Patterns that recur in real policies

Fraud controls above amount tiers

[
  {
    "id": "r2",
    "name": "Payee changed bank details in the last 7 days: CFO verifies by phone",
    "agents": "*",
    "payee": "approved",
    "min": 0,
    "max": null,
    "window": "tx",
    "action": "ask",
    "requires": "payeeChanged",
    "approvers": {
      "people": [
        "cfo"
      ],
      "n": 1
    }
  },
  {
    "id": "r3",
    "name": "Duplicate invoice number within 90 days: blocked",
    "agents": "*",
    "payee": "any",
    "min": 0,
    "max": null,
    "window": "tx",
    "action": "block",
    "requires": "dupInvoice"
  }
]

Amount tiers

[
  {
    "id": "r18",
    "name": "Supplier reorders under $2,000: automatic",
    "agents": [
      "a_proc"
    ],
    "payee": "approved",
    "min": 0,
    "max": 2000,
    "window": "tx",
    "action": "allow"
  },
  {
    "id": "r19",
    "name": "Supplier orders $2,000–$10,000: Head of Supply",
    "agents": [
      "a_proc"
    ],
    "payee": "approved",
    "min": 2000,
    "max": 10000,
    "window": "tx",
    "action": "ask",
    "approvers": {
      "group": "g_supply",
      "n": 1
    }
  },
  {
    "id": "r6",
    "name": "Over $50,000 in one payment: 2 of 3 executives",
    "agents": "*",
    "payee": "any",
    "min": 50000,
    "max": null,
    "window": "tx",
    "action": "ask",
    "approvers": {
      "group": "g_exec",
      "n": 2
    }
  }
]

A circuit breaker with no approval path

The month window and the day window turn a cap into a stop. The second rule has no approvers on purpose: a runaway process should not be able to ask its way through.

[
  {
    "id": "r3",
    "name": "API credits: $200 a day per agent, then stop",
    "agents": [
      "a_eng"
    ],
    "payee": "cat:api",
    "min": 0,
    "max": 200,
    "window": "day",
    "action": "allow"
  },
  {
    "id": "r4",
    "name": "API credits over $200 a day: blocked",
    "agents": [
      "a_eng"
    ],
    "payee": "cat:api",
    "min": 200,
    "max": null,
    "window": "day",
    "action": "block"
  }
]

Evidence as a condition

[
  {
    "id": "r11",
    "name": "Creator payouts up to $1,500 with a signed brief",
    "agents": [
      "a_creator"
    ],
    "payee": "cat:creator",
    "min": 0,
    "max": 1500,
    "window": "tx",
    "action": "allow",
    "requires": "brief"
  },
  {
    "id": "r26",
    "name": "Returns AI: no refund before the warehouse scan",
    "agents": [
      "a_ret"
    ],
    "payee": "cat:refund",
    "min": 0,
    "max": null,
    "window": "tx",
    "action": "block",
    "absent": "scan"
  }
]

Currency and time of day

[
  {
    "id": "r17",
    "name": "HKD payments above HK$200,000: CFO, no automatic FX",
    "agents": [
      "a_proc"
    ],
    "payee": "approved",
    "min": 25600,
    "max": null,
    "window": "tx",
    "action": "ask",
    "currency": "HKD",
    "approvers": {
      "people": [
        "cfo"
      ],
      "n": 1
    }
  },
  {
    "id": "r5",
    "name": "Outside 06:00–23:00 SGT: finance on-call decides",
    "agents": [
      "a_proc",
      "a_logi",
      "a_fin"
    ],
    "payee": "any",
    "min": 0,
    "max": null,
    "window": "tx",
    "action": "ask",
    "outsideHours": [
      6,
      23
    ],
    "approvers": {
      "group": "g_fin",
      "n": 1
    }
  }
]

Publishing a policy

Replace the whole rule list with PUT /v1/admin/rules (admin key). The server validates every rule, publishes a new numbered version, and every later request is checked against it. Past payments stay tied to the version that decided them.

curl -X PUT https://agentic-sandbox.pinkwallet.com/v1/admin/rules \
  -H "Authorization: Bearer <admin_key>" -H "Content-Type: application/json" \
  -d '{"rules":[ ...full ordered list... ], "by":"Sarah Kim"}'
# → {"policy_version": 2, "rules": 18}

How an agent sees the rules

pink.list_rules returns the rules that apply to the calling agent, in order, with approver labels resolved. This is the first rule the Purchasing AI sees in the coffee template:

{
  "id": "r11",
  "name": "Never: gift cards, cash-like, crypto",
  "agents": "*",
  "payee": "cat:blocked",
  "amount": {
    "min": 0,
    "max": null,
    "window": "tx"
  },
  "action": "block"
}

Templates

TemplateAgentsRulesWhat it demonstrates
coffee411Caps, a manager tier, a daily ad cap, night-time and new-payee controls.
startup617API-credit circuit breaker, CFO tier, 2-of-3 leadership, statement-matched cloud invoices, hardware tickets.
ecommerce730PO matching, duplicate invoices, payee bank-detail changes, HKD/JPY rules, refund tiers, creator briefs, carrier statements.