Detecting Fraud in Agentic Payments: 7 Patterns Human Rules Miss
An AI shopping agent runs 47 purchases in 11 seconds. Each one is for $19.99, all to the same merchant, all from the same user account, all within a valid mandate. None of them trip a velocity rule, because the per-agent velocity threshold was tuned for humans who pause between clicks. The fraud team finds out 14 hours later when the chargebacks arrive.
Agentic payments are not a future scenario anymore. Visa, Mastercard, Stripe, and PayPal have all shipped agentic commerce protocols in 2025 and 2026. Cloudflare's Agent Pay and the Agent Payments Protocol (AP2) define how AI agents acquire spending mandates and complete checkouts on behalf of humans. The pipes are live. So is the new attack surface.
The fraud signals that worked for humans do not transfer cleanly. Humans get tired, hit typos, pause to think, and travel through space at finite speeds. Agents do none of those things. An attacker who compromises an agent or steals a mandate can fire transactions at machine speed, distribute them across merchants, and coordinate multiple agents under one user. Most existing fraud-detection systems were trained to flag human deviations and miss agent-specific signals entirely.
This article catalogs seven distinct fraud patterns that are either unique to agentic payments or dangerous in agentic contexts even when they exist in human fraud. Each pattern includes a streaming SQL detection query you can run against a continuous transaction stream. Four of the seven are verified end to end against a running RisingWave v2.8.0 instance with real output embedded. The remaining three follow the same pattern and are presented as templates.
Why Human Fraud Rules Fail for AI Agents
Most card-not-present fraud rules in production today rely on assumptions that no longer hold when an AI agent is the buyer:
- Human tempo assumptions. A human types a CVV in seconds, navigates a checkout flow with hesitation, and rarely makes more than a few purchases per hour. Velocity rules built on human tempo flag 10 transactions per minute as suspicious. An agent with a valid mandate can legitimately do 100 in a minute when restocking groceries or rebooking a multi-leg trip.
- Geo-velocity heuristics. Impossible-travel detection assumes the buyer has a body. An agent runs in a data center; geographic signals from agent transactions reflect cloud regions, not the human user's location. A naive geo-velocity rule will either flag every legitimate agent transaction or, after relaxation, flag none of the malicious ones.
- Behavioral biometrics. Mouse movement, typing rhythm, and scroll patterns are absent. Agents do not generate them.
- Per-card velocity windows. Agents share payment instruments. One card may legitimately back five different agents owned by one user. Per-card aggregations underestimate the real velocity per agent and overestimate per-user.
- Static whitelist merchants. Legitimate agents discover merchants dynamically through marketplaces and protocol-level catalogs. Static merchant whitelists either reject legitimate purchases or get loosened until they protect nothing.
The fraud signals that do work shift in two directions. First, they get more agent-aware: per-agent cadence, per-mandate scope, per-agent geographic stationarity. Second, they get more user-centric: cross-agent correlation under one user, cumulative spend across multiple mandates. Both shifts demand stateful, low-latency processing across multiple streams. Batch jobs running every six hours cannot meet the timing budget when an agent can drain a card in seconds.
A real-world example: an anonymous commission-free trading broker we work with replaced a stack of Apache Flink, Apache Kafka, and Apache Spark with RisingWave to power their fraud feature store. The team saw the same shift play out in trading agents: human-tuned alpha rules generated thousands of false positives once retail customers started using algorithmic agents, and the fix required materialized views that aggregated behavior per user across all agents in real time. Atome, a regional buy-now-pay-later provider, made a similar move for real-time risk scoring on transactions that increasingly originate from automated checkout flows.
We will use a setup with two tables: one for agent transactions, one for the mandates that authorize them.
CREATE TABLE aap06_agent_transactions (
tx_id VARCHAR PRIMARY KEY,
agent_id VARCHAR NOT NULL,
user_id VARCHAR NOT NULL,
mandate_id VARCHAR,
merchant VARCHAR NOT NULL,
merchant_category VARCHAR,
amount DECIMAL NOT NULL,
country VARCHAR,
lat DOUBLE PRECISION,
lng DOUBLE PRECISION,
tx_time TIMESTAMPTZ NOT NULL
);
CREATE TABLE aap06_mandates (
mandate_id VARCHAR PRIMARY KEY,
agent_id VARCHAR NOT NULL,
user_id VARCHAR NOT NULL,
scope_merchant VARCHAR,
max_amount DECIMAL,
valid_from TIMESTAMPTZ,
valid_to TIMESTAMPTZ
);
In production, both tables would be backed by Kafka sources ingesting from your payment gateway and mandate registry. For this article, we use direct inserts. The dataset embeds patterns 1, 2, 3, and 4 across 28 transactions and 7 mandates so we can verify each detection materialized view against real output.
INSERT INTO aap06_mandates VALUES
('mdt_001', 'agt_alpha', 'usr_100', 'amazon.com', 200.00,
'2026-05-01 00:00:00+00', '2026-05-31 23:59:59+00'),
('mdt_002', 'agt_beta', 'usr_200', 'instacart.com', 150.00,
'2026-05-01 00:00:00+00', '2026-05-31 23:59:59+00'),
('mdt_003', 'agt_gamma', 'usr_300', 'expedia.com', 1000.00,
'2026-05-01 00:00:00+00', '2026-05-31 23:59:59+00'),
('mdt_004', 'agt_delta', 'usr_400', 'doordash.com', 80.00,
'2026-05-01 00:00:00+00', '2026-05-15 23:59:59+00'),
('mdt_005', 'agt_epsilon', 'usr_500', 'walmart.com', 300.00,
'2026-05-01 00:00:00+00', '2026-05-31 23:59:59+00'),
('mdt_006', 'agt_zeta', 'usr_500', 'target.com', 300.00,
'2026-05-01 00:00:00+00', '2026-05-31 23:59:59+00'),
('mdt_007', 'agt_eta', 'usr_600', 'apple.com', 500.00,
'2026-05-01 00:00:00+00', '2026-05-31 23:59:59+00');
Note that usr_500 owns two agents, agt_epsilon and agt_zeta, with mandates at related retailers. That setup is what enables Pattern 4.
Pattern 1: Hijacked Agent Burst
A legitimate shopping agent normally completes a few purchases per hour. When the agent is hijacked, either through a stolen API token or a compromised host, the attacker has a short window to extract value before the user notices. The signature is a sudden spike in transaction count over a tight window: the agent fires five, ten, or fifty transactions in a few seconds, completely outside its normal rhythm.
Per-card velocity rules miss this when several agents share one card, and per-agent rules miss it when the threshold is set high enough to allow legitimate burst behavior like grocery restocking. The detection that works is a rolling-window count partitioned by agent_id.
CREATE MATERIALIZED VIEW aap06_burst_detection_mv AS
WITH windowed AS (
SELECT
agent_id,
user_id,
tx_id,
tx_time,
COUNT(*) OVER (
PARTITION BY agent_id
ORDER BY tx_time
RANGE BETWEEN INTERVAL '60 seconds' PRECEDING AND CURRENT ROW
) AS tx_in_60s
FROM aap06_agent_transactions
)
SELECT
agent_id,
user_id,
MAX(tx_in_60s) AS peak_burst_count,
MIN(tx_time) FILTER (WHERE tx_in_60s >= 5) AS burst_start,
MAX(tx_time) FILTER (WHERE tx_in_60s >= 5) AS burst_end
FROM windowed
WHERE tx_in_60s >= 5
GROUP BY agent_id, user_id;
Querying the view against the seeded dataset:
agent_id | user_id | peak_burst_count | burst_start | burst_end
-----------+---------+------------------+---------------------------+---------------------------
agt_alpha | usr_100 | 5 | 2026-05-05 14:01:00+00:00 | 2026-05-05 14:01:45+00:00
(1 row)
agt_alpha had three normal transactions during the day, then fired eight in a row at 15-second intervals starting at 14:00:00. The window count peaks at 5 within the 60-second slice, which is the threshold for an alert. In production you would tune the threshold per-agent based on its baseline, and stream the burst events to a downstream queue that pauses the agent's mandate. RisingWave evaluates this materialized view incrementally as new transactions arrive, so the alert lands inside the same second as the offending transaction.
Pattern 2: Mandate Replay Attack
A mandate is the cryptographic token that authorizes an agent to spend up to a limit at a specific merchant during a specific window. The protocol assumes single-use or bounded-use semantics, but implementations vary. An attacker who captures a mandate can attempt to reuse it many times, individually staying under the per-transaction cap while collectively breaching the cumulative cap or the time window.
Detection joins the transaction stream against the mandate registry and computes cumulative spend per mandate.
CREATE MATERIALIZED VIEW aap06_replay_detection_mv AS
SELECT
t.mandate_id,
t.agent_id,
t.user_id,
m.max_amount,
COUNT(*) AS use_count,
SUM(t.amount) AS cumulative_spend,
SUM(t.amount) - m.max_amount AS over_amount
FROM aap06_agent_transactions t
JOIN aap06_mandates m ON t.mandate_id = m.mandate_id
GROUP BY t.mandate_id, t.agent_id, t.user_id, m.max_amount
HAVING SUM(t.amount) > m.max_amount;
Output:
mandate_id | agent_id | user_id | max_amount | use_count | cumulative_spend | over_amount
------------+-------------+---------+------------+-----------+------------------+-------------
mdt_001 | agt_alpha | usr_100 | 200 | 11 | 256.41 | 56.41
mdt_002 | agt_beta | usr_200 | 150 | 4 | 435.00 | 285.00
mdt_003 | agt_gamma | usr_300 | 1000 | 3 | 1570.00 | 570.00
mdt_005 | agt_epsilon | usr_500 | 300 | 3 | 891.00 | 591.00
mdt_006 | agt_zeta | usr_500 | 300 | 3 | 889.00 | 589.00
(5 rows)
Five mandates have been used past their cap. mdt_002 is the cleanest replay signal: an instacart.com mandate capped at $150 that has accumulated $435 across four uses. mdt_001 shows the cumulative-spend version of the burst pattern from before; the per-transaction amount of $19.99 stayed under any single-transaction limit, but the cumulative breach is real.
The same pattern, with valid_to added to the join, catches time-window replay (a mandate used after its expiration timestamp). Most production deployments combine the two: filter tx_time BETWEEN m.valid_from AND m.valid_to first, then aggregate, and emit two separate signals for amount overage and time-window overage.
Pattern 3: Scope Escalation
A mandate scoped to expedia.com should not produce a charge at casino-online.com. Agents are expected to honor mandate scope, but a compromised agent or a buggy implementation may not. Scope escalation is the simplest of the seven patterns to detect and one of the highest-signal: a single occurrence is almost certainly fraud or a critical bug.
CREATE MATERIALIZED VIEW aap06_scope_escalation_mv AS
SELECT
t.tx_id,
t.agent_id,
t.user_id,
t.mandate_id,
m.scope_merchant AS allowed_merchant,
t.merchant AS actual_merchant,
t.amount,
t.tx_time
FROM aap06_agent_transactions t
JOIN aap06_mandates m ON t.mandate_id = m.mandate_id
WHERE t.merchant <> m.scope_merchant;
Output:
tx_id | agent_id | user_id | mandate_id | allowed_merchant | actual_merchant | amount | tx_time
--------+-----------+---------+------------+------------------+-------------------+--------+---------------------------
tx_017 | agt_gamma | usr_300 | mdt_003 | expedia.com | airbnb.com | 320.00 | 2026-05-04 12:30:00+00:00
tx_018 | agt_gamma | usr_300 | mdt_003 | expedia.com | casino-online.com | 800.00 | 2026-05-04 13:00:00+00:00
(2 rows)
agt_gamma had a mandate for expedia.com and used it at airbnb.com and casino-online.com. The Airbnb hit is potentially a benign category leak; some payment networks treat related travel merchants as substitutable. The casino hit is unambiguous fraud. In production, you would enrich scope_merchant with a category hierarchy (so expedia.com and airbnb.com both belong to travel) and split the view into a strict-violation tier and a category-violation tier. Strict violations get blocked synchronously; category violations get reviewed.
This pattern is structurally similar to row-level access control. The mandate is a per-transaction grant; the view enforces it as a streaming filter.
Pattern 4: Multi-Agent Collusion
The most subtle of the four. A user authorizes several agents, each with its own mandate. If a single attacker controls all of them, the attacker can split a large fraudulent purchase across mandates to stay under per-agent caps, while the cumulative damage to the user is unmistakable. Per-agent monitoring sees nothing wrong; per-user monitoring sees the pattern immediately.
CREATE MATERIALIZED VIEW aap06_collusion_mv AS
WITH paired AS (
SELECT
a.user_id,
a.agent_id AS agent_a,
b.agent_id AS agent_b,
a.tx_id AS tx_a,
b.tx_id AS tx_b,
a.amount AS amt_a,
b.amount AS amt_b,
ABS(EXTRACT(EPOCH FROM (a.tx_time - b.tx_time))) AS gap_seconds
FROM aap06_agent_transactions a
JOIN aap06_agent_transactions b
ON a.user_id = b.user_id
AND a.agent_id < b.agent_id
AND ABS(EXTRACT(EPOCH FROM (a.tx_time - b.tx_time))) <= 10
AND ABS(a.amount - b.amount) < 10
)
SELECT
user_id,
agent_a,
agent_b,
COUNT(*) AS coordinated_pair_count,
SUM(amt_a + amt_b) AS coordinated_total_amount
FROM paired
GROUP BY user_id, agent_a, agent_b
HAVING COUNT(*) >= 2;
Output:
user_id | agent_a | agent_b | coordinated_pair_count | coordinated_total_amount
---------+-------------+----------+------------------------+--------------------------
usr_500 | agt_epsilon | agt_zeta | 3 | 1780.00
(1 row)
usr_500 ran two agents at almost the same time, each making three purchases of approximately $295 to $299, one at Walmart and one at Target, paired within 5 seconds of each other. The per-agent view sees three transactions of $295 to a single mandate, all under the $300 cap. The cross-agent view sees $1780 of coordinated activity in two minutes.
This pattern matters more in agentic commerce than in human fraud because legitimate users do authorize multiple agents. Cross-agent correlation is a normal feature of the topology; the fraud signal is correlation that is too tight in time and too suspicious in amounts. The threshold is tunable: five-second windows and $10 amount tolerance work for the dataset above; production deployments typically scan a broader window and weight by amount and merchant similarity.
Pattern 5: Cross-Merchant Correlation Fraud
This pattern is structurally close to Pattern 4 but operates within a single agent rather than across agents. A compromised agent visits a sequence of unrelated merchants in a short window in a way that does not match any plausible user intent: an Apple Store purchase, then a gift-card reseller, then a peer-to-peer transfer. The signal is the merchant-category transition graph, not the per-merchant velocity.
The detection SQL follows the same shape as the burst and replay views, but groups by an agent_id plus a window over distinct merchant categories.
-- Pattern 5 detection (template, not run against the dataset above):
CREATE MATERIALIZED VIEW aap06_cross_merchant_mv AS
WITH windowed AS (
SELECT
agent_id,
user_id,
tx_time,
COUNT(DISTINCT merchant_category) OVER (
PARTITION BY agent_id
ORDER BY tx_time
RANGE BETWEEN INTERVAL '5 minutes' PRECEDING AND CURRENT ROW
) AS distinct_categories_5m
FROM aap06_agent_transactions
)
SELECT agent_id, user_id, MAX(distinct_categories_5m) AS peak_categories
FROM windowed
WHERE distinct_categories_5m >= 4
GROUP BY agent_id, user_id;
Tuning depends on the agent type. A general-purpose shopping agent legitimately spans categories; a travel agent should not. In practice you maintain a per-agent baseline of normal category breadth and alert on deviations. The same materialized view shape used for Patterns 1, 2, and 3 carries over: incremental aggregation with a rolling time window function.
Pattern 6: Cadence Anomaly
Humans transact at irregular intervals. Even a power user has variation in the gap between consecutive purchases: 4 seconds, 17 seconds, 3 minutes. A naive agent implementation often fires at perfectly regular intervals, sometimes by accident (a setInterval(100) loop) and sometimes by design (rate-limit-respecting backoff). Both are visible in the inter-arrival time distribution.
The signal is statistical: the variance of inter-arrival times collapses near zero. Detection computes the standard deviation of consecutive transaction gaps per agent and alerts when it falls below a threshold while the mean is also small.
-- Pattern 6 detection (template):
CREATE MATERIALIZED VIEW aap06_cadence_mv AS
WITH gaps AS (
SELECT
agent_id,
user_id,
tx_time,
EXTRACT(EPOCH FROM (
tx_time - LAG(tx_time) OVER (PARTITION BY agent_id ORDER BY tx_time)
)) AS gap_seconds
FROM aap06_agent_transactions
)
SELECT
agent_id,
user_id,
AVG(gap_seconds) AS mean_gap,
STDDEV(gap_seconds) AS stddev_gap,
COUNT(*) AS sample_size
FROM gaps
WHERE gap_seconds IS NOT NULL
GROUP BY agent_id, user_id
HAVING COUNT(*) >= 10
AND STDDEV(gap_seconds) < 1
AND AVG(gap_seconds) < 30;
This view emits one row per agent whose recent transactions arrived at suspiciously consistent intervals. The threshold pair (stddev < 1 second, mean < 30 seconds) catches obvious robotic timing without flagging legitimate scheduled purchases like every-Friday grocery runs. For broader coverage, replace the global aggregate with a windowed aggregate over the most recent N transactions.
Pattern 7: Geographic Impossibility for Stationary Agents
Geographic anomalies behave differently for agents than for humans. A human's location moves continuously through space, so impossible-travel rules look for transitions that exceed plausible velocity. An agent runs in a fixed data center for its lifetime; its claimed lat/lng should not change at all unless the agent reports the user's mobile location for delivery.
The fraud signature is: an agent that has previously transacted from one stable geographic point suddenly reports a different point. Either the agent has been hijacked and is running in a different region, or the location signal is being spoofed.
-- Pattern 7 detection (template):
CREATE MATERIALIZED VIEW aap06_geo_stationarity_mv AS
WITH per_agent AS (
SELECT
agent_id,
user_id,
COUNT(*) AS tx_count,
STDDEV(lat) AS lat_stddev,
STDDEV(lng) AS lng_stddev,
MAX(lat) - MIN(lat) AS lat_range,
MAX(lng) - MIN(lng) AS lng_range
FROM aap06_agent_transactions
WHERE lat IS NOT NULL AND lng IS NOT NULL
GROUP BY agent_id, user_id
)
SELECT *
FROM per_agent
WHERE tx_count >= 5
AND (lat_range > 1.0 OR lng_range > 1.0);
A lat_range > 1.0 corresponds to roughly 110 kilometers of north-south movement; an agent whose claimed location moves more than that in its transaction history is almost certainly compromised or spoofed. In production, you maintain the agent's "home" point as a separate registry value and alert on any deviation beyond a per-agent radius. The pattern fits the streaming model cleanly: each new transaction updates the aggregate incrementally.
Composing Patterns Into a Risk Score
No single pattern is the answer. A real fraud system combines all seven into a composite risk score and routes per-transaction decisions based on the total. The composition is straightforward in streaming SQL: each detection materialized view emits a per-agent or per-mandate signal, and a final view joins them and assigns weights.
A representative skeleton:
CREATE MATERIALIZED VIEW aap06_agent_risk_score_mv AS
SELECT
a.agent_id,
a.user_id,
-- Pattern 1
COALESCE(b.peak_burst_count, 0) AS burst_score,
-- Pattern 2
COALESCE(r.over_amount, 0) AS replay_over_amount,
-- Pattern 3
COALESCE(s.violation_count, 0) AS scope_violations,
-- Pattern 4
COALESCE(c.coordinated_pair_count, 0) AS collusion_pairs,
-- Composite
(COALESCE(b.peak_burst_count, 0) * 5
+ COALESCE(r.over_amount, 0) * 0.1
+ COALESCE(s.violation_count, 0) * 50
+ COALESCE(c.coordinated_pair_count, 0) * 30) AS composite_risk
FROM (SELECT DISTINCT agent_id, user_id FROM aap06_agent_transactions) a
LEFT JOIN aap06_burst_detection_mv b USING (agent_id, user_id)
LEFT JOIN aap06_replay_detection_mv r USING (agent_id, user_id)
LEFT JOIN (SELECT agent_id, user_id, COUNT(*) AS violation_count
FROM aap06_scope_escalation_mv GROUP BY agent_id, user_id) s
USING (agent_id, user_id)
LEFT JOIN aap06_collusion_mv c ON c.agent_a = a.agent_id;
The weights are illustrative; in production they come from a calibration pipeline that ties detection rates to confirmed-fraud labels. The streaming model lets the composite score update on every new transaction, so a downstream policy engine can block, hold, or release in the same transaction lifecycle.
For deeper coverage of related primitives, see our companion articles on payment fraud detection with streaming SQL, transaction velocity fraud detection, and the broader fraud-detection feature store pattern.
FAQ
How is agentic payment fraud different from traditional payment fraud?
Traditional payment fraud rules assume a human is on the other end of the transaction: they get tired, they get frustrated, they make typos, they take time between actions. AI agents do none of these things. An agent can fire 100 transactions per second with millisecond-level consistency, switch merchants instantly, and operate 24/7 with no fatigue signal. The fraud signals shift from human-behavior heuristics like impossible travel and typing speed to agent-specific signals like cadence anomalies, mandate scope violations, replay attacks, and multi-agent collusion. Detecting agentic fraud requires streaming systems that maintain state across agent sessions and correlate behavior across mandates, merchants, and time windows.
What is mandate replay and how can it be detected?
A mandate is the cryptographic permission a user grants an AI agent to spend money on their behalf, typically scoped by merchant, amount cap, and time window. Mandate replay happens when a compromised agent or a man-in-the-middle reuses the same mandate beyond its intended scope, for example by submitting it 20 times in a row or using it after the legitimate transaction has already settled. Detection works by joining the live transaction stream against the mandate registry, computing the cumulative spend per mandate, and comparing to the max_amount and valid_to window. A streaming materialized view in RisingWave keeps this comparison continuously fresh so a replay can be blocked within seconds.
Can multiple AI agents collude in payment fraud?
Yes. Users frequently authorize several agents at once: a shopping agent, a travel agent, a subscription manager, a grocery agent. If one is compromised, an attacker can coordinate purchases across all of them, splitting amounts to stay under per-agent thresholds while draining the user. Detection requires a user-centric view rather than an agent-centric view: aggregate behavior by user_id across agents, and look for time-correlated transactions of similar amounts at related merchants. Streaming SQL with self-joins on the transaction table catches this pattern in seconds.
What tools are best for real-time agentic fraud detection?
Real-time agentic fraud detection requires a streaming database that supports stateful pattern matching, low-latency joins between transaction streams and mandate registries, and incremental aggregation across rolling time windows. RisingWave fits this need with PostgreSQL-compatible streaming SQL and built-in materialized views, removing the need to write Java or Scala jobs in Apache Flink. Apache Kafka or Apache Pulsar work as the ingestion layer; RisingWave consumes from them and serves fraud signals to downstream systems through Postgres-compatible queries or change-data-capture sinks.
Wrapping Up
Agentic payments are not just card-not-present fraud at higher volume. They are a new transaction shape with a new threat model. The seven patterns in this article (hijacked agent burst, mandate replay, scope escalation, multi-agent collusion, cross-merchant correlation, cadence anomaly, and geographic impossibility) cover the bulk of what a working agentic fraud system needs to detect today. Each one composes into a streaming materialized view that updates as transactions arrive. None of them require writing a single line of Java or Scala.
The teams already in production with this architecture, from a commission-free trading broker that retired Flink, Kafka, and Spark in favor of RisingWave to BNPL providers like Atome scoring risk on every authorization, share a pattern: define the detection logic in SQL, let the streaming engine maintain the state, and feed the signals into a policy layer that decides whether to authorize, hold, or block.
Ready to detect agentic fraud patterns in real time? Try RisingWave Cloud free.
Join our Slack community to discuss agentic fraud detection.

