# Pause workflows for approval with Chat SDK

**Published:** August 6, 2026 | **Authors:** Ben Sabic

---

You can build human-in-the-loop approvals with Chat SDK through the new `chat/workflow` subpath. One `requestApproval` call posts a card with Approve and Deny buttons and suspends a [Workflow SDK](https://workflow-sdk.dev) workflow until someone decides.

![slack message lm desktop](//images.ctfassets.net/e5382hct74si/3EthhZErvh7EZgkGLyJuRo/845c57ed64660c9a1994efc677f0a2e1/Slack_message-3.png)

The wait can last seconds or days and survives deploys and restarts. You don't need an approvals table, an `onAction` handler, or a polling loop:

**lib/bot.ts**
```typescript
import { requestApproval } from "chat/workflow";
import type { Thread } from "chat";

export async function deployApproval(opts: { thread: Thread; version: string }) {
  "use workflow";

  const { approved, user, timedOut } = await requestApproval(opts.thread, {
    title: `Deploy Website?`,
    fields: { Version: opts.version },
    timeout: "24h",
  });

  if (approved) {
    await deploy(opts.version);
  }
}
```

Start the workflow from any handler, and `Thread` instances serialize across the workflow boundary automatically. The card handles the rest:

- **Scoped approvers: **Pass `approvers` to restrict who can decide. Clicks from anyone else post a notice, and the workflow keeps waiting.
- **Verified decisions: **Chat SDK checks the platform's signature on every click, so the `user.id` on the result is the person who decided.
- **Audit trail: **Once a decision lands or the timeout elapses, the card is edited in place with an outcome line, preventing stale clicks.

Get started by reading the [approvals documentation](https://chat-sdk.dev/docs/approvals).

---

📚 **More updates:** [View all changelog entries](/changelog/sitemap.md) | [Blog](/blog/sitemap.md)