Correct Payment Amount, Wrong Recipient Address: Where Did Authorization Fail?

 / 
2

The money is still in the wallet, but the agent says the payment failed. This is not a network issue. Two authorization checks are at work.

Some developers reported that when an agent called a paid API, the amount check passed, but the request still returned 'transfer failed'. A block explorer showed the transaction never went on-chain, and logs showed 'recipient not allowed'. The amount and address entered were correct, but the recipient was not on the preset allowlist, so the authorization mechanism rejected the signing request.

First, understand the two gates

AI agent payments must pass two gates: the amount gate and the address gate. If the amount check passes but the address rule blocks the request, it means the first gate opened and the second gate did not. This is the authorization mechanism working as configured, not a system bug.

Recipient allowlist: This limits the agent to paying only specified addresses. If the target address is not on the list, the signing request is rejected and the transaction never goes on-chain.

Spending limits: These limit the amount of funds the agent can use for a single transaction and over time. If the amount check passes, this gate has already been opened.

These checks happen at the same time, not one after another. When the agent starts a payment, the wallet or smart account checks both amount and address. If either check fails, the request is not signed.

Step 1: Find out which rule blocked the payment

Goal: Find the exact reason for the block instead of guessing.

How to check

  • Open the agent's audit log or wallet tool output and find the failed payment record.

  • In Circle Agent Wallet, use the circle wallet log command to check why the transaction failed. It will clearly show whether it was 'address not allowed' or 'limit exceeded'.

  • If using AgentPay, the error will include something like 'recipient not in allowlist' or 'daily limit exceeded'.

Done when: You have a clear rejection reason, not just a generic 'transfer failed' message.

Case A: The recipient address is not on the allowlist

This is the most common case where the amount check passes but the address is blocked.

Why it happens: When you or the system set up the agent wallet, a recipient allowlist was configured. Circle Agent Stack's allowlist feature works this way: it only lets the agent send USDC to specified contract addresses or wallet addresses. AgentPay's AGENTPAY_ALLOWED_RECIPIENTS environment variable does the same job.

Solution:

  1. Go to the wallet configuration page and check the current allowlist.

  2. If the target address really should be allowed, add it to the allowlist.

  3. If the target address is not something the agent should use, the agent's behavior is wrong. It is trying to send funds to an unauthorized address, so review the agent's logic.

Circle CLI: check the allowlist:

circle wallet allowlist --address 0xYourWalletAddress --chain BASE

Circle CLI: add an address:

circle wallet allowlist add --address 0xYourWalletAddress --chain BASE --recipient 0xTargetAddress

Done when: After adding the address, retry the payment and no address rejection error appears.

Case B: The address passes, but the amount rule has a hidden limit

The amount may look correct, but the payment was blocked because only the single transaction limit was checked and the cumulative limit was not.

Circle's limit rules are progressive: per-transaction ≤ daily ≤ weekly ≤ monthly. A 100 USDC transaction may be under the per-transaction limit, but if the 50 USDC daily limit is already used up, the system will still reject the transaction.

Solution: Use circle wallet limit to check the current limit status and make sure there is still room in the daily, weekly, and monthly limits.

Done when: There is remaining room in all limits, and the new transaction succeeds.

Case C: The limit rules are on-chain and cannot be changed directly

Some tools write limit rules into smart contracts. Abstract's Session Key Policy Registry works this way: all session key policies must pass contract allowlist checks, and any request that does not meet the conditions is rejected. Even if the amount is completely correct, the transaction will still fail if the policy contract restricts the target address range or token type.

Solution:

  • Check the scope or constraints configuration that was set when the session key was created.

  • Abstract requires you to add a constraints array to approve-type operations. This limits approval to a specific contract address.

  • If that constraint is not added, the transaction will be rejected directly by the contract.

Done when: After updating the session policy or creating a new session key with the correct constraints, the transaction passes validation.

Important warning

Limit rules are defensive tools that only block payments. They are not authorization passes that allow anything. If the allowlist is too broad, it cannot stop the agent from paying the wrong address. If it is too strict, normal business requests will also be blocked. The official advice is to start with small limits, verify that the agent's behavior is exactly as expected, and then gradually loosen the restrictions.

Regulatory reality: From a legal perspective, if a user gives payment credentials to an agent, the payment will likely be considered 'authorized' no matter how much the agent spends or who it pays. Permission rules are your only defense against an agent going beyond its authority. They are not a shield that protects you from legal responsibility.

Final verification

Run this test to confirm the fix:

  1. Ask the agent to make another payment for the same amount to the same address.

  2. The log should show a clear 'success' or 'settled' record.

  3. Go to the block explorer and check the transaction hash. The status should show 'Success'.

Verification channels: You can see success records in Circle CLI's circle wallet log or AgentPay's audit log. If the transaction still fails, check whether the error message changed from 'address not allowed' to something else. That means the address check passed, and the request is now stuck at the next validation rule.