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

# Human approval

> Pause agent execution when a guardrail requires human approval in the Ratri dashboard.

A guardrail flags an MCP tool your agent has never called in production. Instead of blocking outright, your policy requires human approval. The agent pauses, an approval request appears in the dashboard, and execution resumes only after someone approves or rejects.

When you finish this page, you'll understand the approval flow, timeouts, and how to handle approval in both SDK and MCP proxy paths.

## How approval works

1. Guard evaluates an action → decision is `require_approval`
2. Ratri emits `agent.approval.requested`
3. SDK polls the dashboard via `approvals.wait()`
4. Human approves or rejects in the Ratri dashboard
5. Ratri emits `agent.approval.resolved`
6. If approved, the callback proceeds; if rejected or timed out, an error is thrown

This only blocks in **Enforce mode**. In Monitor mode, approval requirements are logged but execution proceeds.

## Configure timeout

Default approval wait is 5 minutes. Adjust with `approvalTimeoutMs`:

<CodeGroup>
  ```ts TypeScript theme={null}
  const ratri = new Ratri({
    approvalTimeoutMs: 600_000, // 10 minutes
  });
  ```

  ```python Python theme={null}
  ratri = Ratri.create({"approval_timeout_ms": 600_000})
  ```
</CodeGroup>

## Automatic approval in withTool

When Enforce mode is active and a policy decision is `require_approval`, `withTool` handles the full flow automatically — you don't call `approvals.wait()` manually.

<CodeGroup>
  ```ts TypeScript theme={null}
  // In Enforce mode — approval is automatic inside withTool
  await ratri.withTool(
    {
      runId: run.id,
      tool: { name: "unknown_mcp_tool", riskLevel: "high" },
      action: { type: "execute", name: "unknown_mcp_tool" },
      resource: { type: "file", environment: "production" },
    },
    async () => mcpClient.callTool("unknown_tool", {}),
  );
  ```

  ```python Python theme={null}
  ratri.with_tool(
      {
          "runId": run.id,
          "tool": {"name": "unknown_mcp_tool", "riskLevel": "high"},
          "action": {"type": "execute", "name": "unknown_mcp_tool"},
          "resource": {"type": "file", "environment": "production"},
      },
      lambda: mcp_client.call_tool("unknown_tool", {}),
  )
  ```
</CodeGroup>

### What you'll see

A pending approval in the Ratri dashboard with the action details, matched guardrail, and approve/reject buttons. After resolution, the run timeline shows the approval requested and resolved events.

## Manual approval polling

For custom flows, poll approval status directly:

<CodeGroup>
  ```ts TypeScript theme={null}
  const status = await ratri.approvals.wait({
    approvalId: "appr_123",
    timeoutMs: 300_000,
  });
  // status: "approved" | "rejected" | "expired" | "cancelled" | "timeout"

  const current = await ratri.approvals.getStatus("appr_123");
  ```

  ```python Python theme={null}
  status = ratri.approvals.wait({"approvalId": "appr_123", "timeoutMs": 300_000})

  current = ratri.approvals.get_status("appr_123")
  ```
</CodeGroup>

## MCP proxy approvals

In MCP proxy Enforce mode, approval-required tool calls are blocked at the proxy layer. The MCP host receives JSON-RPC error `-32002` if approval is denied or times out.

Configure approval timeout in `ratri.mcp.json`:

```json theme={null}
{
  "agentKey": "my-agent",
  "mode": "enforce",
  "approvalTimeoutMs": 600000,
  "upstream": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"] }
}
```

See [MCP enforcement recipe](/recipes/mcp-enforcement).

## Approval statuses

| Status      | Meaning                              |
| ----------- | ------------------------------------ |
| `approved`  | Human approved — execution proceeds  |
| `rejected`  | Human rejected — execution throws    |
| `expired`   | Approval window expired in dashboard |
| `cancelled` | Approval was cancelled               |
| `timeout`   | SDK wait timed out before resolution |

## Next steps

<CardGroup cols={2}>
  <Card title="MCP enforcement" icon="plug" href="/recipes/mcp-enforcement">
    Enforce mode + approval through MCP proxy.
  </Card>

  <Card title="Enforce guardrails" icon="shield" href="/guardrails/enforce-guardrails">
    Configure Enforce mode and failure handling.
  </Card>
</CardGroup>
