## TL;DR
Auto-close goes wrong when the close decision races a customer reply: the agent checks activity, finds none, and closes a second before the reply lands. Guard every close with a fresh last-activity check at execution time, exclude tickets with unread customer messages, and never close a ticket the customer touched within the idle window. A close should be a confirmed idle, not a sampled idle.

## The query

```text
auto-close agent closing tickets with pending customer replies
```

## Use this when

- Auto-close shuts tickets customers are still using
- Reopen rates spike after enabling auto-close
- Customers complain about premature closes
- You are operating an auto-close agent

## Not for

- Writing close notification copy
- Choosing idle timeout durations
- Manual agent close workflows
- Ticket archiving policy

## Steps

### 1. Re-check activity at close time, not at scan time

The agent typically scans for idle tickets, then closes them minutes later. Re-read the ticket's last activity immediately before closing. Any customer activity since the scan aborts the close.

Expected output: closes gated on fresh activity reads.

### 2. Exclude tickets with unread customer messages

A customer message the agent has not read yet is pending by definition. Never auto-close a ticket with unread customer messages, regardless of timestamps. Unread is the strongest pending signal.

Expected output: unread-message check as a hard close blocker.

### 3. Define pending explicitly and check all of it

Pending means: unread customer messages, scheduled callbacks, open child tickets, awaiting third-party responses. Write the list and check every item before closing. "No agent activity for N days" is not the same as "nothing pending."

Expected output: a written pending definition, fully checked.

### 4. Warn before closing, and honor the warning window

Send the "we will close this in N days without a reply" notice, and only close after the window fully elapses with no customer activity. The warning is both a courtesy and a second activity check.

Expected output: warning sent, window honored, then close.

### 5. Track wrongful-close rate and reopen rate

Sample closed tickets for customer activity just before close, and track reopens within 7 days. A rising reopen rate means the guards are leaking. Tune from the metric, not from complaints.

Expected output: wrongful-close and reopen metrics tracked.

## Template: the checklist

```text
Auto-close with pending replies:
[ ] Last activity re-checked at close execution time
[ ] Unread customer messages block the close absolutely
[ ] Pending defined (unread, callbacks, child tickets, third-party waits)
[ ] Close warning sent with the full window honored
[ ] Wrongful-close and reopen rates tracked
```

## Variant phrasings

### auto close shutting active tickets

Steps 1 and 2. Fresh check plus unread blocker.

### tickets reopened after auto close

Step 5. The reopen rate is the diagnostic.

### auto close race condition customer reply

Step 1 as the direct fix.

## Why it happens

Auto-close pipelines separate candidate selection from execution, and customer replies land in the gap. The pipeline was designed for truly idle tickets but operates on stale reads, so it closes tickets that were idle at scan time and active at close time. The race is structural; only a fresh read at execution closes it.

## Edge cases

- Customer replies during the warning window: reset the window, do not just delay the close by a day.
- Bot replies counting as activity: exclude automated messages from the activity check or bots will keep tickets alive forever.
- Merged tickets: activity on the merged-away ticket may not show on the survivor. Check merge history.
- Timezone edge: a reply timestamped just inside the window in another timezone. Use UTC consistently for comparisons.

## Provenance

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