diff --git a/docs/docs.json b/docs/docs.json
index 49794a422fd..8d5f3d3bbaa 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -618,6 +618,7 @@
"guides/example-projects/product-image-generator",
"guides/example-projects/realtime-csv-importer",
"guides/example-projects/realtime-fal-ai",
+ "guides/example-projects/resend-email-agent",
"guides/example-projects/smart-spreadsheet",
"guides/example-projects/turborepo-monorepo-prisma",
"guides/example-projects/vercel-ai-sdk-deep-research",
diff --git a/docs/guides/example-projects/resend-email-agent.mdx b/docs/guides/example-projects/resend-email-agent.mdx
new file mode 100644
index 00000000000..6ecb3c78171
--- /dev/null
+++ b/docs/guides/example-projects/resend-email-agent.mdx
@@ -0,0 +1,160 @@
+---
+title: "Resend email agent with Slack approval"
+sidebarTitle: "Resend email agent"
+description: "An AI agent that drafts replies to a Resend inbox and sends nothing until you approve it in Slack. Uses hosted webhooks for Resend and Slack, and wait tokens to pause each email thread until you click Send."
+---
+
+
+
+## Overview
+
+This agent drafts replies to the email in a [Resend Inboxes](https://resend.com/docs/api-reference/inboxes) inbox and posts each draft to your Slack DMs for approval. Every email chain gets its own Slack thread. Click **Send** to reply from the inbox address, **Don't send** to drop the draft, or reply in the thread ("shorter", "say we're closed over Christmas") to get a new draft. Later emails in the same chain land in the same Slack thread.
+
+**Tech stack:**
+
+- **[Trigger.dev webhooks](/webhooks/overview)** receive Resend and Slack events and verify their signatures
+- **[Wait tokens](/wait-for-token)** pause each email thread's run until you act in Slack
+- **[Resend Inboxes](https://resend.com/docs/api-reference/inboxes)** receive email and send the approved replies
+- **[AI SDK](https://ai-sdk.dev)** drafts replies through the [Vercel AI Gateway](https://vercel.com/docs/ai-gateway)
+- **[Slack](https://api.slack.com)** for the DM-only approval app
+
+**Features:**
+
+- **A person sends every reply**: the model has no tools, so a hostile email can only change the words of a draft you read first.
+- **Feedback in the thread**: replying to a draft writes a new one that takes your note into account.
+- **One run per email chain**: a run waits days for your click without holding a machine or a concurrency slot.
+- **Sender allowlist**: `ALLOWED_SENDER_DOMAINS` drops unknown senders before they reach Slack or cost a model call.
+- **Idempotent sends**: each inbound email gets at most one reply, even when a run retries.
+
+## GitHub repo
+
+
+ Click here to view the full code for this project in our examples repository on GitHub. You can
+ fork it and use it as a starting point for your own project.
+
+
+## How it works
+
+Each email chain gets one long-running `email-thread` run that sleeps on a wait token between events. The token is tagged with the email thread id and the Slack message timestamp, so a webhook from either side can find it and wake the run.
+
+```mermaid
+flowchart LR
+ E([New email]) --> R[resend-email-received webhook task]
+ C([Button click]) --> S[slack-activity webhook task]
+ T([Thread reply]) --> S
+ R -- wakes or starts --> RUN[email-thread run waits on a token]
+ S -- completes token --> RUN
+ RUN -- email, draft, buttons --> DM[Your Slack DM]
+ RUN -- after you click Send --> SEND[Resend reply]
+```
+
+### Hosted webhook endpoints
+
+Two endpoints receive events, one for Resend and one for Slack. Trigger.dev checks each request's signature before your code runs, and the Slack source answers Slack's `url_verification` handshake.
+
+```ts src/trigger/endpoints.ts
+import { webhooks } from "@trigger.dev/sdk";
+import { webhookSource, type SlackBlockActions, type SlackMessageEvent } from "@trigger.dev/slack";
+import type { ResendWebhookEvent } from "./resend";
+
+export const resendEvents = webhooks.endpoint.define({
+ id: "resend",
+ source: webhooks.resend(),
+});
+
+export const slackEvents = webhooks.endpoint.define({
+ id: "slack",
+ source: webhookSource(),
+});
+```
+
+### Waiting for approval
+
+After posting a draft, the run creates a wait token and waits on it. The token is created before the draft is posted, so a fast click always has something to complete. Each button carries the token id.
+
+```ts src/trigger/email-thread.ts
+const token = await wait.createToken({
+ timeout: "30d",
+ tags: [emailTag(threadId), slackTag(slackTs)],
+});
+draftTs = await post(channel, "Draft reply", draftBlocks(draft, token.id), slackTs);
+
+const result = await wait.forToken(token);
+```
+
+### Waking the run
+
+The webhook tasks find the waiting token by tag and complete it with what happened: a button click, a reply in the thread, or a new email. The run then sends the reply, drops it, or redrafts with your note, and waits again.
+
+```ts src/trigger/inbound.ts
+const token = await waitingToken(slackTag(msg.thread_ts));
+if (token) await wait.completeToken(token, { kind: "feedback", user: msg.user, text });
+```
+
+## Running the project
+
+You need a Trigger.dev project, a Resend inbox on a verified domain, a Slack workspace where you can create apps, and a Vercel AI Gateway key.
+
+
+
+ ```bash
+ git clone https://github.com/triggerdotdev/examples.git
+ cd examples/resend-slack-email-agent
+ cp .env.example .env
+ pnpm install
+ ```
+
+ Set `TRIGGER_PROJECT_REF` in `.env` to your project's ref, from the project settings page in the dashboard. Then run `pnpm dev`, which adds two endpoints, `resend` and `slack`, to your dev environment's **Webhooks** page.
+
+
+ Add a Resend webhook pointing at the `resend` endpoint URL with the `inbox.email.received` event. Paste its signing secret into the `resend` endpoint, and set `RESEND_API_KEY`.
+
+
+ Put the `slack` endpoint URL in `slack/manifest.yaml` and create the app from it. Paste its Signing Secret into the `slack` endpoint, click **Verify** in Event Subscriptions, install the app, and set `SLACK_BOT_TOKEN`.
+
+
+ Set `SLACK_USER_ID` to your Slack member ID, `ALLOWED_SENDER_DOMAINS` to the domains you accept email from, and `AI_GATEWAY_API_KEY`. Restart `pnpm dev`.
+
+
+ Email your inbox from an allowed address. A DM from the bot shows the email with a draft in its thread, and the dev terminal shows a `resend-email-received` run followed by an `email-thread` run that stays waiting.
+
+
+
+To deploy, run `npx trigger.dev@latest deploy` and set the same environment variables on your production environment. Production has its own `resend` and `slack` endpoints, with their own URLs and secrets: point a Resend webhook and a Slack app at the production URLs, and paste each one's signing secret into the matching production endpoint. Until then, the endpoint shows "Needs secret" on the Webhooks page.
+
+## Relevant code
+
+- **Email thread task**: [src/trigger/email-thread.ts](https://github.com/triggerdotdev/examples/blob/main/resend-slack-email-agent/src/trigger/email-thread.ts): one run per chain that posts, drafts, waits on a token and acts on the result
+- **Webhook tasks**: [src/trigger/inbound.ts](https://github.com/triggerdotdev/examples/blob/main/resend-slack-email-agent/src/trigger/inbound.ts): wake or start a thread's run from Resend emails, Slack clicks and thread replies
+- **Drafting prompt**: [src/trigger/draft.ts](https://github.com/triggerdotdev/examples/blob/main/resend-slack-email-agent/src/trigger/draft.ts): the AI SDK call and the system prompt to tune for your inbox
+- **Webhook endpoints**: [src/trigger/endpoints.ts](https://github.com/triggerdotdev/examples/blob/main/resend-slack-email-agent/src/trigger/endpoints.ts): the hosted Resend and Slack endpoints
+- **Slack app**: [slack/manifest.yaml](https://github.com/triggerdotdev/examples/blob/main/resend-slack-email-agent/slack/manifest.yaml): a DM-only app with three scopes
+
+## Learn more
+
+
+
+ Hosted endpoints that verify and deliver events to your tasks.
+
+
+ Pause a run until an external event completes a token.
+
+
+ Every built-in source, including `resend()`, and how each is verified.
+
+
+ The Slack source and channel in `@trigger.dev/slack`.
+
+
diff --git a/docs/guides/introduction.mdx b/docs/guides/introduction.mdx
index aeb9611b063..d354fea6ae3 100644
--- a/docs/guides/introduction.mdx
+++ b/docs/guides/introduction.mdx
@@ -70,6 +70,7 @@ Example projects are full projects with example repos you can fork and use. Thes
| [Python web crawler](/guides/python/python-crawl4ai) | Use Python, Crawl4AI and Playwright to create a headless web crawler with Trigger.dev. | — | [View the repo](https://github.com/triggerdotdev/examples/tree/main/python-crawl4ai) |
| [Realtime CSV Importer](/guides/example-projects/realtime-csv-importer) | Upload a CSV file and see the progress of the task streamed to the frontend. | Next.js | [View the repo](https://github.com/triggerdotdev/examples/tree/main/realtime-csv-importer) |
| [Realtime Fal.ai image generation](/guides/example-projects/realtime-fal-ai) | Generate an image from a prompt using Fal.ai and show the progress of the task on the frontend using Realtime. | Next.js | [View the repo](https://github.com/triggerdotdev/examples/tree/main/realtime-fal-ai-image-generation) |
+| [Resend email agent](/guides/example-projects/resend-email-agent) | An AI agent that drafts replies to a Resend inbox and waits for your approval in Slack before sending, using hosted webhooks and wait tokens. | — | [View the repo](https://github.com/triggerdotdev/examples/tree/main/resend-slack-email-agent) |
| [Smart Spreadsheet](/guides/example-projects/smart-spreadsheet) | Enrich company data using Exa search and Claude with real-time streaming results. | Next.js | [View the repo](https://github.com/triggerdotdev/examples/tree/main/smart-spreadsheet) |
| [Turborepo monorepo with Prisma](/guides/example-projects/turborepo-monorepo-prisma) | Use Prisma in a Turborepo monorepo with Trigger.dev. | Next.js | [View the repo](https://github.com/triggerdotdev/examples/tree/main/monorepos/turborepo-prisma-tasks-package) |
| [Vercel AI SDK image generator](/guides/example-projects/vercel-ai-sdk-image-generator) | Use the Vercel AI SDK to generate images from a prompt. | Next.js | [View the repo](https://github.com/triggerdotdev/examples/tree/main/vercel-ai-sdk-image-generator) |
diff --git a/docs/webhooks/sources.mdx b/docs/webhooks/sources.mdx
index d8f3a2ac97f..8481628d698 100644
--- a/docs/webhooks/sources.mdx
+++ b/docs/webhooks/sources.mdx
@@ -106,6 +106,8 @@ Supabase database webhooks aren't signed, so `supabase()` checks a shared secret
Slack also ships as a chat channel in `@trigger.dev/slack`.
+For a complete project built on `resend()`, see the [Resend email agent example](https://github.com/triggerdotdev/examples/tree/main/resend-slack-email-agent). It drafts replies to a Resend inbox and waits for your approval in Slack before sending them.
+
### Hookdeck
`hookdeck()` verifies requests that a [Hookdeck](https://hookdeck.com) connection forwards to the endpoint. Hookdeck forwards the original provider's body unchanged, so pass that provider's event type: