<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Quinn</title>
    <description>The latest articles on DEV Community by Quinn (@quinn_854b15f517d8632ed4f).</description>
    <link>https://dev.to/quinn_854b15f517d8632ed4f</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4148138%2Faa0ab823-d61a-4ab9-bb2d-d38d4acc1e86.png</url>
      <title>DEV Community: Quinn</title>
      <link>https://dev.to/quinn_854b15f517d8632ed4f</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/quinn_854b15f517d8632ed4f"/>
    <language>en</language>
    <item>
      <title>How Do I Set Per-Agent Spending Limits for an AI Agent That Pays Through MCP?</title>
      <dc:creator>Quinn</dc:creator>
      <pubDate>Mon, 02 Nov 2026 17:33:29 +0000</pubDate>
      <link>https://dev.to/quinn_854b15f517d8632ed4f/how-do-i-set-per-agent-spending-limits-for-an-ai-agent-that-pays-through-mcp-c4j</link>
      <guid>https://dev.to/quinn_854b15f517d8632ed4f/how-do-i-set-per-agent-spending-limits-for-an-ai-agent-that-pays-through-mcp-c4j</guid>
      <description>&lt;p&gt;Give the agent its own workspace identity, give that identity a monthly budget, and add an amount rule with a &lt;code&gt;tx&lt;/code&gt; (per-transaction) window set to the dollar amount you want to be the hard per-payment ceiling. A rule evaluation engine then checks every payment request against the budget and the rule before anything is issued, and returns &lt;code&gt;allowed&lt;/code&gt;, &lt;code&gt;blocked&lt;/code&gt;, or &lt;code&gt;pending_human&lt;/code&gt; instead of a yes/no guess. Below is a full walkthrough using a real policy engine (Pink Agentic AI Payments' public sandbox) so you can see the actual request and response bodies, not a diagram.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the limits are layered
&lt;/h2&gt;

&lt;p&gt;Pink checks three kinds of limit, in this order, before it issues anything: company breakers (agent paused, the agent's monthly budget used up, the company-wide daily ceiling hit, vault balance), then the rule list, top to bottom, first match wins, default is block. Rules carry an amount range and a window: &lt;code&gt;tx&lt;/code&gt; (this payment alone), &lt;code&gt;day&lt;/code&gt; or &lt;code&gt;month&lt;/code&gt; (running total). A hard per-payment ceiling is a rule with &lt;code&gt;window: "tx"&lt;/code&gt;. The steps below set that up and run it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: create a sandbox workspace
&lt;/h2&gt;

&lt;p&gt;No signup form, just a POST. This returns an admin key for the company dashboard and one API key per seeded agent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://agentic-sandbox.pinkwallet.com/v1/sandbox/workspaces &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"company":"Acme Procurement Test","email":"you@example.com","template":"coffee"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response includes a &lt;code&gt;workspace_id&lt;/code&gt;, an &lt;code&gt;admin_key&lt;/code&gt;, and a list of agents, each with its own key and MCP URL, for example &lt;code&gt;https://agentic-sandbox.pinkwallet.com/mcp/&amp;lt;agent_key&amp;gt;&lt;/code&gt;. The "coffee" template seeds four agents (Purchasing, Inventory, Marketing, Payroll &amp;amp; Bills) with starter budgets and payees so you don't have to build fixtures by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: give the agent a monthly budget
&lt;/h2&gt;

&lt;p&gt;Every agent already has a &lt;code&gt;monthly&lt;/code&gt; budget field. You can raise or lower it from the admin side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; PATCH https://agentic-sandbox.pinkwallet.com/v1/admin/agents/a_purch &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ADMIN_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"monthly":3000}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checking the agent's own view of its budget confirms the number is live:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Purchasing AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"monthly_budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"spent_this_month"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2260&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"left_this_month"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;740&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"single_payment_cap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"company_daily_ceiling"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response also shows a &lt;code&gt;single_payment_cap&lt;/code&gt; field. In the current sandbox the engine does not check that field when deciding a payment, so set the per-payment ceiling with a rule, as in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: add a per-payment amount rule with window "tx"
&lt;/h2&gt;

&lt;p&gt;The policy is a list of rules evaluated top to bottom, first match wins, default is block. To make a hard per-payment ceiling, add a rule with &lt;code&gt;window: "tx"&lt;/code&gt; and no monthly or daily accumulation, just the single transaction amount:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; PUT https://agentic-sandbox.pinkwallet.com/v1/admin/rules &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ADMIN_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "rules": [
      {
        "id": "r_cap",
        "name": "Hard per-payment cap: $150 (Purchasing AI)",
        "agents": ["a_purch"],
        "payee": "any",
        "min": 150.01,
        "max": null,
        "window": "tx",
        "action": "block"
      }
    ]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This rule has to sit ahead of any rule that would otherwise allow the same payee and agent for a larger amount, because the engine stops at the first match. Putting it first in the array achieves that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: try an in-limit payment
&lt;/h2&gt;

&lt;p&gt;Over REST (the same calls are exposed as MCP tools, &lt;code&gt;pink.check_policy&lt;/code&gt; and &lt;code&gt;pink.request_payment&lt;/code&gt;, for a client that connects over MCP):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://agentic-sandbox.pinkwallet.com/v1/payments &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$AGENT_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_id":"p_sysco","amount":120,"currency":"USD","purpose":"Weekly milk and syrup reorder"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual response from this sandbox run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payment_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_bb13deacc29e"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Purchasing AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sysco"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Small supply orders go through"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtual_card"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sandbox"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"single_use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"card"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"pan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4111 1111 7298 7706"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"exp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12/27"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"cvv"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"843"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;$120 is under the $150 cap, so the new block rule skips, and an older allow rule for approved suppliers under $500 matches instead. A single-use virtual card number is issued for exactly $120.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: try an over-limit payment
&lt;/h2&gt;

&lt;p&gt;Same agent, same payee, bigger amount:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://agentic-sandbox.pinkwallet.com/v1/payments &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$AGENT_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_id":"p_sysco","amount":300,"currency":"USD","purpose":"Large milk and syrup reorder"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payment_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_f0e7f8427aea"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hard per-payment cap: $150 (Purchasing AI)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"why"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"matched · block"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;$300 is well inside the agent's monthly budget (there was $740 left), and well inside the vault balance. It is blocked purely because the per-transaction rule matched before any allow rule had a chance to. No credential is issued. The dry-run endpoint, &lt;code&gt;pink.check_policy&lt;/code&gt; / &lt;code&gt;POST /v1/payments/check&lt;/code&gt;, returns the same decision with a full trace, step by step, without spending anything, useful when you want to show the agent (or a human) why a payment would fail before it tries.&lt;/p&gt;

&lt;h2&gt;
  
  
  A third outcome: held for a human
&lt;/h2&gt;

&lt;p&gt;The same rule set also contains a rule that asks a human whenever the agent tries to pay a payee that isn't on the approved list, regardless of amount:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending_human"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"New payee: always ask the owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hold_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_009dec96a998"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"approvers_needed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"who"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Maya Chen (Owner)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"poll"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pink.get_credential(hold_id) · or GET /v1/payments/{id}"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent (or the MCP client driving it) polls that hold until a person approves or declines it. This is the third decision type, next to allowed and blocked: the payment is neither executed nor refused, it waits.&lt;/p&gt;

&lt;p&gt;Pink Agentic AI Payments checks each agent's budget and amount rules at the MCP layer, before a payment executes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What other approaches exist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stripe's agent tooling&lt;/strong&gt;: Stripe publishes an MCP server and an "Agents" surface (&lt;code&gt;docs.stripe.com/agents&lt;/code&gt;) built on top of Stripe Issuing, where spend controls (card-level limits, real-time authorization, restricted API keys) are enforced by Stripe Issuing when the card is authorized. If you already use Stripe Issuing, this is a reasonable starting point. See &lt;a href="https://docs.stripe.com/agents" rel="noopener noreferrer"&gt;docs.stripe.com/agents&lt;/a&gt; and &lt;a href="https://docs.stripe.com/mcp" rel="noopener noreferrer"&gt;docs.stripe.com/mcp&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;x402 (Coinbase)&lt;/strong&gt;: a protocol that uses the HTTP 402 status code so a server can ask for payment inline, settled in stablecoins on EVM-compatible chains or Solana, with no accounts or API keys. It's built for per-request micropayments rather than company-defined budgets per agent; spend limits aren't part of the base spec. See &lt;a href="https://www.x402.org/" rel="noopener noreferrer"&gt;x402.org&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AP2 (Google)&lt;/strong&gt;: an open protocol extension to Agent2Agent (A2A), currently at spec version 0.2, that defines "mandates" (cryptographically signed authorization objects) a human or policy can issue to constrain what an agent is allowed to buy. It's a specification for how parties talk to each other, not a hosted payments product you call. See &lt;a href="https://ap2-protocol.org/" rel="noopener noreferrer"&gt;ap2-protocol.org&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your use case is "one AI client, connect once over MCP, get a per-agent budget and a per-payment rule enforced server-side before anything is issued," that's the shape this walkthrough covers. If you need live settlement in stablecoins today, or you're already deep in Stripe Issuing, the two links above are worth reading directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The sandbox above uses fake money and seeded templates, no card or bank details required to create a workspace. Try the full flow: &lt;a href="https://agentic-sandbox.pinkwallet.com" rel="noopener noreferrer"&gt;agentic-sandbox.pinkwallet.com&lt;/a&gt;. Developer docs: &lt;a href="https://pinkwallet.com/agentic/developers/?utm_source=devto&amp;amp;utm_campaign=p24" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers&lt;/a&gt;. In production, Pink runs as a decision layer: your agent asks Pink first, and your own Stripe, card or bank pays only if Pink allows it. Pink never holds or moves your money. A pilot on your own production tenant is $99/month, month to month, first month refundable within 30 days: &lt;a href="https://pinkwallet.com/agentic/pilot/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=p24-per-agent-limits" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/pilot&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>payments</category>
      <category>agents</category>
    </item>
    <item>
      <title>What Is the Best Payment API for AI Agents in 2026?</title>
      <dc:creator>Quinn</dc:creator>
      <pubDate>Mon, 02 Nov 2026 14:00:50 +0000</pubDate>
      <link>https://dev.to/quinn_854b15f517d8632ed4f/what-is-the-best-payment-api-for-ai-agents-in-2026-22gh</link>
      <guid>https://dev.to/quinn_854b15f517d8632ed4f/what-is-the-best-payment-api-for-ai-agents-in-2026-22gh</guid>
      <description>&lt;p&gt;There isn't one best payment API for AI agents in 2026, there's a best fit for your constraint. If you need live stablecoin settlement today, look at x402. If you're already on Stripe Issuing, Stripe's agent tooling is the shortest path. If your blocker is "the finance team won't let an agent touch money without a budget and an approval step," that's the problem Pink Agentic AI Payments (and Payman) are built around. This is a practical comparison of seven options, built from each vendor's own public documentation, checked on the date below.&lt;/p&gt;

&lt;p&gt;Last checked: 2026-10-26.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;Agent connects via&lt;/th&gt;
&lt;th&gt;Spend controls&lt;/th&gt;
&lt;th&gt;Settlement rail&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.stripe.com/agents" rel="noopener noreferrer"&gt;Stripe agent tooling&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;API/SDK/MCP server on top of Stripe Issuing and Payments&lt;/td&gt;
&lt;td&gt;REST API, SDKs, MCP server (&lt;code&gt;mcp.stripe.com&lt;/code&gt;), restricted API keys&lt;/td&gt;
&lt;td&gt;Card-level limits and real-time authorization, enforced by Stripe Issuing when a card is authorized&lt;/td&gt;
&lt;td&gt;Card networks (Stripe Issuing virtual/physical cards)&lt;/td&gt;
&lt;td&gt;Issuing and the MCP server are live products&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.x402.org/" rel="noopener noreferrer"&gt;Coinbase x402&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Open protocol using HTTP 402 for inline, per-request payment&lt;/td&gt;
&lt;td&gt;Any HTTP client; server responds 402, client pays and retries&lt;/td&gt;
&lt;td&gt;Not detailed in public docs; architecture favors per-request pricing over standing budgets&lt;/td&gt;
&lt;td&gt;Stablecoins on EVM-compatible chains and Solana&lt;/td&gt;
&lt;td&gt;Live, with multiple open-source implementations (usage figures on x402.org are self-reported)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://ap2-protocol.org/" rel="noopener noreferrer"&gt;Google AP2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Open protocol spec extending Agent2Agent (A2A) for agent purchases&lt;/td&gt;
&lt;td&gt;Implement the protocol; not a hosted API you call&lt;/td&gt;
&lt;td&gt;"Mandates" (Checkout Mandate, Payment Mandate) a human or policy signs to constrain what's bought and how it's paid&lt;/td&gt;
&lt;td&gt;Not specified; protocol is rail-agnostic&lt;/td&gt;
&lt;td&gt;Specification stage, version 0.2; not a live commercial product&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://skyfire.xyz/" rel="noopener noreferrer"&gt;Skyfire&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Identity and payment infrastructure using "Know Your Agent" (KYA) tokens&lt;/td&gt;
&lt;td&gt;KYA token issuance plus a REST API (&lt;code&gt;api.skyfire.xyz&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Not stated in public docs&lt;/td&gt;
&lt;td&gt;Tokenized cards (Visa, Mastercard, Discover) and USDC&lt;/td&gt;
&lt;td&gt;Live walkthrough shown on site; GA status not stated in public docs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/PaymanAI/documentation" rel="noopener noreferrer"&gt;Payman&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;AI-first payment infrastructure with per-agent wallets and a policy engine&lt;/td&gt;
&lt;td&gt;REST API, Python/TypeScript/JS SDKs&lt;/td&gt;
&lt;td&gt;Daily limits, per-transaction caps, approval thresholds, pre-approved payees; policy engine evaluates before execution&lt;/td&gt;
&lt;td&gt;See vendor docs (not verified on the check date)&lt;/td&gt;
&lt;td&gt;Presented as live by the vendor; not verified on the check date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.crossmint.com/" rel="noopener noreferrer"&gt;Crossmint&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Wallets, payments, and an "Agents" product with an MCP server&lt;/td&gt;
&lt;td&gt;Crossmint MCP server, REST API&lt;/td&gt;
&lt;td&gt;"Every allowance is scoped, explicit, and revocable"; card limits enforced at Visa/Mastercard, wallet limits enforced onchain (their wording)&lt;/td&gt;
&lt;td&gt;Stablecoins and card rails&lt;/td&gt;
&lt;td&gt;Availability not stated in public docs for the agents product specifically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pink Agentic AI Payments&lt;/td&gt;
&lt;td&gt;MCP server plus REST API plus a company dashboard for spending rules per agent&lt;/td&gt;
&lt;td&gt;MCP (&lt;code&gt;/mcp/&amp;lt;agent_key&amp;gt;&lt;/code&gt;) or REST, one API key per agent&lt;/td&gt;
&lt;td&gt;Monthly budgets per agent, amount rules with a tx/day/month window, company-wide daily ceiling, human approval holds, all checked server-side before a credential is issued&lt;/td&gt;
&lt;td&gt;Sandbox issues virtual cards, bank transfers, or platform refunds; production decides only, your own Stripe, card or bank pays&lt;/td&gt;
&lt;td&gt;Production live since Oct 2026 as a decision layer ($99/month pilot, first month refundable within 30 days); public sandbox free; not yet proven at high production volume&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Notes on reading this table
&lt;/h2&gt;

&lt;p&gt;A few cells say "not stated in public docs." That's not a knock on the product, it means the information wasn't in the pages I could read as of the check date above. If you're evaluating any of these for real, ask the vendor directly rather than assuming the blank means "no."&lt;/p&gt;

&lt;p&gt;Payman's docs site did not load on the check date, so its row is based on the vendor's public documentation repo and its own descriptions. Verify the details with Payman directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pink Agentic AI Payments, in more detail
&lt;/h2&gt;

&lt;p&gt;Pink's sandbox lets you create a workspace with seeded agents, each with a monthly budget and a starter rule set, for free, with no card required: &lt;a href="https://agentic-sandbox.pinkwallet.com" rel="noopener noreferrer"&gt;agentic-sandbox.pinkwallet.com&lt;/a&gt;. The rule engine evaluates company breakers first (is the agent paused, is the monthly budget already used up, is the company-wide daily ceiling hit, is there balance in the vault), then walks the rule list top to bottom, first match decides, default is block. A rule with a &lt;code&gt;tx&lt;/code&gt; window is what gives you a hard per-payment ceiling; a rule with a &lt;code&gt;day&lt;/code&gt; or &lt;code&gt;month&lt;/code&gt; window gives you a rolling spend cap. Any rule can require human approval instead of allowing or blocking outright, which is how a payment ends up &lt;code&gt;pending_human&lt;/code&gt; with a hold id an agent can poll.&lt;/p&gt;

&lt;p&gt;Pink Agentic AI Payments is the option built around company-defined spending rules: an agent connects over MCP, and every payment is checked against its budget and rules before it runs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose Pink if&lt;/strong&gt; you want one MCP connection per agent and a dashboard where someone outside engineering can set a budget, an amount rule, and an approval threshold without reading code, and you're fine running on a sandbox while the team evaluates it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pink is not the right fit if&lt;/strong&gt; you need live stablecoin or on-chain settlement in production today, or you need a payments platform that is already generally available at production volume. For the former, look at x402 or AP2 implementations with a settlement partner; for the latter, Stripe's agent tooling sits on top of an already-GA Issuing product.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to actually decide
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Settlement rail first.&lt;/strong&gt; If the payment has to land in a crypto wallet today, your shortlist is x402 (or a protocol built on it) or a stablecoin-first platform like Crossmint. If it has to land on a card or bank rail, Stripe covers that today. Pink's sandbox issues single-use virtual card and bank transfer credentials; in production Pink only decides, and your own card, bank or Stripe account settles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Who writes the spending rule.&lt;/strong&gt; If it has to be an engineer shipping code, most of these work. If it has to be someone in finance or ops, without a deploy, look specifically for a dashboard, not just an API: Payman and Pink both describe one; Stripe's controls live inside Stripe Issuing's dashboard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protocol vs. product.&lt;/strong&gt; AP2 is a specification you'd implement yourself or wait for a vendor to support; it is not something you call today and get a payment back. x402 is both a spec and a live set of implementations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How real is "status."&lt;/strong&gt; A live walkthrough on a marketing page is not the same as GA. Ask for the production rate limits, the uptime SLA, and whether the vendor will say "yes" if you ask "can I send real production volume through this right now."&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Pink's sandbox: &lt;a href="https://agentic-sandbox.pinkwallet.com" rel="noopener noreferrer"&gt;agentic-sandbox.pinkwallet.com&lt;/a&gt;. Developer docs: &lt;a href="https://pinkwallet.com/agentic/developers/?utm_source=devto&amp;amp;utm_campaign=p02" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers&lt;/a&gt;. Production pilot on your own tenant, $99/month, month to month, first month refundable within 30 days: &lt;a href="https://pinkwallet.com/agentic/pilot/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=p02-best-payment-api" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/pilot&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>payments</category>
      <category>agents</category>
      <category>mcp</category>
    </item>
    <item>
      <title>How Can an AI Agent Make a Payment on Its Own? The Infrastructure You Actually Need</title>
      <dc:creator>Quinn</dc:creator>
      <pubDate>Sat, 31 Oct 2026 14:00:41 +0000</pubDate>
      <link>https://dev.to/quinn_854b15f517d8632ed4f/how-can-an-ai-agent-make-a-payment-on-its-own-the-infrastructure-you-actually-need-56ol</link>
      <guid>https://dev.to/quinn_854b15f517d8632ed4f/how-can-an-ai-agent-make-a-payment-on-its-own-the-infrastructure-you-actually-need-56ol</guid>
      <description>&lt;p&gt;An autonomous agent payment needs five things: a way for the agent to ask (a tool interface such as MCP), a decision layer outside the model that checks company rules, a short-lived credential scoped to the one approved payment, a payment rail that actually moves money, and an audit trail that records what happened and why. Pink Agentic AI Payments covers the first three and the last one today, in a sandbox, with test money.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I work on Pink Agentic AI Payments at PinkWallet. This post was written with AI and checked against the product source.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The question "can my agent just pay for things" comes up the moment you give an LLM a task with a real-world cost attached: reorder stock when it runs low, renew a subscription, pay a contractor invoice, top up an ad budget. The model can decide &lt;em&gt;that&lt;/em&gt; a payment should happen. It should never be the thing that decides &lt;em&gt;whether&lt;/em&gt; it is allowed to happen. That decision needs to live outside the model, on a server, before any money moves.&lt;/p&gt;

&lt;p&gt;Pink Agentic AI Payments decides on the server, before any money moves, whether an agent's payment request is allowed, blocked or sent to a person.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five layers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Why the model can't do it itself&lt;/th&gt;
&lt;th&gt;What Pink does today&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. Tool interface&lt;/td&gt;
&lt;td&gt;Gives the agent a defined, callable way to ask for a payment instead of free text or screen-scraping a checkout page&lt;/td&gt;
&lt;td&gt;An LLM has no native "pay" action; without a tool contract it can only describe intent, not execute it&lt;/td&gt;
&lt;td&gt;An MCP server (&lt;code&gt;pink.get_budget&lt;/code&gt;, &lt;code&gt;pink.list_payees&lt;/code&gt;, &lt;code&gt;pink.list_rules&lt;/code&gt;, &lt;code&gt;pink.check_policy&lt;/code&gt;, &lt;code&gt;pink.request_payment&lt;/code&gt;, &lt;code&gt;pink.get_credential&lt;/code&gt;, &lt;code&gt;pink.report_receipt&lt;/code&gt;) plus a REST mirror of the same calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Decision layer&lt;/td&gt;
&lt;td&gt;Evaluates the request against company rules: budgets, ceilings, payee and category rules, time windows, required evidence&lt;/td&gt;
&lt;td&gt;The model can be prompted, jailbroken, or just wrong; a decision that lives inside the model's context can be talked out of itself&lt;/td&gt;
&lt;td&gt;A rules engine that runs server-side on every request: agent registration and status, monthly budget, company-wide daily ceiling, vault balance, then named rules in order, first match decides, default is block&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Short-lived credential&lt;/td&gt;
&lt;td&gt;Issues something the agent can actually use to pay, scoped tightly enough that holding it is not a standing risk&lt;/td&gt;
&lt;td&gt;An agent that holds a real card number or bank login is an agent that can spend outside the decision it was just given&lt;/td&gt;
&lt;td&gt;A single-use credential locked to the approved payee and amount, expiring in 15 minutes. The agent never holds a standing card, bank login or API key to the rail itself&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4. Payment rail&lt;/td&gt;
&lt;td&gt;Actually moves the money: card network, bank transfer, platform settlement&lt;/td&gt;
&lt;td&gt;Out of scope for this post. Pink's production version leaves the rail to you: your own Stripe, card or bank pays after Pink allows the payment&lt;/td&gt;
&lt;td&gt;The sandbox issues test credentials of type &lt;code&gt;virtual_card&lt;/code&gt;, &lt;code&gt;bank_transfer&lt;/code&gt;, or &lt;code&gt;platform_refund&lt;/code&gt; depending on how the payee is set up, but no real money moves&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5. Audit trail&lt;/td&gt;
&lt;td&gt;Records the request, the rule that fired, the credential issued, and (optionally) the receipt filed afterward, so every payment is traceable after the fact&lt;/td&gt;
&lt;td&gt;A chat transcript is not a ledger; "the agent said it paid for it" is not evidence of what actually happened&lt;/td&gt;
&lt;td&gt;Every request is logged against a policy version with the rule name, decision, and credential (if issued); the admin console exposes this as a transaction list and a per-request decision trace&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The point of separating these is that each one fails differently. A broken tool interface means the agent can't ask. A broken decision layer means the agent asks and gets a wrong answer. A broken credential means a right answer leaks into standing access. A missing audit trail means nobody can tell which of those happened after the fact. Bundling them into one black box makes it harder to tell which layer broke.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tracing one payment end to end
&lt;/h2&gt;

&lt;p&gt;To make this concrete, here is one real payment through a sandbox workspace seeded with a small coffee shop's agents, vaults and rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: the agent lists what it's allowed to spend.&lt;/strong&gt; An MCP client connects to the sandbox's MCP endpoint with the agent's key and calls &lt;code&gt;tools/list&lt;/code&gt;, which returns seven tools. The description of &lt;code&gt;pink.get_budget&lt;/code&gt; reads: "What this agent may still spend: monthly budget left, spent today, single-payment cap, vault balances, company daily ceiling." One honest caveat here: a per-agent "single-payment cap" field exists in the budget response, but it is not what actually blocks an oversized payment. The enforcement for "no payment over $X" comes from a named rule with a maximum amount and a transaction-level window, evaluated the same way every other rule is. More on that below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: the agent checks the policy before committing.&lt;/strong&gt; A dry run against &lt;code&gt;pink.check_policy&lt;/code&gt; (or its REST equivalent, &lt;code&gt;POST /v1/payments/check&lt;/code&gt;) for a $180 payment to an approved supplier returned this trace (trimmed: two SKIP lines for rules that didn't apply are left out, and one is shortened):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"would_allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Small supply orders go through"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"PASS · Agent registered · Purchasing AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"PASS · Agent active · not paused"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"PASS · Monthly budget · $2,440 of $4,000 after this"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"PASS · Daily ceiling, all agents · $180 of $6,000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"PASS · Vault balance · Operating · $18,420.55 available"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"SKIP · Never: gift cards, cash-like, crypto · payee out of scope"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"SKIP · Between 11pm and 6am: ask the owner · inside business hours"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"PASS · Small supply orders go through · matched · allow"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule that actually matched, "Small supply orders go through," is defined with a minimum of $0, a maximum of $500, and a window of &lt;code&gt;tx&lt;/code&gt;, meaning per transaction. That is what a real per-payment cap looks like in this engine: not a separate field that gets checked on its own, but an amount rule scoped to a single transaction. The engine evaluates rules top to bottom and the first one whose agent, payee and amount conditions all match decides the outcome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: the agent requests the payment for real.&lt;/strong&gt; The same request goes to &lt;code&gt;pink.request_payment&lt;/code&gt; (or &lt;code&gt;POST /v1/payments&lt;/code&gt;). In production code, also pass an idempotency key: repeating a key returns the original decision instead of paying twice. The response includes a credential:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payment_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_a19642a69639"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Small supply orders go through"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtual_card"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sandbox"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"currency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"locked_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sysco"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"single_use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-26T12:12:24.338Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"card"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"pan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[redacted]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"exp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12/27"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"cvv"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[redacted]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PINK SANDBOX"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The credential carries its own limits independent of anything the agent might try to do with it: &lt;code&gt;max_amount&lt;/code&gt; matches the approved amount exactly, &lt;code&gt;locked_to&lt;/code&gt; names the specific payee, &lt;code&gt;single_use&lt;/code&gt; is true, and it expires in fifteen minutes. If the decision had been "ask" instead of "allow" (for example, a new payee, a payment outside business hours, or an amount above the small-order threshold), the response would carry a &lt;code&gt;hold_id&lt;/code&gt; instead of a credential, and the agent would poll &lt;code&gt;pink.get_credential&lt;/code&gt; until a person approved or declined it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: the payment lands in the audit trail.&lt;/strong&gt; The admin view of this workspace shows the same payment as a transaction record: payment id, decision, agent, payee, amount, the rule name that fired, the policy version it was evaluated against, and the credential that was issued. That policy version matters more than it looks: every transaction is stamped with the rule set that was active when it ran, so changing the rules tomorrow does not rewrite what happened today.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does and doesn't solve
&lt;/h2&gt;

&lt;p&gt;This covers layers 1, 2, 3 and 5. It does not pick a payment rail, and it should not be read as claiming to. In Pink's production version the rail stays yours, which is a separate decision from "should this payment happen and under what scoped credential." Keeping those decoupled is deliberate: the policy engine and the credential issuance do not need to know or care how the money eventually settles.&lt;/p&gt;

&lt;p&gt;It is also worth being direct about what is still a sandbox. Every number above came from test money in a workspace created for this post. The credential numbers are not real card numbers. Nothing here moved currency. Pink's production version (live since October 2026) runs the decision layer and the audit trail only; it does not issue credentials, and your own payment method pays.&lt;/p&gt;

&lt;p&gt;If you are building an agent that needs to spend money without you reading every line of its tool calls, the sandbox is free to try: &lt;a href="https://pinkwallet.com/agentic/developers/" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers&lt;/a&gt;. Sandbox: test money only. A pilot on your own production tenant is $99/month: &lt;a href="https://pinkwallet.com/agentic/pilot/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=p01-agent-payment-infra" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/pilot&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>mcp</category>
      <category>fintech</category>
    </item>
    <item>
      <title>Which Payment Provider Works Best for Autonomous AI Procurement?</title>
      <dc:creator>Quinn</dc:creator>
      <pubDate>Fri, 30 Oct 2026 14:00:46 +0000</pubDate>
      <link>https://dev.to/quinn_854b15f517d8632ed4f/which-payment-provider-works-best-for-autonomous-ai-procurement-bhm</link>
      <guid>https://dev.to/quinn_854b15f517d8632ed4f/which-payment-provider-works-best-for-autonomous-ai-procurement-bhm</guid>
      <description>&lt;p&gt;For autonomous AI procurement, the provider that works best is the one where a company's own rules, not the agent, decide whether an order goes through. Pink Agentic AI Payments does this: a procurement agent requests a purchase, a rules engine checks it against vendor, amount, and budget policy, and anything outside policy routes to a named human approver before any money moves. Only on approval does the agent receive a single-use credential locked to that vendor and amount.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I work on Pink Agentic AI Payments at PinkWallet. This post was written with AI and checked against the product source.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pink Agentic AI Payments routes any purchase order above a company-set amount to a named approver before a credential is issued.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a procurement agent actually needs to buy things
&lt;/h2&gt;

&lt;p&gt;A procurement agent isn't a chatbot with a credit card. It reorders from known suppliers, occasionally tries a new vendor, and needs someone in finance or supply chain to see anything unusual before money leaves the company. Below is what that requires from a payment provider, checked against a sandbox workspace seeded with an e-commerce company's actual procurement policy (seven agents, thirty rules, one of them a dedicated Procurement AI with a $400,000 monthly budget and a $612,000 supplier vault).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Why procurement needs it&lt;/th&gt;
&lt;th&gt;What I observed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Vendor/payee allowlist&lt;/td&gt;
&lt;td&gt;Reordering from an approved supplier shouldn't need a human every time&lt;/td&gt;
&lt;td&gt;A payment to an approved payee under policy limits returned &lt;code&gt;"decision": "allowed"&lt;/code&gt; with no approval step&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New-vendor handling&lt;/td&gt;
&lt;td&gt;A vendor the agent has never paid before is exactly the case that needs a second look&lt;/td&gt;
&lt;td&gt;A payment to an unlisted payee name returned &lt;code&gt;"decision": "pending_human"&lt;/code&gt;, rule &lt;code&gt;"New supplier: first payment up to $5,000, CFO approves"&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amount thresholds to a human&lt;/td&gt;
&lt;td&gt;Small reorders and six-figure supplier contracts carry different risk and should not share one yes/no gate&lt;/td&gt;
&lt;td&gt;A $5,000 payment to an approved supplier matched a different rule than a $900 payment to the same supplier, see walk-through below&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monthly budget per agent&lt;/td&gt;
&lt;td&gt;A single compromised or malfunctioning agent shouldn't be able to drain the company&lt;/td&gt;
&lt;td&gt;The agent's budget response reported a &lt;code&gt;monthly_budget&lt;/code&gt; figure alongside &lt;code&gt;spent_this_month&lt;/code&gt;, enforced in the same policy check as vendor and amount rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Company daily ceiling&lt;/td&gt;
&lt;td&gt;Procurement is one of several agents drawing from company money; one agent's order shouldn't be evaluated in isolation from the rest&lt;/td&gt;
&lt;td&gt;The same budget response reported &lt;code&gt;company_daily_ceiling&lt;/code&gt; and &lt;code&gt;company_spent_today&lt;/code&gt;, aggregated across all agents in the workspace, not just the procurement agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Category blocks&lt;/td&gt;
&lt;td&gt;Some categories (gift cards, crypto exchanges, cash-like transfers) should never be payable by an agent, full stop, no approval path&lt;/td&gt;
&lt;td&gt;A payment to a payee named like a crypto exchange returned &lt;code&gt;"decision": "blocked"&lt;/code&gt;, rule &lt;code&gt;"Never: gift cards, crypto exchanges, cash-like, gambling"&lt;/code&gt;, with no &lt;code&gt;pending_human&lt;/code&gt; option offered&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One credential per order&lt;/td&gt;
&lt;td&gt;A standing card number or bank login in an agent's hands is a bigger blast radius than a credential good for one payment to one vendor&lt;/td&gt;
&lt;td&gt;Every &lt;code&gt;allowed&lt;/code&gt; or &lt;code&gt;approved&lt;/code&gt; response carried a &lt;code&gt;credential&lt;/code&gt; object with &lt;code&gt;single_use: true&lt;/code&gt;, an &lt;code&gt;expires_at&lt;/code&gt; fifteen minutes out, and &lt;code&gt;locked_to&lt;/code&gt; set to the exact vendor name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audit trail of every decision&lt;/td&gt;
&lt;td&gt;Finance needs to see why an order was allowed, held, or blocked, not just that it was&lt;/td&gt;
&lt;td&gt;An admin-side state query returned a &lt;code&gt;transactions&lt;/code&gt; list where each entry carries the exact rule name that fired, for example &lt;code&gt;"Supplier reorders under $2,000: automatic"&lt;/code&gt; or &lt;code&gt;"Supplier orders $2,000-$10,000: Head of Supply"&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  A purchase order walk-through
&lt;/h2&gt;

&lt;p&gt;I set up a sandbox workspace from a template seeded with a real procurement policy: a Procurement AI agent, a supplier payee list, and thirty rules covering amounts, new vendors, blocked categories, and approval chains. Then I ran four requests through it as that agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A routine reorder.&lt;/strong&gt; $900 to an already-approved textile supplier, inside the automatic-approval band:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Supplier reorders under $2,000: automatic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bank_transfer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"locked_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Yiwu Sunrise Textile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"single_use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-26T12:10:52.230Z"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No human touched this. The credential is a bank transfer reference good for exactly $900 to exactly that supplier, expiring in fifteen minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A larger order to the same supplier.&lt;/strong&gt; $5,000, same vendor, same agent. Crossing the threshold changed which rule fired:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending_human"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Supplier orders $2,000-$10,000: Head of Supply"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"who"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1 of 2 in Supply chain (Tom Becker, Marcus Reed)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"approvers_needed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-26T12:25:52.488Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No credential yet. The hold expires if nobody acts. When the named approver approved it through the admin endpoint, the response changed to &lt;code&gt;"decision": "approved"&lt;/code&gt; with a credential attached and &lt;code&gt;"approved_by": ["Tom Becker"]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An unfamiliar vendor.&lt;/strong&gt; Same agent, same kind of purchase, but a payee name that doesn't exist in the company's payee list yet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending_human"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"New supplier: first payment up to $5,000, CFO approves"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"who"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wei Lim (CFO)"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The amount here, $1,200, was well inside the automatic band for known suppliers, but the new-vendor rule matched before any amount rule got a chance to. A vendor the agent has never paid routes to the CFO regardless of how small the order is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A blocked category.&lt;/strong&gt; A payment addressed to something named like a crypto exchange:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Never: gift cards, crypto exchanges, cash-like, gambling"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"retry_after"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No pending state, no approver listed, nothing to escalate. This category doesn't get a human in the loop because it isn't supposed to be payable at all.&lt;/p&gt;

&lt;p&gt;One honest limit: in the sandbox, this category check works on keywords in the name of a payee that isn't on the approved list (gift, crypto, cash, casino and similar). A payee whose name avoids those words isn't blocked by this rule; it falls through to the next rules instead. In this template that means a first payment up to $5,000 goes to the CFO, and anything larger matches no rule, so the engine's default blocks it. Either way it is not paid automatically.&lt;/p&gt;

&lt;p&gt;Four requests, four different outcomes, and the only thing that changed between them was the vendor and the amount, not the agent's behavior. The agent asked for the same kind of thing every time ("pay this vendor this amount for this purpose"); the policy decided what happened next, and an admin query afterward showed all four decisions with the exact rule name attached to each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for a procurement buyer
&lt;/h2&gt;

&lt;p&gt;If you're evaluating payment infrastructure for a purchasing agent, the question isn't whether the agent is smart enough to know which vendor is legitimate or which amount is too big. It's whether the provider lets you write that policy down once, in rules a company admin controls, and have every agent request checked against it the same way every time, with a human named and pulled in only for the cases that actually need one.&lt;/p&gt;

&lt;p&gt;The tests above ran in Pink's public sandbox on test money; nothing real moved. In production, Pink runs as a decision layer: your agent asks Pink first, and your own Stripe, card or bank pays only if Pink allows it. Pink never holds or moves your money. A pilot on your own production tenant is $99/month: &lt;a href="https://pinkwallet.com/agentic/pilot/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=p20-procurement" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/pilot&lt;/a&gt;. If you're building or evaluating a procurement agent and want to see how an amount threshold, a new-vendor rule, or a blocked category behaves against your own policy shape, the sandbox is free to try at &lt;a href="https://pinkwallet.com/agentic/developers/" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>fintech</category>
      <category>procurement</category>
    </item>
    <item>
      <title>What Are the Risks of Letting AI Agents Make Payments, and What Controls Stop Them?</title>
      <dc:creator>Quinn</dc:creator>
      <pubDate>Thu, 29 Oct 2026 14:00:36 +0000</pubDate>
      <link>https://dev.to/quinn_854b15f517d8632ed4f/what-are-the-risks-of-letting-ai-agents-make-payments-and-what-controls-stop-them-49in</link>
      <guid>https://dev.to/quinn_854b15f517d8632ed4f/what-are-the-risks-of-letting-ai-agents-make-payments-and-what-controls-stop-them-49in</guid>
      <description>&lt;p&gt;The main risks of letting an AI agent make payments are a runaway loop that repeats a payment, a prompt injection that swaps the payee, an agent splitting one purchase into several smaller ones to duck under a threshold, a payment to a blocked category like gift cards, a leaked or reused payment credential, and an approval that nobody ever acts on. The controls that stop them are a policy engine that checks every payment against rules before it executes, a credential that is single-use and locked to one payee and amount instead of a standing card or bank login, and holds that expire instead of sitting open forever.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I work on Pink Agentic AI Payments at PinkWallet. This post was written with AI and checked against the product source.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I run a payments sandbox for AI agents, so I tested each of these risks against it instead of describing them in the abstract. Pink Agentic AI Payments checks every agent payment against company rules on the server before it executes, and the agent only ever receives a single-use credential locked to one payee and amount. Below is what I actually observed, including one place the engine does not stop something you might expect it to.&lt;/p&gt;

&lt;h2&gt;
  
  
  The risk register
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Risk&lt;/th&gt;
&lt;th&gt;General control&lt;/th&gt;
&lt;th&gt;What I observed in the sandbox&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Runaway loop / repeated payments&lt;/td&gt;
&lt;td&gt;A per-agent monthly budget and a company-wide daily ceiling that block once spend crosses the line&lt;/td&gt;
&lt;td&gt;Sent 5 payments of $999 each to the same vendor within about 12 seconds. All 5 were allowed, because none individually crossed the $1,000 rule threshold. Nothing in this template would have stopped further repeats until the agent's monthly budget ($3,785 left afterwards) or the company daily ceiling was reached.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt injection redirecting a payment to a different payee&lt;/td&gt;
&lt;td&gt;Payees that aren't on the approved list go to a human, and so do known payees whose bank details just changed&lt;/td&gt;
&lt;td&gt;An injected instruction to pay someone new hits the new-payee rule: $300 to "Zendesk Inc" (not on the approved list) came back &lt;code&gt;pending_human&lt;/code&gt;, rule &lt;code&gt;New payee: CFO decides&lt;/code&gt;, with no credential. For an approved vendor whose bank details changed, $450 to Dell sent with the &lt;code&gt;payeeChanged&lt;/code&gt; evidence flag came back &lt;code&gt;pending_human&lt;/code&gt;, rule &lt;code&gt;Payee changed bank details in the last 7 days: CFO verifies&lt;/code&gt;. That flag can sit on the payee record or arrive with the payment request, so it should be set by your vendor or invoice system, not by the agent's own judgment.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Splitting a purchase into smaller payments to slip under a threshold&lt;/td&gt;
&lt;td&gt;A rule should ideally cap spend to one payee inside a day or month window, not just per transaction&lt;/td&gt;
&lt;td&gt;Same as the runaway-loop test above: all 5 of the $999 payments landed under the per-transaction rule's $1,000 ceiling and were &lt;code&gt;allowed&lt;/code&gt; individually. There is no day-window rule on that category in this template, so splitting under $1,000 is &lt;strong&gt;not&lt;/strong&gt; caught until the agent's monthly budget or the company's daily ceiling is hit.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Payment to a blocked category (gift cards, cash-like)&lt;/td&gt;
&lt;td&gt;A standing rule that blocks a category outright regardless of amount or agent&lt;/td&gt;
&lt;td&gt;Requested $50 to a new payee named "Amazon Gift Cards." Decision: &lt;code&gt;blocked&lt;/code&gt;, rule &lt;code&gt;Never: gift cards, crypto, personal shopping&lt;/code&gt;, before any budget check mattered.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leaked or reused payment credential&lt;/td&gt;
&lt;td&gt;Credential is single-use, locked to one payee and amount, and expires quickly instead of behaving like a standing card&lt;/td&gt;
&lt;td&gt;Every credential issued in testing came back with &lt;code&gt;"single_use": true&lt;/code&gt;, a &lt;code&gt;max_amount&lt;/code&gt; equal to the approved amount, &lt;code&gt;"locked_to"&lt;/code&gt; the exact payee name, and an &lt;code&gt;expires_at&lt;/code&gt; 15 minutes after issue. The agent never receives a standing card number or bank login, so what it holds is scoped to one amount, one payee and a 15-minute window.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Approval nobody acts on&lt;/td&gt;
&lt;td&gt;A hold should expire rather than silently execute or sit open indefinitely&lt;/td&gt;
&lt;td&gt;Created a $450 hold that needed CFO approval and never approved it. 30 minutes later a status check returns &lt;code&gt;expired&lt;/code&gt; rather than staying &lt;code&gt;pending_human&lt;/code&gt; forever or auto-paying.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New, unverified payee&lt;/td&gt;
&lt;td&gt;A rule that always routes a payment to a never-used-before payee to a human, independent of amount&lt;/td&gt;
&lt;td&gt;Requested $300 to a payee not on the approved list ("Zendesk Inc"). Decision: &lt;code&gt;pending_human&lt;/code&gt;, rule &lt;code&gt;New payee: CFO decides&lt;/code&gt;. An admin approval returned a single-use virtual card locked to that payee for exactly $300.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two short excerpts from the raw responses, for the split-payment and blocked-category rows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Known vendors under $1,000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bank_transfer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"single_use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"locked_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-25T16:48:14.948Z"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Amazon Gift Cards"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Never: gift cards, crypto, personal shopping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"why"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"matched · block"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The split-payment test, in detail
&lt;/h2&gt;

&lt;p&gt;This is the one worth being honest about, because it is the risk most readers will actually try. I set up a workspace where an IT agent had a $1,000-per-transaction rule for its usual vendors and a $15,000 monthly budget, with roughly $8,780 of that left for the month. I then sent five payments of $999 each to the same vendor, one after another.&lt;/p&gt;

&lt;p&gt;All five were evaluated as separate transactions against a rule that allows "known vendors under $1,000." None of them individually crossed that line, so all five were allowed, for a combined $4,995 in about 12 seconds. Nothing in the rule itself tracks how many times it fired that day. Spend only stops once the agent's monthly budget or the company's shared daily ceiling would be exceeded, and in this run neither limit was close.&lt;/p&gt;

&lt;p&gt;I also checked something that looked like it should matter: the agent record carries a &lt;code&gt;single_payment_cap&lt;/code&gt; field, separate from the rule system, that you can see when you read the agent's budget. I lowered that field to $10 with an admin call and then sent the same $999 payment again. It still went through, allowed by the same $1,000 rule as before. That field is informational, shown to the agent as a reference number, and the rule engine does not read it when it decides whether to pay. The number that actually stops a payment is whatever a &lt;code&gt;tx&lt;/code&gt;, &lt;code&gt;day&lt;/code&gt;, or &lt;code&gt;month&lt;/code&gt; window rule says, not a per-agent cap field. If you are evaluating a product like this for your own company, ask specifically which field the decision logic reads, not just which fields exist in the data model.&lt;/p&gt;

&lt;p&gt;The fix for split-payment risk is not a bigger "per-payment cap" number. It is a rule with a &lt;code&gt;day&lt;/code&gt; or &lt;code&gt;month&lt;/code&gt; window on the categories where splitting would matter, so five payments to the same vendor in one day sum before the threshold is checked, not after.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for setting up your own rules
&lt;/h2&gt;

&lt;p&gt;None of the controls above are automatic just because a payments layer exists between your company and an AI agent. Each one is a rule someone wrote: block this category, ask a human when a payee is new or its bank details just changed, cap this vendor type per day. (Hold expiry is the exception: it is built in.) The sandbox ships with rules like these as defaults across three company templates (a two-location coffee shop, a 50-person software startup, and a 120-person e-commerce company), but a policy engine only enforces what it is told to check. The runaway-loop and split-payment risk above is exactly what happens when a template has a per-transaction rule but no matching per-day rule for a category.&lt;/p&gt;

&lt;p&gt;The honest summary: a single-use, payee-locked, time-limited credential closes off the leaked-credential and standing-access risks by design. A rule engine with blocked categories and new-payee holds closes off the obvious misuse cases. But window coverage (day and month, not just per-transaction) is something you have to check for each category yourself, because a missing window is invisible until someone runs exactly the test above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The tests above ran in Pink's public sandbox with test money; no real funds moved. You can spin up a sandbox company, connect an agent over MCP or REST, write your own rules, and run tests like the ones above against your own policy at &lt;a href="https://pinkwallet.com/agentic/developers/" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers&lt;/a&gt;. In production, Pink runs as a decision layer: your agent asks Pink first, and your own Stripe, card or bank pays only if Pink allows it. Pink never holds or moves your money. A pilot on your own production tenant is $99/month: &lt;a href="https://pinkwallet.com/agentic/pilot/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=p21-agent-payment-risks" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/pilot&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>agents</category>
      <category>fintech</category>
    </item>
    <item>
      <title>How Do I Give an AI Agent Its Own Wallet and Spending Limits?</title>
      <dc:creator>Quinn</dc:creator>
      <pubDate>Wed, 28 Oct 2026 14:00:24 +0000</pubDate>
      <link>https://dev.to/quinn_854b15f517d8632ed4f/how-do-i-give-an-ai-agent-its-own-wallet-and-spending-limits-3d7g</link>
      <guid>https://dev.to/quinn_854b15f517d8632ed4f/how-do-i-give-an-ai-agent-its-own-wallet-and-spending-limits-3d7g</guid>
      <description>&lt;h1&gt;
  
  
  How Do I Give an AI Agent Its Own Wallet and Spending Limits?
&lt;/h1&gt;

&lt;p&gt;We set one AI agent's monthly budget to $19,000, watched it spend $1,050 in two approved payments, then watched the next two payments get blocked for the same reason, "$18,890 used of $19,000, this would exceed it," with the real numbers to prove it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I work on Pink Agentic AI Payments at PinkWallet. This post was written with AI and checked against the product source.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; don't give the agent a wallet, give it a spending identity. A funded wallet or a private key is something an agent holds and can use anytime, for anything, until someone notices. A budget is something the agent asks against every time, that a server checks before money moves. Pink Agentic AI Payments gives each AI agent its own budget and checks every payment against company rules on the server, before it executes, so the limit lives outside the agent, not inside a key it's holding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wallet vs spending identity
&lt;/h2&gt;

&lt;p&gt;A wallet is bearer access, if the agent has the private key or the card number, it can spend, and the only backstop is whatever the agent's own code decides to do. A spending identity flips that: the agent gets an account on the payment server, that account has a monthly budget and its own rules, and the agent never receives anything it can spend until a specific request clears those checks. Ask the server "can I pay $150," and if yes, you get one single-use, payee-locked credential, good for that payment, expiring in 15 minutes. There's no standing balance an agent can quietly drain over a weekend, because there's nothing sitting in its hands to drain.&lt;/p&gt;

&lt;p&gt;We ran this with a real agent, "Eng Infra AI," for a fictional company, Calder Robotics, buying API credits and cloud capacity.&lt;/p&gt;

&lt;h2&gt;
  
  
  The budget object, before and after
&lt;/h2&gt;

&lt;p&gt;A fresh &lt;code&gt;pink.get_budget&lt;/code&gt; call for this agent, before we touched anything, returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Eng Infra AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"monthly_budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"spent_this_month"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17840&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"left_this_month"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"single_payment_cap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"company_daily_ceiling"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the budget in one object: a monthly ceiling and how much of it is already spent. We tightened it with one call to &lt;code&gt;PATCH /v1/admin/agents/a_eng&lt;/code&gt;, setting &lt;code&gt;monthly&lt;/code&gt; to 19000 (we also set &lt;code&gt;perPay&lt;/code&gt; to 500; more on that below). That endpoint is the only way to change the budget, there's no separate "wallet balance" to top up or drain, the budget itself is the only thing that moves. The agent record after the patch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a_eng"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"monthly"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;19000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"perPay"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"spentMonth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17840&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;$17,840 was already spent against the old $25,000 ceiling, so tightening the monthly number to $19,000 left only $1,160 of headroom for the rest of the month, something we confirmed before making any payment, not after.&lt;/p&gt;

&lt;h2&gt;
  
  
  A day window doing its job
&lt;/h2&gt;

&lt;p&gt;The company also had a rule scoped just to this agent, visible through &lt;code&gt;pink.list_rules&lt;/code&gt;, capping API-category purchases at $200 a day: "API credits: $200 a day per agent, then stop." We sent $150 to OpenAI for eval pipeline testing, and it cleared:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"OpenAI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"API credits: $200 a day per agent, then stop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"locked_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"OpenAI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"single_use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A second request for $100 to Anthropic pushed the day's API spend to $250, over the $200 window, and the server blocked it before it got anywhere near a payment rail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Anthropic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"API credits over $200 a day: blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"why"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"matched · block"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a day-window rule doing exactly what it's for, a ceiling that resets daily and exists independent of the monthly budget. A $900 AWS invoice went through separately under a different rule for cloud invoices that match a billing statement, bringing the day's total spend to $1,050.&lt;/p&gt;

&lt;p&gt;Note that the $900 cleared even though we had set &lt;code&gt;perPay&lt;/code&gt; to 500. In the current sandbox, &lt;code&gt;perPay&lt;/code&gt; is shown to the agent as &lt;code&gt;single_payment_cap&lt;/code&gt; but the engine doesn't enforce that field on its own. A hard per-payment limit is an amount rule with window &lt;code&gt;tx&lt;/code&gt;, scoped to the agent. We'd rather show you that than hide it.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the monthly budget runs out, everything stops, regardless of size
&lt;/h2&gt;

&lt;p&gt;With $18,890 of the $19,000 monthly budget used, we sent two more requests: a $200 AWS line item, and a $1,500 laptop purchase from Dell for a new engineer. Both came back blocked, with identical reasoning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Amazon Web Services"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Eng Infra AI's monthly budget is used up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"why"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$18,890 used of $19,000 · this would exceed it"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Eng Infra AI's monthly budget is used up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"why"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$18,890 used of $19,000 · this would exceed it"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the Dell laptop would otherwise have qualified for a different rule entirely, a mid-size purchase that normally routes to the CFO for a yes or no. It never got that far, the monthly ceiling for this specific agent is checked ahead of that, and once it's exhausted, nothing clears for this agent until the next billing cycle or a human raises the number. The final &lt;code&gt;get_budget&lt;/code&gt; call for the day confirmed it: &lt;code&gt;"left_this_month": 110&lt;/code&gt;, &lt;code&gt;"spent_today": 1050&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where human approval fits, briefly
&lt;/h2&gt;

&lt;p&gt;Some requests in this same rule set don't resolve to allow or block at all, they come back &lt;code&gt;pending_human&lt;/code&gt; and sit with a named approver until someone acts. That's a separate layer from the budget, approval bands decide who signs off on a given amount; the budget decides whether the agent gets to ask in the first place. This post is about the budget, not the approval chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual contrast
&lt;/h2&gt;

&lt;p&gt;Compare this to handing an agent a raw card number or a wallet's private key. There, the limit exists only if the agent's own code enforces it, and a bug, a prompt injection, or a bad tool call bypasses it instantly because the agent is the thing holding the money. Here, the agent asked for $1,500 and the server said no on its own, the agent's code didn't have to get that check right, because it never had the option to skip it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Spin up a free sandbox workspace with test money, no signup required: &lt;code&gt;POST https://agentic-sandbox.pinkwallet.com/v1/sandbox/workspaces?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=agent-wallet-spending-limits&lt;/code&gt;. Full docs at &lt;a href="https://pinkwallet.com/agentic/developers/" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers&lt;/a&gt;. The same kind of rules (budgets, amount and payee rules, approval chains) also run in production as a decision layer: your agent asks Pink first, and your own Stripe, card or bank pays only if Pink allows it. Pink never holds or moves your money. A pilot on your own production tenant is $99/month: &lt;a href="https://pinkwallet.com/agentic/pilot/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=agent-wallet-spending-limits" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/pilot&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>fintech</category>
      <category>api</category>
      <category>ai</category>
    </item>
    <item>
      <title>Is There an MCP Server That Lets Claude or ChatGPT Send Money or Pay for Things?</title>
      <dc:creator>Quinn</dc:creator>
      <pubDate>Tue, 27 Oct 2026 14:00:37 +0000</pubDate>
      <link>https://dev.to/quinn_854b15f517d8632ed4f/is-there-an-mcp-server-that-lets-claude-or-chatgpt-send-money-or-pay-for-things-4pjp</link>
      <guid>https://dev.to/quinn_854b15f517d8632ed4f/is-there-an-mcp-server-that-lets-claude-or-chatgpt-send-money-or-pay-for-things-4pjp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update, 2026-10-28:&lt;/strong&gt; Pink Agentic AI Payments is now live in production as a decision layer: your agent asks Pink before each payment, and your own Stripe, card or bank pays only if Pink allows it. Pink never holds or moves your money. Anything below that says early access or test money describes the free public sandbox, which still runs on test money. Production pilot on your own tenant: $99/month, &lt;a href="https://pinkwallet.com/agentic/pilot/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=update-1028&amp;amp;utm_content=4912353" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/pilot&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Is There an MCP Server That Lets Claude or ChatGPT Send Money or Pay for Things?
&lt;/h1&gt;

&lt;p&gt;We opened an MCP session against a live payments sandbox, sent the same &lt;code&gt;request_payment&lt;/code&gt; tool calls Claude or ChatGPT would send for three test invoices, and got three different outcomes back: one approved with a single-use card, one parked for a human to approve, and one rejected outright, all before any money moved.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I work on Pink Agentic AI Payments at PinkWallet. This post was written with AI and checked against the product source.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; yes, there is an MCP server built specifically for this: it exposes payment tools to any MCP client, but every call still passes through a server-side rule engine before anything is charged. Pink Agentic AI Payments gives each AI agent its own budget and checks every payment against company rules on the server, before it executes. The model never sees a card number, a bank login, or a private key, it only sees a decision: allowed, pending on a human, or blocked.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the server actually hands the model
&lt;/h2&gt;

&lt;p&gt;We spun up a free sandbox workspace for a fictional company, Lantern &amp;amp; Oak Coffee, and connected to its MCP server at &lt;code&gt;https://agentic-sandbox.pinkwallet.com/mcp&lt;/code&gt; using an agent key called "Purchasing AI." The first call in any MCP session is &lt;code&gt;initialize&lt;/code&gt;, and the server's own instructions field tells the model exactly what it can and can't do:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"You never hold money, a standing card or the company's account keys: each allowed or approved payment returns one single-use credential locked to that payee and amount, expiring in 15 minutes."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the whole design in one sentence. The model is never handed standing payment access, it's handed a yes/no/ask-a-human decision, and only on "yes" does it get something it can actually spend, and that something expires in 15 minutes and only works at one payee.&lt;/p&gt;

&lt;p&gt;Calling &lt;code&gt;tools/list&lt;/code&gt; on the same connection returns seven tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pink.get_budget&lt;/code&gt;, how much is left this month, the vault balance and the company-wide daily ceiling&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pink.list_payees&lt;/code&gt;, the suppliers and vendors this company has approved&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pink.list_rules&lt;/code&gt;, the policy rules that apply to this agent, in the order they're checked&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pink.check_policy&lt;/code&gt;, a dry run: would this payment be allowed, asked, or blocked, with no money moved&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pink.request_payment&lt;/code&gt;, the real call, returns allowed, pending_human, or blocked&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pink.get_credential&lt;/code&gt;, poll a pending hold until a person decides&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pink.report_receipt&lt;/code&gt;, file the receipt after paying so the payment reconciles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No tool returns a reusable card, account number, or standing token at any point. The only thing that can move money is &lt;code&gt;request_payment&lt;/code&gt;, and it only ever hands back something single-use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting a real MCP client
&lt;/h2&gt;

&lt;p&gt;The connection guide at &lt;a href="https://pinkwallet.com/agentic/developers/" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers&lt;/a&gt; documents the server URL as &lt;code&gt;https://agentic-sandbox.pinkwallet.com/mcp&lt;/code&gt;, with the agent key sent either as &lt;code&gt;Authorization: Bearer &amp;lt;agent_key&amp;gt;&lt;/code&gt; or embedded directly in the path as &lt;code&gt;.../mcp/&amp;lt;agent_key&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For Claude Code, the docs give this exact command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--scope&lt;/span&gt; project &lt;span class="nt"&gt;--transport&lt;/span&gt; http pink &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/mcp/&amp;lt;agent_key&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Claude Desktop and ChatGPT, the docs describe the GUI path rather than a config file: in Claude Desktop, Settings → Connectors → Add custom connector, then paste the same URL. In ChatGPT, Settings → Connectors → Create, paste the same URL, available on Plus, Pro, Business, and Enterprise plans with Developer mode turned on. The docs list 14 documented clients in total, including Claude Code, Claude.ai/Desktop, the Anthropic and OpenAI APIs, ChatGPT, Gemini CLI, Cursor, Windsurf, VS Code, Copilot Studio, LangChain, CrewAI, n8n, and "any MCP SDK." If a client isn't in that list, we're not claiming it works, remote MCP support varies enough between clients that it's worth checking the docs directly before assuming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three requests, three outcomes
&lt;/h2&gt;

&lt;p&gt;With the Purchasing AI agent connected, we called &lt;code&gt;pink.request_payment&lt;/code&gt; three times through the actual MCP &lt;code&gt;tools/call&lt;/code&gt; interface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;$300 to Sysco, for a weekly milk and syrup restock, came back allowed:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sysco"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Small supply orders go through"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtual_card"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"locked_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sysco"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"single_use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-24T16:53:59.971Z"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That credential only authorizes $300 at Sysco and stops working in 15 minutes. The rule that let it through, "Small supply orders go through," caps anything on an approved payee at $500 per transaction for this agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;$700 to Uline, for a bulk cup and lid order, came back pending_human:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending_human"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Uline"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bigger supply orders: store manager checks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hold_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_f0bbaf5ef3fc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"who"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Luis Ortega (Store manager)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-24T17:09:00.224Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No credential, no card, nothing to spend. $500 to $2,000 on this account routes to a named human, Luis Ortega, the store manager. The agent's only move here is to call &lt;code&gt;pink.get_credential&lt;/code&gt; with the &lt;code&gt;hold_id&lt;/code&gt; and poll. We did, and before Luis acted, the poll returned the same &lt;code&gt;pending_human&lt;/code&gt; state, the credential only appears in that response once a person actually approves it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;$50 to giftcards.com came back blocked, flat out, no polling possible:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"giftcards.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Never: gift cards, cash-like, crypto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one isn't a budget or approval question, it's a category block that applies to every agent on the account, no matter the amount. &lt;code&gt;pink.list_rules&lt;/code&gt; shows it sitting first in the evaluation order, ahead of any dollar-amount rule, which matches how the engine works: the first matching rule wins, and a flat "never" rule for a payee category beats a dollar-threshold rule every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the model never touches the money
&lt;/h2&gt;

&lt;p&gt;Across all three calls, the model's job was identical: describe the payment, call &lt;code&gt;request_payment&lt;/code&gt;, read the decision. It never constructed a card number, never held a reusable credential, and never had standing access to pay anyone twice. The 15-minute expiry on the one approved credential means even if that JSON leaked somewhere downstream, it would already be dead by the time anyone could misuse it.&lt;/p&gt;

&lt;p&gt;That's the actual answer to "can an MCP server let an AI send money": yes, but the interesting engineering isn't the MCP transport, plenty of servers can expose a &lt;code&gt;pay()&lt;/code&gt; tool. The interesting part is what happens between the tool call and the money moving, a rule check that runs on every single request, decides allow, ask, or block, and only ever issues something single-use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The sandbox above is free, uses test money only, and needs no signup: &lt;code&gt;POST https://agentic-sandbox.pinkwallet.com/v1/sandbox/workspaces?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=mcp-server-send-money&lt;/code&gt; spins up a new company with its own agents, rules, and payees in one call. Full docs: &lt;a href="https://pinkwallet.com/agentic/developers/" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers&lt;/a&gt;. Production access is early access only right now, reach out through the docs site if you want in.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>agents</category>
      <category>api</category>
    </item>
    <item>
      <title>What's the Best Way to Give AI Agents Controlled Spending Authority?</title>
      <dc:creator>Quinn</dc:creator>
      <pubDate>Sun, 25 Oct 2026 14:00:43 +0000</pubDate>
      <link>https://dev.to/quinn_854b15f517d8632ed4f/whats-the-best-way-to-give-ai-agents-controlled-spending-authority-5fgo</link>
      <guid>https://dev.to/quinn_854b15f517d8632ed4f/whats-the-best-way-to-give-ai-agents-controlled-spending-authority-5fgo</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update, 2026-10-28:&lt;/strong&gt; Pink Agentic AI Payments is now live in production as a decision layer: your agent asks Pink before each payment, and your own Stripe, card or bank pays only if Pink allows it. Pink never holds or moves your money. Anything below that says early access or test money describes the free public sandbox, which still runs on test money. Production pilot on your own tenant: $99/month, &lt;a href="https://pinkwallet.com/agentic/pilot/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=update-1028&amp;amp;utm_content=4883249" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/pilot&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A Marketing AI agent's second ad purchase of the day, $150, landed as &lt;code&gt;pending_human&lt;/code&gt; in front of the store owner about one second after its first $220 ad purchase cleared automatically. Same agent, same API key, same rule, the only difference was that the two spends together crossed a $300-a-day line.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I work on Pink Agentic AI Payments at PinkWallet.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; give each AI agent the same kind of layered spending authority you'd give an employee with a corporate card: a monthly budget, a per-payment cap, a daily window that catches cumulative drift, an approval band for anything bigger, and a hard block on categories that should never be self-service. Pink Agentic AI Payments checks every one of those limits on the server, before a payment executes, so the limits hold even if the agent's own context has no memory of what it already spent today. Here's that model, run live against a sandbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  Borrow the model you already trust: employee spend authority
&lt;/h2&gt;

&lt;p&gt;Companies don't give employees unlimited corporate cards, and they don't rely on employees self-reporting their own spending either. They give a card with a limit, a manager who sees the statement, and a policy for what's never reimbursable. The same five levers work for an AI agent, and they map directly onto this rule engine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Per-agent budget&lt;/strong&gt;: a hard monthly ceiling, like a department budget.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-payment cap&lt;/strong&gt;: no single transaction above X, regardless of what's left in the month. In Pink this is an amount rule with window &lt;code&gt;tx&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily window&lt;/strong&gt;: catches an agent that stays under its per-payment cap but fires off many small payments in one day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approval band&lt;/strong&gt;: amounts above a threshold route to a named human instead of executing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blocked categories&lt;/strong&gt;: gift cards, crypto, personal purchases, never allowed, no approval path, no exceptions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: a workspace with that authority already assigned per agent
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/sandbox/workspaces?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ai-agent-spending-authority"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"company":"Bramble &amp;amp; Finch Roasters","email":"dev@brambleandfinch.example","template":"coffee"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trimmed real response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workspace_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"9vmbv7tb8n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bramble &amp;amp; Finch Roasters"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"template"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"coffee"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"agents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a_purch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Purchasing AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"monthly_budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"per_payment_cap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a_inv"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Inventory AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"monthly_budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"per_payment_cap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a_mkt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Marketing AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"monthly_budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"per_payment_cap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a_pay"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Payroll &amp;amp; Bills AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"monthly_budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"per_payment_cap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four agents, four different budgets and caps, sized for what each one actually does. Payroll's agent can move far more per payment than marketing's, because its job is to pay a fixed vendor on schedule, not to improvise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: set the budget and cap for one agent explicitly
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; PATCH &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/admin/agents/a_mkt"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ADMIN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"monthly":3500,"perPay":300}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a_mkt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Marketing AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"dept"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Marketing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"monthly"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"perPay"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"spentMonth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2060&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"spentToday"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;monthly&lt;/code&gt; and &lt;code&gt;perPay&lt;/code&gt; are the only two fields this PATCH call takes. &lt;code&gt;monthly&lt;/code&gt; is checked before every payment. &lt;code&gt;perPay&lt;/code&gt; is shown to the agent as &lt;code&gt;single_payment_cap&lt;/code&gt;, but in the current sandbox the engine doesn't enforce that field on its own, so a hard per-payment limit is an amount rule with window &lt;code&gt;tx&lt;/code&gt;. There's no hourly budget in this engine, only transaction, daily, and monthly windows, and the daily one is where most real drift gets caught.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: the daily window is what catches cumulative drift, not just one big payment
&lt;/h2&gt;

&lt;p&gt;The rule table for this agent has a matched pair:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rule&lt;/th&gt;
&lt;th&gt;Payee&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;th&gt;Window&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ads up to $300 a day&lt;/td&gt;
&lt;td&gt;cat:ads&lt;/td&gt;
&lt;td&gt;$0–$300&lt;/td&gt;
&lt;td&gt;&lt;code&gt;day&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;allow&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ads above $300 a day: ask the owner&lt;/td&gt;
&lt;td&gt;cat:ads&lt;/td&gt;
&lt;td&gt;$300+&lt;/td&gt;
&lt;td&gt;&lt;code&gt;day&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ask&lt;/code&gt; → Maya Chen (Owner)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Neither rule looks at a single payment in isolation. The day window is the agent's total spend for the day across all its payments, including this one, compared against the line. The payee scope (&lt;code&gt;cat:ads&lt;/code&gt;) decides whether the rule applies at all; it doesn't narrow the running total to ads only.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First ad spend, well under the line:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$MKT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_id":"p_meta","amount":220,"purpose":"Instagram ad boost, morning promo"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ads up to $300 a day"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"locked_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Meta Ads"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Second ad spend, same day, same agent, same rule pair:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$MKT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_id":"p_meta","amount":150,"purpose":"Instagram ad boost, afternoon top-up"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending_human"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ads above $300 a day: ask the owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hold_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_50bbb7ea049b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"who"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Maya Chen (Owner)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"approvers_needed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-20T12:59:25.026Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;$220 plus $150 is $370, over the $300 line, so the second request held instead of executing. The agent never had to track its own running total. One nuance worth knowing: after this hold, the agent's &lt;code&gt;spentToday&lt;/code&gt; field still read $220, not $370, because a &lt;code&gt;pending_human&lt;/code&gt; payment hasn't actually moved money yet. It only counts toward the window once it's approved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: a human approves, with the admin key, not the agent's own key
&lt;/h2&gt;

&lt;p&gt;Approving a hold is a real admin-key call: &lt;code&gt;POST /v1/admin/requests/{hold_id}/approve&lt;/code&gt; with &lt;code&gt;{"by": "&amp;lt;approver name&amp;gt;"}&lt;/code&gt;. This step reproduces the $220 allowed / $150 pending_human pair in a fresh coffee-template workspace (company "Thistle &amp;amp; Oak Roasters," &lt;code&gt;workspace_id t91ic75cpd&lt;/code&gt;) to show the approval closing the loop end to end.&lt;/p&gt;

&lt;p&gt;The owner approves the held $150 with the admin key, the same key behind the approvals console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/admin/requests/pay_7b5fcf234bea/approve"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ADMIN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"by":"Maya Chen"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payment_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_7b5fcf234bea"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"approved"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ads above $300 a day: ask the owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtual_card"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"locked_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Meta Ads"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"single_use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"approved_by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Maya Chen"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent's own key can't take that same action on its own behalf. Calling the identical endpoint with the Marketing AI agent's key instead of the admin key gets rejected outright:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/admin/requests/pay_7b5fcf234bea/approve"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$MKT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"by":"Maya Chen"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"unknown route for an agent key"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After approval, the agent's own key can still read the resolved state and the now-issued credential with &lt;code&gt;GET /v1/payments/{id}&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payment_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_7b5fcf234bea"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"approved"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtual_card"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"locked_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Meta Ads"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"single_use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"approved_by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Maya Chen"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the agent's &lt;code&gt;spentToday&lt;/code&gt; only moves once the hold clears: it read $220 right after the hold was created, and $370 ($220 + the now-approved $150) once Maya Chen's approval went through. In practice, this is a human opening the approvals console at a URL shaped like &lt;code&gt;/console?key=&amp;lt;admin_key&amp;gt;&lt;/code&gt;, seeing the hold, and clicking approve. The API call above is what that click does under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: blocked categories and new payees close the rest of the loop
&lt;/h2&gt;

&lt;p&gt;Spending authority isn't just a number. Two more real calls against the same agent:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blocked, no approval path at all:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Never: gift cards, cash-like, crypto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"why"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"matched · block"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;A brand-new payee, routed to the owner regardless of amount:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending_human"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"New payee: always ask the owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"who"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Maya Chen (Owner)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"approvers_needed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A first-time vendor gets a human look once, even at $100, which is the same instinct behind requiring a second signature the first time a new supplier gets paid.&lt;/p&gt;

&lt;h2&gt;
  
  
  What each lever actually buys
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Lever&lt;/th&gt;
&lt;th&gt;What it stops&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Monthly budget&lt;/td&gt;
&lt;td&gt;The agent running up a bill no one approved for the month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-payment cap&lt;/td&gt;
&lt;td&gt;One oversized payment in a single call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daily window&lt;/td&gt;
&lt;td&gt;Many small payments that individually pass the cap but add up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Approval band&lt;/td&gt;
&lt;td&gt;Anything large enough that a human should see it before it executes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocked categories&lt;/td&gt;
&lt;td&gt;Categories with no legitimate agent use case, with no approval override&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Honest limits
&lt;/h2&gt;

&lt;p&gt;This is test money against a public sandbox. Production with real money is early access, not something generally available yet. The evaluation order checked monthly budget and a company-wide daily ceiling as hard stops ahead of the rule table itself, according to the docs; this sandbox run exercised the per-agent rule table, not the company-wide ceiling specifically.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does raising a monthly budget override the daily window?&lt;/strong&gt; No. The docs describe both as separate checks, monthly budget as a hard stop checked ahead of the rule table, the daily window as a rule within that table; raising one doesn't change the other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens if the owner never approves the hold?&lt;/strong&gt; It carries an &lt;code&gt;expires_at&lt;/code&gt;. After that, the payment is no longer actionable and the agent has to ask again if the work still needs doing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can different categories have different spending authority on the same agent?&lt;/strong&gt; Yes. The ads pair above is scoped by &lt;code&gt;payee: "cat:ads"&lt;/code&gt;, so the same agent can have a tighter window for ads than for, say, approved software subscriptions, inside one rule table.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Sandbox is free, no account required: &lt;a href="https://agentic-sandbox.pinkwallet.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ai-agent-spending-authority" rel="noopener noreferrer"&gt;agentic-sandbox.pinkwallet.com&lt;/a&gt;. Full docs: &lt;a href="https://pinkwallet.com/agentic/developers/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ai-agent-spending-authority" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers&lt;/a&gt;. Production with real money is early access only, not generally available.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>fintech</category>
      <category>security</category>
    </item>
    <item>
      <title>Is There a Policy Engine or Rules Layer for AI Agent Payments?</title>
      <dc:creator>Quinn</dc:creator>
      <pubDate>Sat, 24 Oct 2026 14:00:43 +0000</pubDate>
      <link>https://dev.to/quinn_854b15f517d8632ed4f/is-there-a-policy-engine-or-rules-layer-for-ai-agent-payments-56mc</link>
      <guid>https://dev.to/quinn_854b15f517d8632ed4f/is-there-a-policy-engine-or-rules-layer-for-ai-agent-payments-56mc</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update, 2026-10-28:&lt;/strong&gt; Pink Agentic AI Payments is now live in production as a decision layer: your agent asks Pink before each payment, and your own Stripe, card or bank pays only if Pink allows it. Pink never holds or moves your money. Anything below that says early access or test money describes the free public sandbox, which still runs on test money. Production pilot on your own tenant: $99/month, &lt;a href="https://pinkwallet.com/agentic/pilot/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=update-1028&amp;amp;utm_content=4883248" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/pilot&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A $150 gift-card purchase, a $450 hardware order, and a $2,800 laptop order hit the same AI agent's payment endpoint minutes apart today. One came back &lt;code&gt;blocked&lt;/code&gt; with no human path at all, one cleared on its own in under a second, and one sat waiting on a named CFO. Same agent, same API key, three different outcomes, decided entirely by rules the agent itself never sees or controls.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I work on Pink Agentic AI Payments at PinkWallet.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; yes, a policy engine for AI agent payments is a server-side rule table that every payment request is checked against before money moves, not a prompt the agent is asked to follow. Pink Agentic AI Payments enforces that rule evaluation on the server, before a payment executes, independent of anything the agent believes about its own limits. Below is a real rule table and real calls against a sandbox, including what happens when you edit a rule the wrong way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a rules layer between an agent and money actually has to do
&lt;/h2&gt;

&lt;p&gt;A system prompt that says "stay under budget" is advice a model reads, not a constraint it obeys. A rules layer that's actually worth calling a policy engine has to do five things a prompt can't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Evaluate before execution.&lt;/strong&gt; The check happens before a credential is issued, not as a cleanup pass after money already moved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be deterministic.&lt;/strong&gt; The same request, run twice, gets the same decision. No sampling, no "it depends on the model's mood."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resolve conflicts with a fixed order.&lt;/strong&gt; When two rules could both apply, the first match in the ordered list wins, and the rest never run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default to deny.&lt;/strong&gt; If nothing in the table matches, the payment is blocked, not allowed by omission.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Say why.&lt;/strong&gt; A human (or the agent) can see which named rule fired, not just "no."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the shape of the engine behind Pink Agentic AI Payments. Here's what it looks like with real traffic against it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: a workspace with a real rule table already in it
&lt;/h2&gt;

&lt;p&gt;No signup required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/sandbox/workspaces?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=policy-engine-rules"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"company":"Harbor Metrics","email":"dev@harbor-metrics.example","template":"startup"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trimmed real response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workspace_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8qc0ijqupz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Harbor Metrics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"template"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"startup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"policy_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"agents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a_eng"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Eng Infra AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"monthly_budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"per_payment_cap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This seeds 6 agents and 17 rules. An agent reads its own rule table with its own key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/rules"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ENG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That returns 11 rules scoped to the Eng Infra AI agent (some of the 17 only apply to other agents, like design or recruiting). A few of the ones that matter here:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rule&lt;/th&gt;
&lt;th&gt;Payee&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;th&gt;Window&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Never: gift cards, crypto, personal shopping&lt;/td&gt;
&lt;td&gt;blocked category&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;tx&lt;/td&gt;
&lt;td&gt;&lt;code&gt;block&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Known vendors under $1,000&lt;/td&gt;
&lt;td&gt;approved&lt;/td&gt;
&lt;td&gt;$0–$1,000&lt;/td&gt;
&lt;td&gt;tx&lt;/td&gt;
&lt;td&gt;&lt;code&gt;allow&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$1,000–$5,000: CFO approves&lt;/td&gt;
&lt;td&gt;approved&lt;/td&gt;
&lt;td&gt;$1,000–$5,000&lt;/td&gt;
&lt;td&gt;tx&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ask&lt;/code&gt; → Sarah Kim (CFO)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Over $5,000: 2 of 3 leadership&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;$5,000+&lt;/td&gt;
&lt;td&gt;tx&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ask&lt;/code&gt; → 2 of 3 named leaders&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duplicate invoice number within 90 days: blocked&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;tx&lt;/td&gt;
&lt;td&gt;&lt;code&gt;block&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Rules are checked in order, first match wins. The gift-card block sits ahead of everything else in this table, so a gift-card purchase never gets a chance to match a friendlier rule further down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: three requests, three outcomes, same agent
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Allowed&lt;/strong&gt; ($450 to an approved vendor, under the $1,000 line):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ENG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_id":"p_dell","amount":450,"purpose":"replacement laptop dock"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Known vendors under $1,000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"policy_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bank_transfer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;450&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"locked_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"single_use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"transfer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ACH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"reference"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PWS-1C5B8C68"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"submitted"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;pending_human&lt;/strong&gt; ($2,800, inside the $1,000–$5,000 band):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ENG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_id":"p_dell","amount":2800,"purpose":"3 replacement laptops for new hires"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending_human"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$1,000–$5,000: CFO approves"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hold_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_f858f5e00691"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"who"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sarah Kim (CFO)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"approvers_needed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-20T12:57:21.518Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;blocked, with a reason&lt;/strong&gt; (gift cards, no human path regardless of amount):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ENG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_name":"giftcards.com","amount":150,"purpose":"team swag gift cards"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Never: gift cards, crypto, personal shopping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"why"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"matched · block"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;why&lt;/code&gt; field is the audit trail. The agent (or a human reading logs later) gets a named rule, not a bare rejection. Every decision also carries a &lt;code&gt;policy_version&lt;/code&gt;, so a payment made under last week's rules stays attributable to last week's rules even after the table changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: editing a rule the right way
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;PUT /v1/admin/rules&lt;/code&gt; replaces the entire ordered list, not just the rule you're touching, so the source of truth for any edit has to be the full table, not one agent's view of it. This step uses a fresh sandbox workspace (company "Fernbank Logistics," &lt;code&gt;workspace_id y3edzx3as7&lt;/code&gt;, same &lt;code&gt;startup&lt;/code&gt; template as Step 1, so it also seeds 17 rules) to show the correct workflow end to end.&lt;/p&gt;

&lt;p&gt;First, pull the full company-wide rule table with the admin key, not the agent key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/admin/state"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ADMIN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;rules&lt;/code&gt; array in that response is the full ordered table, all 17 rules, including the ones scoped to other agents. That's different from &lt;code&gt;GET /v1/rules&lt;/code&gt; with an agent key, which only returns the subset that applies to the calling agent (11 of the 17, for Eng Infra AI), because it's a per-agent view, not the company's live policy. Starting a &lt;code&gt;PUT&lt;/code&gt; from that narrower view would silently drop every rule that applies only to other agents.&lt;/p&gt;

&lt;p&gt;With the full table in hand, I raised the ceiling on one rule, &lt;code&gt;Known vendors under $1,000&lt;/code&gt;, from &lt;code&gt;max: 1000&lt;/code&gt; to &lt;code&gt;max: 1200&lt;/code&gt;, kept the other 16 rules and the order unchanged, and PUT the whole list back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; PUT &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/admin/rules"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ADMIN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"rules": [...all 17 rules, r12 with max 1200...], "by": "dev@fernbank-logistics.example"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One schema detail that will save you a failed request: &lt;code&gt;GET /v1/admin/state&lt;/code&gt; returns each rule's limits nested under &lt;code&gt;amount&lt;/code&gt; (&lt;code&gt;{"min", "max", "window"}&lt;/code&gt;), but &lt;code&gt;PUT /v1/admin/rules&lt;/code&gt; expects &lt;code&gt;min&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt; and &lt;code&gt;window&lt;/code&gt; as top-level fields on each rule. Sending the GET shape unchanged returns &lt;code&gt;{"error": "each rule needs id, name, action, window"}&lt;/code&gt;, so flatten &lt;code&gt;amount&lt;/code&gt; before the PUT.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"policy_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Policy version ticked up to 2, and the rule count held at 17, because the edit started from the full table instead of a filtered one.&lt;/p&gt;

&lt;p&gt;The edit itself took effect immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ENG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_id":"p_dell","amount":1100,"purpose":"replacement laptops for new hires"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Known vendors under $1,000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"policy_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"locked_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"single_use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A $1,100 payment to the same vendor, which would have landed as &lt;code&gt;pending_human&lt;/code&gt; under the old $1,000 ceiling, now auto-allows under the raised one, and the response's &lt;code&gt;policy_version: 2&lt;/code&gt; ties that decision to the edited table. No redeploy, no change to the agent's prompt or code. The one rule that matters here: always build a &lt;code&gt;PUT&lt;/code&gt; from the full table &lt;code&gt;GET /v1/admin/state&lt;/code&gt; returns, never from a single agent's filtered &lt;code&gt;GET /v1/rules&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What each decision actually means
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decision&lt;/th&gt;
&lt;th&gt;Who acts&lt;/th&gt;
&lt;th&gt;What happens next&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nobody&lt;/td&gt;
&lt;td&gt;A single-use credential locked to that payee and amount is issued immediately&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pending_human&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A named approver (or N of a named group)&lt;/td&gt;
&lt;td&gt;The payment sits as a hold with an &lt;code&gt;expires_at&lt;/code&gt;; nothing moves until that person approves&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;blocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nobody; there's no approve path&lt;/td&gt;
&lt;td&gt;The agent gets &lt;code&gt;why&lt;/code&gt; naming the rule that matched, and the payment never exists&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Honest limits
&lt;/h2&gt;

&lt;p&gt;This is test money against a public sandbox, not production. Production with real money is early access, not something generally available yet. The rule engine checks amount, payee, category, and time window; it does not independently verify a self-asserted claim like a stated PO number, only whether one was attached.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can the agent talk its way past a rule?&lt;/strong&gt; No. The check runs server-side before a credential is issued; nothing the agent says in its own context changes what the server evaluates against.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens when two rules could both match?&lt;/strong&gt; The first match in the ordered list wins and nothing below it is evaluated for that request, which is why the blocked-categories rule sits at the top of this table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the engine support a dry run before actually submitting a payment?&lt;/strong&gt; The API documents a &lt;code&gt;POST /v1/payments/check&lt;/code&gt; route for exactly that; this article only exercised live &lt;code&gt;/v1/payments&lt;/code&gt; calls, so no response from that route is shown here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Sandbox is free, no account required: &lt;a href="https://agentic-sandbox.pinkwallet.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=policy-engine-rules" rel="noopener noreferrer"&gt;agentic-sandbox.pinkwallet.com&lt;/a&gt;. Full docs: &lt;a href="https://pinkwallet.com/agentic/developers/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=policy-engine-rules" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers&lt;/a&gt;. Production with real money is early access only, not generally available.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>api</category>
      <category>security</category>
    </item>
    <item>
      <title>Agentic Commerce Market Map 2026: Payments Layer Players</title>
      <dc:creator>Quinn</dc:creator>
      <pubDate>Fri, 23 Oct 2026 14:00:44 +0000</pubDate>
      <link>https://dev.to/quinn_854b15f517d8632ed4f/agentic-commerce-market-map-2026-payments-layer-players-14jn</link>
      <guid>https://dev.to/quinn_854b15f517d8632ed4f/agentic-commerce-market-map-2026-payments-layer-players-14jn</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update, 2026-10-28:&lt;/strong&gt; Pink Agentic AI Payments is now live in production as a decision layer: your agent asks Pink before each payment, and your own Stripe, card or bank pays only if Pink allows it. Pink never holds or moves your money. Anything below that says early access or test money describes the free public sandbox, which still runs on test money. Production pilot on your own tenant: $99/month, &lt;a href="https://pinkwallet.com/agentic/pilot/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=update-1028&amp;amp;utm_content=4884462" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/pilot&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Disclosure: I work on Pink Agentic AI Payments.&lt;/p&gt;

&lt;p&gt;Last checked: 2026-10-20.&lt;/p&gt;

&lt;p&gt;The payments layer of agentic commerce splits into five segments: open protocols that standardize how an agent and a merchant talk (x402, AP2, ACP, and the transport layer MCP), agent wallets and accounts that give an agent an identity and a way to hold or spend money, card and network programs that let an agent spend through existing card rails, stablecoin rails for on-chain settlement, and a spend-control (policy) layer that decides what an agent is allowed to do before any of the above executes a payment. Pink Agentic AI Payments, a new product from PinkWallet, is in that last segment.&lt;/p&gt;

&lt;p&gt;If you are an investor or researcher building a market map for agentic commerce, the segment that gets skipped most often is spend control. Protocols and wallets get the press. The layer that enforces a company's actual rules, caps, allow-lists, who has to approve what, is smaller and newer, and this post is about where it sits and who else is in it.&lt;/p&gt;

&lt;p&gt;Pink Agentic AI Payments (by PinkWallet) sits in the spend-control layer: it enforces per-agent caps, payee allow-lists and human-approval thresholds at the MCP/API layer, before a payment executes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The map
&lt;/h2&gt;

&lt;p&gt;Every player below has a public page I opened today (2026-10-20) describing what it does in its own words. No scoring, no "best," no "leader." Protocol names are neutral by nature; vendor names are listed because they publish a live product page, not because of any ranking.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Segment&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Example players&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Protocols&lt;/td&gt;
&lt;td&gt;Standardize how an agent and a merchant or server exchange payment instructions&lt;/td&gt;
&lt;td&gt;x402, AP2, ACP, MCP&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://www.x402.org/" rel="noopener noreferrer"&gt;x402.org&lt;/a&gt;, &lt;a href="https://ap2-protocol.org/" rel="noopener noreferrer"&gt;ap2-protocol.org&lt;/a&gt;, &lt;a href="https://www.agenticcommerce.dev/" rel="noopener noreferrer"&gt;agenticcommerce.dev&lt;/a&gt;, &lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;modelcontextprotocol.io&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent wallets / accounts&lt;/td&gt;
&lt;td&gt;Give an agent a verifiable identity and a wallet or account it can spend from&lt;/td&gt;
&lt;td&gt;Skyfire, Payman&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://skyfire.xyz/" rel="noopener noreferrer"&gt;skyfire.xyz&lt;/a&gt;, &lt;a href="https://www.paymanai.com/" rel="noopener noreferrer"&gt;paymanai.com&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Card / network programs&lt;/td&gt;
&lt;td&gt;Let an agent spend through an existing card network&lt;/td&gt;
&lt;td&gt;Visa Intelligent Commerce, Mastercard Agent Pay&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://www.visa.com/en-us/solutions/intelligent-commerce" rel="noopener noreferrer"&gt;visa.com&lt;/a&gt;, &lt;a href="https://thepaypers.com/payments/news/mastercard-to-launch-agentic-pay" rel="noopener noreferrer"&gt;thepaypers.com coverage of Mastercard's announcement&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stablecoin rails&lt;/td&gt;
&lt;td&gt;Provide on-chain, programmable dollar settlement an agent can move without a bank intermediary&lt;/td&gt;
&lt;td&gt;USDC (Circle)&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.circle.com/en/usdc" rel="noopener noreferrer"&gt;circle.com/en/usdc&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spend-control / policy layer&lt;/td&gt;
&lt;td&gt;Enforces what an agent is allowed to pay for: caps, allow-lists, approval thresholds, before the payment reaches a rail&lt;/td&gt;
&lt;td&gt;Pink Agentic AI Payments (by PinkWallet)&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://pinkwallet.com/agentic/" rel="noopener noreferrer"&gt;pinkwallet.com/agentic&lt;/a&gt;, &lt;a href="https://agentic-sandbox.pinkwallet.com" rel="noopener noreferrer"&gt;agentic-sandbox.pinkwallet.com&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A couple of notes on how this table was built. x402 describes itself as an open, blockchain-agnostic standard for payments made directly over HTTP 402 responses, aimed at machine and agent use. AP2, from Google, focuses on authorization and authenticity for agent-to-merchant purchases using verifiable credentials. ACP, published jointly by Stripe and OpenAI under Apache 2.0, standardizes agentic checkout flows while keeping payment credential handling with the merchant. MCP, from Anthropic, is not a payments protocol; it is the transport standard most of these tools use to connect an AI application to external systems, including payment APIs, so it belongs in the map as infrastructure rather than as a payments protocol itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pink's part of the map: the spend-control layer
&lt;/h2&gt;

&lt;p&gt;Pink Agentic AI Payments is an MCP server plus a REST API that any AI agent can call to request a payment, paired with an admin console where a company sets the rules. The rules an admin can set today, confirmed against the sandbox source code: per-agent caps per payment, per day and per month, payee allow-lists, and human-approval thresholds with a configurable approver group. The default for any payment that matches no rule is block.&lt;/p&gt;

&lt;p&gt;Here is a real call against the public sandbox, not a mockup. I created a workspace, set one rule (Marketing AI agent, any payee, allow up to 100 USD per payment), then tried a 150 USD payment against it.&lt;/p&gt;

&lt;p&gt;Request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /v1/payments
Authorization: Bearer &amp;lt;agent key&amp;gt;
{
  "payee_name": "New Ad Vendor LLC",
  "amount": 150,
  "currency": "USD",
  "purpose": "Sponsored post boost"
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payment_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_1edc7b6a4fbf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Marketing AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"New Ad Vendor LLC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"currency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"No rule allows this payment"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"why"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default is block"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An 80 USD request against the same rule came back allowed, with a single-use sandbox virtual card capped at exactly that amount, locked to that payee, expiring in 15 minutes. That is the shape of the control: the agent never holds a standing payment credential, it gets a scoped one only after a payment clears policy. You can reproduce both calls in a few minutes with a free test workspace at agentic-sandbox.pinkwallet.com, or click through the no-signup demo at agentic-sandbox.pinkwallet.com/demo.&lt;/p&gt;

&lt;p&gt;Two mechanics worth checking in any spend-control product, shown here as Pink behaves: in Pink, a day or month window on a rule counts the agent's total spend in that window, not spend broken out by merchant category, so one day-window rule caps the agent's whole day across any mix of payments. And in Pink, approving one over-threshold payment does not automatically add that payee to a permanent allow-list; the next payment to the same new payee is evaluated against the policy again.&lt;/p&gt;

&lt;p&gt;What is not yet decided and should not be assumed from this post: which settlement rail Pink runs on (stablecoin, fiat, or card), pricing, or production availability for real money. The sandbox at agentic-sandbox.pinkwallet.com runs on test funds only. Early access for companies wanting a design-partner conversation is at pinkwallet.com/agentic.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to read this map
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;For protocols, check whether the spec defines payment authorization only, or also identity and dispute handling; AP2 and ACP both lean toward identity and credential handling, x402 leans toward raw payment transport.&lt;/li&gt;
&lt;li&gt;For agent wallets, check who issues the agent's identity (the wallet vendor or the AI platform) and whether that identity is portable across merchants.&lt;/li&gt;
&lt;li&gt;For card and network programs, check whether the control point is the agent, the card network, or the issuing bank, since that determines who can set and revoke a spending limit.&lt;/li&gt;
&lt;li&gt;For the spend-control layer specifically, check whether rules are enforced before the payment reaches a rail (API-level) or only after, as a reconciliation or alert.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is this the full agentic commerce stack?&lt;/strong&gt;&lt;br&gt;
No. This post covers only the payments layer. Agent discovery, product search, and checkout UX are adjacent segments not covered here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does MCP belong next to x402, AP2 and ACP as a payment protocol?&lt;/strong&gt;&lt;br&gt;
Not really. MCP standardizes how an AI application talks to external tools and data sources. It is the channel several of these payment flows run over, which is why it is listed, but it does not define payment authorization semantics the way AP2 or ACP do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where does Pink fit if a company is already using a card network program like Visa Intelligent Commerce or Mastercard Agent Pay?&lt;/strong&gt;&lt;br&gt;
Those sit at the rail level, controlling how a card transaction clears. Pink's policy layer sits one level up, deciding whether an agent is allowed to attempt the payment at all, through whichever rail a company chooses, which is why the settlement rail question is separate from the spend-control question.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>payments</category>
      <category>fintech</category>
    </item>
    <item>
      <title>How to Let AI Agents Pay Vendors Automatically (and Safely)</title>
      <dc:creator>Quinn</dc:creator>
      <pubDate>Thu, 22 Oct 2026 14:00:44 +0000</pubDate>
      <link>https://dev.to/quinn_854b15f517d8632ed4f/how-to-let-ai-agents-pay-vendors-automatically-and-safely-41p7</link>
      <guid>https://dev.to/quinn_854b15f517d8632ed4f/how-to-let-ai-agents-pay-vendors-automatically-and-safely-41p7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update, 2026-10-28:&lt;/strong&gt; Pink Agentic AI Payments is now live in production as a decision layer: your agent asks Pink before each payment, and your own Stripe, card or bank pays only if Pink allows it. Pink never holds or moves your money. Anything below that says early access or test money describes the free public sandbox, which still runs on test money. Production pilot on your own tenant: $99/month, &lt;a href="https://pinkwallet.com/agentic/pilot/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=update-1028&amp;amp;utm_content=4881382" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/pilot&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A $1,150 customs duty payment from an AI agent cleared automatically today in under a second, while a $3,200 payment to a brand-new supplier it had never paid before sat waiting for a named human, and a $2,500 payment to a known supplier got blocked outright because it had no matching purchase order.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I work on Pink Agentic AI Payments at PinkWallet.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; build an approved-payee list, give known vendors an auto-approve band under a set amount, and route anything new or unmatched to a human instead of blind-trusting the agent. Pink Agentic AI Payments checks every payment an AI agent requests against per-agent budgets and approval rules on the server, before it executes, so the "safely" part isn't a prompt instruction, it's a server-side rule an ops team writes once. Below is a real sandbox run, with the actual responses, connected over MCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup an ops team actually wants
&lt;/h2&gt;

&lt;p&gt;"Let the agent pay vendors automatically" usually means three different things bundled together:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A list of vendors the agent is even allowed to pay (an approved-payee list, not "any bank account the agent decides to use").&lt;/li&gt;
&lt;li&gt;A ceiling under which a known, approved vendor just gets paid, no human in the loop.&lt;/li&gt;
&lt;li&gt;A trapdoor for anything that doesn't fit that shape: a brand-new vendor, an amount over the ceiling, or a payment missing the paperwork it should have.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below is a workspace built for a 120-person e-commerce company that ships all three.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: spin up a workspace with an approved-vendor list already in it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/sandbox/workspaces?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=autopay-vendors"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"company":"Driftwood Goods","email":"dev@driftwood-goods.example","template":"ecommerce"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real, trimmed response from today's run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workspace_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"zus8sjzdue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Driftwood Goods"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"template"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ecommerce"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"agents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a_proc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Procurement AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"monthly_budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;400000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"per_payment_cap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a_fin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Finance Ops AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"monthly_budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"per_payment_cap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payees"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"p_foshan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"p_yiwu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"p_hk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"p_dhl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"p_ups"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"p_duty"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"p_klaviyo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;19 payees ship pre-approved, each with a category (&lt;code&gt;supplier&lt;/code&gt;, &lt;code&gt;logistics&lt;/code&gt;, &lt;code&gt;duty&lt;/code&gt;, &lt;code&gt;saas&lt;/code&gt;, and so on), and some already carry a risk flag. One supplier in this template, Foshan Ceramics Co., ships with &lt;code&gt;"risk_flags": ["payeeChanged"]&lt;/code&gt; because its bank details changed 3 days ago, which on its own routes any payment to that payee to a human rather than letting the amount decide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: the auto-approve band for a known, small payment
&lt;/h2&gt;

&lt;p&gt;Not every rule in this template needs a human. Customs duties under $3,000 to the approved duty payee clear on their own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$FIN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_id":"p_duty","amount":1150,"purpose":"import duty, October container"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Customs duties and taxes up to $3,000: automatic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bank_transfer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"locked_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DHL Duties &amp;amp; Taxes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"single_use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"transfer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ACH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"reference"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PWS-6E770BCF"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"submitted"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;credential&lt;/code&gt; is single-use and locked to this exact payee and amount; it's issued only after the rule matched, and it can't be reused for a different payee or a larger amount.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: a hold for a vendor the agent has never paid before
&lt;/h2&gt;

&lt;p&gt;The same workspace's Procurement AI agent has its own rule for anything new:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$PROC&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_name":"Guangzhou Zipper Factory","amount":3200,"purpose":"first order, new zipper supplier"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending_human"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"New supplier: first payment up to $5,000, CFO approves"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hold_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_0c1906fcba25"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"who"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wei Lim (CFO)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"approvers_needed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-20T06:06:39.691Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A vendor that isn't on the approved list yet, even for a first order under the normal CFO band, waits for a named person. Approving that first payment doesn't add the vendor to the approved list by itself: the approved-payee list is something the company maintains, and only payees on it can match the auto-approve bands for known vendors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: a block for a known vendor missing its paperwork
&lt;/h2&gt;

&lt;p&gt;The same Procurement AI agent also carries a rule that any payment to an approved supplier without a matching purchase order gets blocked outright, not held, not asked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$PROC&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_id":"p_yiwu","amount":2500,"purpose":"rush order, PO not issued yet"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Supplier payment without a matching PO: blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"why"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"matched · block"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a good one to test against your own setup before you trust an auto-approve band blindly: in this template, that rule is checked ahead of the small-reorder auto-approve rule for this agent, so a known vendor with a missing PO gets blocked rather than quietly clearing under the small-amount band. Rule order matters as much as the rule itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: connect the agent over MCP or REST
&lt;/h2&gt;

&lt;p&gt;MCP, no OAuth flow needed in the sandbox:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pink"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pink-agentic-payments-mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"PINK_AGENT_KEY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pk_sandbox_agent_&amp;lt;your_key&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or call the REST API directly, which is what every example above does. Python and n8n integrations exist too (&lt;code&gt;pip install langchain-pink&lt;/code&gt;, and an n8n node), for teams that would rather wire this into an existing agent framework than write raw HTTP calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to decide before turning this on
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decision&lt;/th&gt;
&lt;th&gt;Where it lives&lt;/th&gt;
&lt;th&gt;What happens if you skip it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Which vendors the agent can pay at all&lt;/td&gt;
&lt;td&gt;The approved-payee list&lt;/td&gt;
&lt;td&gt;Any payee name the agent sends gets treated as new, routing almost everything to a human&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The ceiling for auto-approve on known vendors&lt;/td&gt;
&lt;td&gt;A rule with an &lt;code&gt;amount.max&lt;/code&gt; and &lt;code&gt;action: allow&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Every payment, even a $20 recurring charge, needs a human&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What counts as "new" or "risky" enough to hold&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;payee: "new"&lt;/code&gt; rules, and risk flags like a recently changed bank detail&lt;/td&gt;
&lt;td&gt;A compromised or swapped payee account gets paid without anyone noticing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What paperwork a payment needs before it clears&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;requires&lt;/code&gt; fields like a purchase order match&lt;/td&gt;
&lt;td&gt;An agent can pay an approved vendor for something nobody ordered&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Honest limits of this sandbox
&lt;/h2&gt;

&lt;p&gt;This is test money against a sandbox at &lt;code&gt;agentic-sandbox.pinkwallet.com&lt;/code&gt;, not production; production with real money is early access right now. The engine checks the conditions you write into a rule, like amount, payee, category, and whether a flag like a purchase order was attached; it does not independently verify that a stated PO number is real, only that one was or wasn't provided. And because rules are evaluated in order, first match wins, a broad rule placed above a narrower one will shadow it, which is exactly what happened with the blocked payment above.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can the agent still pay a vendor that's not on the approved list?&lt;/strong&gt; Not without a rule for it. A payment to an unlisted payee name matches a &lt;code&gt;payee: "new"&lt;/code&gt; rule if one exists; without one, the request has no rule to route through.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does the agent get back when a payment is held, not blocked?&lt;/strong&gt; A &lt;code&gt;hold_id&lt;/code&gt;, the named approver (or group), and an &lt;code&gt;expires_at&lt;/code&gt;. The agent can poll for the outcome; the credential only exists after a human approves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does connecting over MCP change which rules apply?&lt;/strong&gt; No. MCP and REST hit the same server-side rule engine; the transport changes, the check doesn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Sandbox is free, no account required: &lt;a href="https://agentic-sandbox.pinkwallet.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=autopay-vendors" rel="noopener noreferrer"&gt;agentic-sandbox.pinkwallet.com&lt;/a&gt;. Full API and rules reference: &lt;a href="https://pinkwallet.com/agentic/developers/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=autopay-vendors" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers&lt;/a&gt;. Security model: &lt;a href="https://pinkwallet.com/agentic/developers/security-model/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=autopay-vendors" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers/security-model&lt;/a&gt;. Production with real money is early access: &lt;a href="https://pinkwallet.com/agentic/#early-access?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=autopay-vendors" rel="noopener noreferrer"&gt;join the waitlist&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>mcp</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How Can a Finance Team Cap and Approve What AI Agents Spend?</title>
      <dc:creator>Quinn</dc:creator>
      <pubDate>Wed, 21 Oct 2026 14:03:33 +0000</pubDate>
      <link>https://dev.to/quinn_854b15f517d8632ed4f/how-can-a-finance-team-cap-and-approve-what-ai-agents-spend-3jg9</link>
      <guid>https://dev.to/quinn_854b15f517d8632ed4f/how-can-a-finance-team-cap-and-approve-what-ai-agents-spend-3jg9</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update, 2026-10-28:&lt;/strong&gt; Pink Agentic AI Payments is now live in production as a decision layer: your agent asks Pink before each payment, and your own Stripe, card or bank pays only if Pink allows it. Pink never holds or moves your money. Anything below that says early access or test money describes the free public sandbox, which still runs on test money. Production pilot on your own tenant: $99/month, &lt;a href="https://pinkwallet.com/agentic/pilot/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=update-1028&amp;amp;utm_content=4881379" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/pilot&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A $7,500 server hardware order from an AI agent sat as &lt;code&gt;pending_human&lt;/code&gt; today, routed to two named executives before any money could move, while a $450 order from the same agent cleared on its own in under a second.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I work on Pink Agentic AI Payments at PinkWallet.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; give each AI agent a monthly budget and a per-payment cap, then layer amount bands on top that route to a specific named human instead of executing. Pink Agentic AI Payments checks every payment an AI agent requests against per-agent budgets and approval rules on the server, before it executes, and a finance team edits those rules from a console without touching the agent's code. Below is a real run against a sandbox workspace, with the actual responses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "ask the agent nicely" doesn't satisfy a controller
&lt;/h2&gt;

&lt;p&gt;A system prompt that says "stay under $5,000 a month" is advice the model reads, not a constraint it obeys. Nothing stops a long conversation, a bad retry loop, or a crafted tool response from drifting past it, and the agent's own context window has no memory of what finance actually approved. A finance team needs the check to live somewhere the agent cannot talk its way around: on the server, evaluated before the payment executes, independent of whatever the agent currently believes its budget is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: spin up a workspace with real rules already in it
&lt;/h2&gt;

&lt;p&gt;No signup required to test this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/sandbox/workspaces?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=finance-cap-approve"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"company":"Nimbus Analytics","email":"dev@nimbus-analytics.example","template":"startup"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This template seeds a 50-person software company with 6 agents and 17 rules. Trimmed real response from today's run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workspace_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1iwi11zcgy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nimbus Analytics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"template"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"startup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"agents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a_eng"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Eng Infra AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"monthly_budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"per_payment_cap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A finance team gets a console link in the same response (&lt;code&gt;urls.console&lt;/code&gt;) where a person can review and edit the rule set without redeploying the agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: set the monthly budget and per-payment cap
&lt;/h2&gt;

&lt;p&gt;One &lt;code&gt;PATCH&lt;/code&gt; call on the admin route changes both numbers for a single agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; PATCH &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/admin/agents/a_eng"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ADMIN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"monthly":30000,"perPay":1500}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a_eng"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Eng Infra AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"dept"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Engineering"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"monthly"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"perPay"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"spentMonth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17840&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"trust"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;monthly&lt;/code&gt; is this agent's hard ceiling for the current month. &lt;code&gt;perPay&lt;/code&gt; caps any single payment regardless of what's left in the month. Both are checked before a payment is created. The spending windows in this engine are per-transaction, daily, and monthly only, which keeps the rule set small enough for a controller to actually read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: amount bands route to a named human, not a queue
&lt;/h2&gt;

&lt;p&gt;The template's rule set has three bands stacked on top of each other for this agent, first match wins:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Under $1,000&lt;/strong&gt;, an approved payee: &lt;code&gt;allow&lt;/code&gt; automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$1,000 to $5,000&lt;/strong&gt;, an approved payee: &lt;code&gt;ask&lt;/code&gt;, routed to "Sarah Kim (CFO)" by name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over $5,000&lt;/strong&gt;, any payee: &lt;code&gt;ask&lt;/code&gt;, routed to "2 of 3 in Leadership (Daniel Park, Sarah Kim, Omar Haddad)", meaning two of those three specific people have to sign off, not just one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gift cards, crypto, and personal shopping are a separate &lt;code&gt;block&lt;/code&gt; rule with no human path at all, evaluated ahead of the amount bands so a gift-card purchase never lands in anyone's queue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: four payments, four outcomes, run today
&lt;/h2&gt;

&lt;p&gt;Same agent, same rule set, different amounts and payees against the sandbox at &lt;code&gt;agentic-sandbox.pinkwallet.com&lt;/code&gt;. Real, trimmed responses:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Allowed&lt;/strong&gt; ($450, hardware accessory, under the $1,000 band):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ENG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_id":"p_dell","amount":450,"purpose":"replacement laptop dock + accessories"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Known vendors under $1,000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bank_transfer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"max_amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;450&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"locked_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"single_use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"transfer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ACH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"reference"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PWS-39C7198F"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"submitted"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;pending_human, CFO tier&lt;/strong&gt; ($2,800, inside the $1,000-$5,000 band):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ENG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_id":"p_dell","amount":2800,"purpose":"3 replacement laptops for new hires"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending_human"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$1,000-$5,000: CFO approves"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hold_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_f6c2b2fbe109"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"who"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sarah Kim (CFO)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"approvers_needed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-20T06:06:11.468Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;pending_human, leadership tier&lt;/strong&gt; ($7,500, over the $5,000 line):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ENG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_id":"p_dell","amount":7500,"purpose":"server rack hardware refresh, 3 units"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending_human"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Over $5,000: 2 of 3 leadership"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hold_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_3897fab2bb11"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"who"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2 of 3 in Leadership (Daniel Park, Sarah Kim, Omar Haddad)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"approvers_needed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Blocked&lt;/strong&gt; (gift cards, any amount, no human path):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://agentic-sandbox.pinkwallet.com/v1/payments"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ENG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"payee_name":"giftcards.com","amount":150,"purpose":"team swag gift cards"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Never: gift cards, crypto, personal shopping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"credential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"why"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"matched · block"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the field is &lt;code&gt;why&lt;/code&gt; on a block, not &lt;code&gt;reason&lt;/code&gt;. The two &lt;code&gt;pending_human&lt;/code&gt; payments don't move money; a named person has to open the console and approve the hold before a credential is ever issued.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a finance team actually sees
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decision&lt;/th&gt;
&lt;th&gt;Who acts&lt;/th&gt;
&lt;th&gt;What happens next&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nobody&lt;/td&gt;
&lt;td&gt;A single-use credential is issued, locked to that payee and amount, and the agent completes the payment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pending_human&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A named approver (or N of a named group)&lt;/td&gt;
&lt;td&gt;The payment sits as a hold with an &lt;code&gt;expires_at&lt;/code&gt;; nothing moves until that person approves in the console&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;blocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nobody; there's no approve path&lt;/td&gt;
&lt;td&gt;The agent gets &lt;code&gt;why: "matched · block"&lt;/code&gt; and the payment never exists&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every one of these decisions, plus who the approver was and when they acted, is tied to a &lt;code&gt;payment_id&lt;/code&gt; and a &lt;code&gt;policy_version&lt;/code&gt;, so a controller reviewing the month can see exactly which rule fired on every dollar and which version of the rule set was active when it did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limits of this sandbox
&lt;/h2&gt;

&lt;p&gt;This is test money against a sandbox at &lt;code&gt;agentic-sandbox.pinkwallet.com&lt;/code&gt;, not production. Production with real money is early access right now (waitlist linked below). The rule engine checks amount, payee, category, and time window; it does not independently verify self-asserted evidence like a stated invoice number, only that one was or wasn't attached. And the order rules are listed in matters: a narrower rule further down the list never fires if a broader one above it already matched.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can a finance team change the budget without redeploying the agent?&lt;/strong&gt; Yes. The &lt;code&gt;PATCH /v1/admin/agents/{id}&lt;/code&gt; call changes &lt;code&gt;monthly&lt;/code&gt; and &lt;code&gt;perPay&lt;/code&gt; immediately; the agent's code and prompt don't change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens if nobody approves a pending_human payment in time?&lt;/strong&gt; The hold carries an &lt;code&gt;expires_at&lt;/code&gt;. After that, the payment is no longer actionable and the agent has to request it again if the work is still needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the agent know it got blocked because of a rule, or does it just fail silently?&lt;/strong&gt; It gets a structured response with &lt;code&gt;decision: "blocked"&lt;/code&gt; and a &lt;code&gt;why&lt;/code&gt; field naming the rule that matched, so the agent (or a human reading its logs) can see exactly why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Sandbox is free, no account required: &lt;a href="https://agentic-sandbox.pinkwallet.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=finance-cap-approve" rel="noopener noreferrer"&gt;agentic-sandbox.pinkwallet.com&lt;/a&gt;. Rules reference: &lt;a href="https://pinkwallet.com/agentic/developers/policy-rules-reference?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=finance-cap-approve" rel="noopener noreferrer"&gt;pinkwallet.com/agentic/developers/policy-rules-reference&lt;/a&gt;. Production with real money is early access: &lt;a href="https://pinkwallet.com/agentic/#early-access?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=finance-cap-approve" rel="noopener noreferrer"&gt;join the waitlist&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>fintech</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
