> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inferable.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Human in the Loop

> Learn how to implement human approval flows in your Inferable applications

Human-in-the-loop (HITL) allow you to require human approval before certain actions are executed. This is useful for:

* Reviewing and approving high-risk operations
* Validating model outputs before taking action

Inferable provides a simple API for creating approval requests and approving them. It accomplishes this by returning a special result type.

<Note>
  If you would like to send a notification *without* pausing the workflow, see [notifications](/pages/notifications).

  The `notification` input defined here is the same as what is passed to `ctx.notify()`.
</Note>

## Usage

The following example shows how to use the `Interrupt.approval()` function to pause a workflow and wait for human approval.

```typescript
import { Interrupt } from "inferable";

deleteUserWorkflow.version(1).define(async (ctx, input) => {
  // ... existing workflow code ...

  if (!ctx.approved) {
    return Interrupt.approval();
  }

  await db.customers.delete({
    userId: input.userId,
  });
});
```

## Approval Notifications

By default, the approval request will be created in the [Inferable app](https://app.inferable.ai). Unless a human explicitly approves or rejects the request, the workflow will be indefinitely paused.

### Notifications

Approval requests can also provide a notification destination to send the request to.

#### Email

<Note>Emails will be delivered from `no-reply@workflows.inferable.ai`</Note>

```typescript
deleteUserWorkflow.version(1).define(async (ctx, input) => {
  if (!ctx.approved) {
    return Interrupt.approval({
      message: `I need your approval to delete the user ${input.userId}. Is this ok?`,
      destination: {
        type: "email",
        // The email address to notify
        email: "test@example.com",
      },
    });
  }
  //...
});
```

### Slack

If enabled, the [Slack integration](/pages/slack) can also be used to notify users / channels of approval requests.

```typescript
deleteUserWorkflow.version(1).define(async (ctx, input) => {
  if (!ctx.approved) {
    return Interrupt.approval({
      message: `I need your approval to delete the user ${input.userId}. Is this ok?`,
      destination: {
        type: "slack",
        // The email address of the Slack user to notify
        email: "test@example.com",
        // Or Slack user ID
        userId: "U0123456789",
        // Or Slack channel ID
        channelId: "C0123456789",
      },
    });
  }
  //...
});
```

## Semantics

### Approval Flow

When `Interrupt.approval()` is returned from a Workflow:

1. The Workflow or Run is `paused`.

2. The approval request is created.

3. An authorized user must approve or reject the request using the API or the App UI.

4. If the approval is successful,

   4.1 The workflow will resume execution, and will call the handler again with the same input.

   4.2 At this point, since the `context.approved` is `true`, the handler will continue without entering the `return Interrupt.approval()` block.

5. If the approval is rejected

   5.1 The tool / workflow will be rejected. If this is a tool, the agent will be notified that the tool call was rejected.

### Pausing a Workflow

When a Workflow is paused, Inferable's durable execution engine will save the state and resume when the approval is resolved.

Since humans can take a long time to approve, the run or workflow can be paused for an indefinite amount of time. There's no theoretical upper limit on how long a run can be paused for.
