**TL;DR**

Failed logins must get quieter, not louder. Put a circuit breaker on the login path: a few failures in a row trips it, and once it's tripped the agent stops trying and pages a human. Add real backoff between attempts so even the early retries don't look like an attack. An account locked for suspicious activity at 2am is almost always an agent retrying a dead session, not an actual attacker, and the fix is to make the agent give up gracefully.

```text
salesloft session expired at 2am and the agent kept clicking log in in a loop until the account got locked for suspicious activity
```

## Steps

1. Detect session expiry as its own signal: the session cookie or token is gone or rejected, which is different from a wrong password. Log it as session_expired, not login_failed.
   Expected: an expired session in staging is classified correctly and doesn't increment the bad-password counter.
2. Add exponential backoff between login attempts, starting at minutes not seconds. The first retry should not fire immediately.
   Expected: three failed logins in staging are spaced minutes apart, not seconds.
3. Trip a circuit breaker after a small number of consecutive failures (three is plenty). While the breaker is open, no login attempts happen at all and the operator gets paged.
   Expected: the fourth consecutive failure pages the operator and the fifth attempt never fires.
4. While the breaker is open, pause the jobs that depend on the session instead of letting each one run its own retry loop. One breaker for the account, not one per job.
   Expected: with the breaker open, dependent sequences show paused_for_auth and make zero login attempts.
5. Require a human to close the breaker after re-authenticating or confirming the session is valid again. The agent never resets its own breaker.
   Expected: the breaker stays open through a simulated recovery until the operator explicitly closes it.

## Use this when

- a session expires overnight and the agent's retry loop gets the account locked
- repeated login failures are triggering suspicious-activity flags
- you need backoff and a circuit breaker on an automated login path

## Not for this skill when

- an OAuth refresh grant that was revoked (that's a re-authorization problem, not a retry problem)
- a human-verification checkpoint on login (that's a stop-and-alert problem, never a retry problem)
- rate limits on API calls (that's an API backoff problem, separate from login attempts)

## Variant phrasings

- session expired, agent retried login in a loop, account locked for suspicious activity
- automated login hammering after session death, 2am lockout
- no backoff on login retries, platform flagged the account

## Why it happens

The session died at 2am and the agent's only behavior for a failed login was to try again immediately. To the platform, dozens of rapid login attempts from an automated client look exactly like a credential-stuffing attack, so it locked the account. The agent turned a routine session expiry into a security incident because nothing told it to slow down or stop.

## Edge cases

- the breaker threshold should be low for logins and higher for API calls; a login is a much more sensitive signal to a platform than a throttled API request
- backoff with jitter avoids the thundering herd when several agents share the same dead session and all retry at once
- a session that expires on a predictable schedule (every N hours) should be refreshed proactively before expiry, not retried after
- log every login attempt with timestamp and outcome; when the platform asks what happened at 2am, you want the answer in one query

## Provenance

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