I had an email in my inbox that I completely forgot to reply to; it was someone I intended to work with to build some interesting stuff. I didn't mean to miss it, who does? I just got busy, and his email got buried under all of the marketing emails I get. I would have missed out on some consulting revenue because I didn't have a system in place to remind me. So I put something together to remind me.

Every morning, Claude Cowork goes through my inbox and looks for any emails that are waiting for me to reply to or that I'm waiting for someone else to reply to. It will then send a wrap-up to Slack so I can follow up on anything I may be missing.

If you do any outbound work — consulting, sales, partnerships, or even managing contractors — email threads are where deals quietly die. This isn't about being more responsive in real time. It's about having a system that catches the things you meant to follow up on but didn't.

What Claude Desktop Does Here

Claude Desktop has a built-in task scheduler called Cowork. You write a plain-English prompt, set a time, and it runs on that schedule using whatever MCP integrations you've connected. I've used it for newsroom inbox triage and LinkedIn carousel generation — Cowork is the part that makes it hands-off.

For this, the setup is:

Gmail MCP: Gives Claude read access to your inbox and sent folder

Slack MCP: Let’s Claude post to a channel

One Cowork scheduled task: The prompt that ties it together, running daily at 8 am

The prompt tells Claude to search Gmail in two directions, filter out noise, read enough of each thread to write a one-liner, and post the digest to Slack. If nothing qualifies in either bucket, nothing gets posted.

The reason this is worth building with Cowork rather than a Zap or a cron job is that you're not just triggering a fixed action — you're asking Claude to read and reason about actual email content. A Zap can fire when an email arrives; it can't tell you whether a reply was a genuine human response or an out-of-office. That judgment is what makes the filter useful.

How the prompt works

You can find the full prompt at the end of the article, but only if you're a subscriber.

Step 1: Finding threads where you're waiting on a reply

Search query: in:sent older_than:3d

That search query will return any email thread in which a message sent more than 3 days ago appears. One note here: in:sent returns all emails you sent during that window, not necessarily the most recent message in a thread. Claude will read the thread, determine which message is the last one, and add it to the list.

The prompt also tells Claude to check whether anything appears to be an out-of-office or auto-reply, whether the email body contains more than 20 words and reads as if a person wrote it, and finally, to filter out any marketing emails that contain unsubscribe or no-reply language.

If you send a lot of one-way emails — announcements, FYIs, newsletters — you may want to exclude your own domain from the results. You can add to:[email protected] to the search query or instruct Claude to skip threads where you're emailing your own organization. Gmail's advanced search operators give you a lot of flexibility here beyond what's in the default prompt.

Once it finds everything that passes the checks, it will add the threads to a list for sending to Slack.

Step 2: Finding threads where someone is waiting on you

Search query: in:inbox older_than:1d

That search query will return any email thread older than 24 hours. Claude checks whether the most recent message is from someone else — not a reply you already sent. It also filters out newsletters, generic messages, and promotional language.

The prompt filters out anything with List-Unsubscribe headers, unsubscribe links in the body, or sender addresses containing noreply, newsletter, or no-reply. These catches cover the bulk of automated emails that land in your inbox.

We don't need the is:unread search query here because we want to catch emails we've opened but not responded to. Once Claude finds everything that passes this check, those threads get added to the list.

Step 3: Post To Slack

Claude will then send both lists to your Slack channel as a single digest, oldest first. If both buckets are empty, nothing gets posted. If the Gmail MCP returns an error, Claude will post an error message instead.

The output looks like this:

📬 Follow-Up Radar — April 22

⏳ WAITING ON THEM (3)

• Sarah @ Acme — "Q2 contract" — 5 days, no reply

• Mike — "Invoice approval" — 4 days, no reply

• [email protected] — "Pricing quote" — 3 days, no reply

📥 WAITING ON YOU (2)

• Dan — "Can you review the brief?" — 2 days, no reply

• Julia — "Quick question on the proposal" — 1 day, no reply

How to Set It Up

Step 1: Connect Gmail MCP

Claude Desktop → Settings → Integrations → add the Gmail MCP and authorize it with the Gmail account you want to monitor. You need read access — the prompt doesn't write to Gmail, reads threads.

Step 2: Connect Slack MCP

Claude Desktop → Settings → Integrations → add the Slack MCP and authorize it with your workspace. Make sure the integration can post to the channel you want to use.

Step 3: Set up the Cowork scheduled task

Claude Desktop → Cowork → Scheduled Tasks → New Task.

Set the frequency to Daily and the time to whatever works for your morning — I use 8:00 am so it's ready before I start working.

Paste the full prompt from prompt.md. Replace #your-channel with the Slack channel name where you want the digest to land. Save.

Step 4: Trigger it manually once

Before trusting it to run on schedule, trigger the task manually and watch the output. Confirm that Claude searches Gmail without errors, that the Slack message lands in the right channel, and that the thread summaries look right.

If the digest is too noisy, adjust the thresholds:

  • Change older_than:3d to older_than:5d if you send a lot of cold outreach or FYIs

  • Change older_than:1d to older_than:2d on the inbox side, if 24 hours feels too tight

You can also add sender-based filters directly in the prompt. If you only want to track threads with people at specific domains — a client list or a shortlist of prospects — add an instruction like: "Only include threads where the sender is not from my own domain and is from a domain I've emailed more than once." That significantly reduces noise for high-volume senders.

What to Watch Out For

in:sent older_than:3d returns threads, not messages

Gmail's search operators work at the thread level. A thread comes back in your in:sent results if any sent message in it falls in the window — even if someone already replied after. The prompt tells Claude to read each thread and confirm that your message is the last one, but this adds to the time the task takes to run on large sent folders.

is:unread isn't the right signal for "waiting on you"

The obvious approach for finding inbound emails you haven't answered is is:unread. The problem: you probably opened the email. It's marked read. It's just unanswered. The prompt uses a thread structure instead — it looks for threads in which the most recent message is from someone else, regardless of read status.

Auto-replies look like real replies

Out-of-office responses, delivery confirmations, and Calendly booking notifications are all technically replies. If the prompt just checks "did a reply arrive after my sent message," it'll skip threads that should still be on the radar. The filter looks for reply bodies under 20 words and flags anything that reads like a canned response.

Your threshold might be wrong for your inbox

Three days is a reasonable default for most business emails. If you send a lot of cold outreach, proposal follow-ups, or newsletter pitches, three days will catch everything — including things you never expected a reply to. Bump it to five or seven days for those cases. Same on the inbox side: 24 hours is tight if your contacts are in different time zones.

The machine has to be on

This runs locally. Suppose your laptop is closed at 8 am, the task skips. For most desk-based workflows, that's fine. If you travel often or work irregular hours, you'll notice gaps.

The cleanest fix is to convert the prompt logic into a server-side function that uses the Gmail API and Slack's Incoming Webhooks directly — no Claude Desktop dependency. I covered that pattern in "How to Automate Email Reports to Slack with Firebase," and the structure carries over well. It's a bigger build, but it runs whether your laptop is open or not.

Taking It Further

A few variations worth trying once the base setup is working:

Track only a specific client list. Add a filter to the prompt that only surfaces threads where the sender or recipient matches a list of domains you care about. Useful if you work with a fixed set of clients and don't want noise from cold contacts you never expected to hear back from.

Run it twice a day. Morning for the daily review, afternoon for anything that came in during the day and needs a same-day reply. Set up a second Cowork task with a tighter older_than:3h window and route it to a separate Slack channel so it doesn't get mixed with your morning digest.

Add a priority signal. Tell Claude to flag threads that mention words like "contract," "proposal," "invoice," or "deadline" and prefix those entries with a 🔴 in the Slack message. That gives you a quick visual triage layer without having to read every summary.

The goal is simple: surface things you've forgotten about before the day gets away from you. Since it looks both ways — who you're waiting on and who's waiting on you — it's less of a reminder tool and more of a relationship radar.

You'll need to tune the thresholds for your inbox. This is just a starting point. Only you know how you work.

The Prompt

You are a follow-up radar agent. Run this task every morning.

## Step 1 — Find threads where you are waiting on a reply

Use the Gmail MCP to search the sent folder for threads where your message is the most recent and no reply has arrived in more than 3 days.

Search query: `in:sent older_than:3d`

For each thread returned:
1. Read the full thread to confirm your sent message is the last message in the thread (not just one of the messages). If a reply exists after your sent message, skip this thread.
2. Check if the reply (if any) looks substantive. Ignore out-of-office auto-replies, delivery receipts, and responses with body text under 20 words.
3. If the sender domain or body contains any of the following, skip this thread — it is noise: `unsubscribe`, `noreply`, `no-reply`, `automated`, `notification`, `do not reply`, `list-unsubscribe`
4. If the thread passes all checks, add it to the WAITING ON THEM list with: sender name or email, subject line, number of days since your sent message.

Sort WAITING ON THEM oldest-first.

## Step 2 — Find threads where someone is waiting on you

Use the Gmail MCP to search the inbox for threads where an inbound message is the most recent and you have not replied within 24 hours.

Search query: `in:inbox older_than:1d`

For each thread returned:
1. Read the full thread to confirm the most recent message is from someone else (not from you). If your reply is the last message, skip this thread.
2. Skip threads where the sender domain or body contains: `unsubscribe`, `noreply`, `no-reply`, `automated`, `notification`, `do not reply`, `list-unsubscribe`
3. Skip threads where the message appears to be a newsletter, marketing email, or automated notification (bulk sender headers, generic salutation, promotional language).
4. If the thread passes all checks, add it to the WAITING ON YOU list with: sender name or email, subject line, number of days since their message.

Sort WAITING ON YOU oldest-first.

## Step 3 — Post to Slack

If both lists are empty, stop here. Do not post to Slack.

Otherwise, use the Slack MCP to post the following message to `#your-channel`:

```
📬 Follow-Up Radar — [TODAY'S DATE, e.g. April 22]

⏳ WAITING ON THEM ([COUNT])
• [Sender name or email] — "[Subject]" — [X] days, no reply
[repeat for each thread, oldest first]

📥 WAITING ON YOU ([COUNT])
• [Sender name or email] — "[Subject]" — [X] days, no reply
[repeat for each thread, oldest first]
```

If only one bucket has items, omit the empty bucket's section entirely.

If the Gmail MCP returns an error on either search, post this instead:
```
⚠️ Follow-Up Radar — [TODAY'S DATE] — Could not reach Gmail. Check your MCP connection.
```

Keep Reading