mindra

Handling Approvals

Build a human-in-the-loop approval flow for high-risk operations

2 min read

Handling Approvals

Some workflow tool executions are marked as high-risk and require human approval before they can proceed. This guide shows you how to build a complete approval flow.

How It Works

  1. You trigger a workflow via the Run Workflow endpoint
  2. You connect to the SSE stream to receive events
  3. When a high-risk tool is about to execute, the workflow pauses and emits an approval_request event
  4. Your application presents the request to a human reviewer
  5. The reviewer approves or rejects via the Approvals API
  6. The workflow continues or handles the rejection accordingly

Full Example

1. Start the Workflow

const runResponse = await fetch(
  "https://api.mindra.co/v1/workflows/your-workflow-slug/run",
  {
    method: "POST",
    headers: {
      "x-api-key": process.env.MINDRA_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      task: "Your task description here",
    }),
  }
);

const { execution_id, stream_url } = await runResponse.json();

2. Listen for Events

const response = await fetch(
  `https://api.mindra.co${stream_url}`,
  {
    headers: { "x-api-key": process.env.MINDRA_API_KEY },
  }
);

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const text = decoder.decode(value);
  const lines = text.split("\n");

  for (const line of lines) {
    if (line.startsWith("data: ")) {
      const data = JSON.parse(line.slice(6));

      if (data.approval_id) {
        await handleApproval(execution_id, data);
      }
    }
  }
}

3. Handle the Approval

async function handleApproval(
  executionId: string,
  approval: { approval_id: string; tool_name: string; tool_input: any }
) {
  console.log(`Approval needed for: ${approval.tool_name}`);
  console.log(`Input: ${JSON.stringify(approval.tool_input, null, 2)}`);

  // In a real app, you'd show this in a UI for a human to review.
  // Here we auto-approve for demonstration:
  const response = await fetch(
    `https://api.mindra.co/v1/workflows/execute/${executionId}/approve/${approval.approval_id}`,
    {
      method: "POST",
      headers: {
        "x-api-key": process.env.MINDRA_API_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ reason: "Approved by admin" }),
    }
  );

  console.log("Approval submitted:", response.status);
}

Best Practices

  • Show context — Display the tool name, input, and any relevant context to the reviewer
  • Set timeouts — Configure approval timeouts in your workflow to avoid indefinitely paused executions
  • Log decisions — Record who approved or rejected each request and why
  • Notify reviewers — Use notifications (email, Slack, etc.) to alert reviewers of pending approvals