## TL;DR
The agent parks a transaction in review while waiting for a 3D Secure challenge that may never complete, and the whole run hangs on it. Fix: never block on 3DS. Give the review state a TTL, release the worker, and let a scheduler re-check at expiry. Waiting is a scheduled job, not a held thread.

```text
fraud agent never exited review state on pending 3ds and timed out
```

## Use this when
- Run elapsed time tracks a single pending-3DS transaction with no progress.
- Workers pile up behind one transaction stuck in review.
- Runs time out instead of completing when 3DS challenges are pending.

## Not for this skill when
- Scoring itself is slow. That is a performance problem, not a parked state.
- 3DS completes but the result is wrong. That is an integration bug.

## Steps
1. Confirm the hang: find runs where the log shows no progress while one transaction sits in review. Verify: elapsed time correlates with one pending-3DS transaction.
2. Add a TTL to the review state, matched to your 3DS expiry window. Verify: every parked state record carries an expires-at timestamp.
3. On entering review for 3DS, release the worker and schedule a re-check at expiry. Verify: the worker picks up the next transaction immediately.
4. At expiry, re-read the 3DS outcome: completed means resume scoring, still pending means move to a timed-out state with a reason code. Verify: every parked transaction reaches a terminal state.
5. Alert on transactions that time out repeatedly from the same device or card. Verify: repeat timeouts surface as a pattern instead of silent drops.

## Variant phrasings
### agent hangs on pending 3ds
Common phrasing.
### 3ds pending review timeout
State-focused search.
### fraud agent waits for 3ds forever
Agent-focused phrasing.

Compatibility: any async review pipeline; the scheduler can be a cron job, a delayed queue, or the agent's own tick loop.

## Why it happens
The agent was written as if 3DS completes synchronously. In reality the customer may abandon, the bank page may fail, or the challenge may expire. A blocking wait on an external human action is a guaranteed hang.

## Edge cases / pitfalls
- Customers who complete 3DS after the TTL: allow reopening from the timed-out state if your policy permits, with the late result logged.
- TTLs shorter than the bank's challenge window cause false timeouts; align with the card network's expiry.
- Never auto-approve on timeout. Timed out means escalate or decline per policy, never silent approval.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_WmKqTeiPYpVxcaR_h9IwDg
