Approvals (human-in-the-loop)

Require human sign-off before an agent runs a sensitive tool.

Some tool calls are too consequential to run unsupervised: sending an email, writing to a CRM, moving money. Rightbrain lets you put a human in the loop on a per-tool basis. When a gated tool is called, the run pauses, an approval request is raised, and the agent only continues once a person approves it. This is the difference between an agent that can use tools and one that can be operated inside an organization.

Approvals are configured on the agent revision, so they are versioned alongside the rest of the agent’s wiring. Changing an approval policy creates a new revision, and rolling back restores the previous policy. See Versioning & revisions.

Per-tool action controls

Every tool attached to an agent revision — a Task, an integration tool, an MCP tool, or a registered tool — carries an action control with two settings:

action_mode
'auto_run' | 'require_approval'Defaults to auto_run

auto_run lets the agent call the tool without interruption. require_approval pauses the run and raises an approval request before the tool executes.

rejection_behavior
'end_run' | 'return_rejection_to_model'Defaults to end_run

What happens when a request is rejected. end_run stops the run and marks it failed. return_rejection_to_model returns the rejection to the agent so it can reconsider and try a different approach.

You set these by configuring the tool action controls on the agent revision — over the API, or in the dashboard, where each tool in the agent’s tool list carries its own approval setting.

Reach for return_rejection_to_model when you want a reviewer to redirect the agent (“don’t email this customer, log a note instead”) rather than abort the whole run. Use end_run for hard stops.

Gate selectively

The point of per-tool controls is that you gate the side effect, not the whole agent. Attach every tool an email agent needs — read the inbox, look up the customer, draft the reply, send it — but leave the reads and the draft on auto_run and set only the send tool to require_approval. Reading and drafting are preparatory and safe to run unattended; sending is the irreversible step a person should sign off on. The agent works right up to the edge of the consequential action, then waits.

What happens during a run

When an agent calls a tool set to require_approval:

1

The run pauses

The run status becomes waiting_for_human. The agent stops before the tool executes.

2

An approval request is raised

Rightbrain creates an approval request holding the tool and its arguments. The arguments are encrypted at rest.

3

A human reviews it

A reviewer approves or rejects the request from the dashboard or the API.

4

The run resumes

On approval the tool executes and the run continues. On rejection the run follows the tool’s rejection_behavior. Resumed runs keep their session and any files intact — nothing is lost across the pause.

Run statuses move through runningwaiting_for_humancompleted or failed. A single run can pause and resume multiple times if it calls more than one gated tool.

Finding and resolving requests

List approval requests project-wide, or scope them to a single agent:

PurposeEndpoint
List all pending requests in a projectGET …/task-agent/approval-request
List requests for one agentGET …/task-agent/{agent_id}/approval-request
Get a single requestGET …/task-agent/{agent_id}/approval-request/{id}
ApprovePOST …/task-agent/{agent_id}/approval-request/{id}/approve
RejectPOST …/task-agent/{agent_id}/approval-request/{id}/reject
Resume a paused runPOST …/task-agent/{agent_id}/approval-request/{id}/resume

All paths are under https://app.rightbrain.ai/api/v1/org/{org_id}/project/{project_id}.

List and approve a request

$curl https://app.rightbrain.ai/api/v1/org/$ORG_ID/project/$PROJECT_ID/task-agent/approval-request \
> -H "Authorization: Bearer $RB_API_KEY"

The approve, reject, and resume endpoints all require a JSON body. Send an empty object ({}) when you have nothing to add; approve and reject both accept an optional decision_note.

Approving records the decision — it does not by itself continue the run. Call the /resume endpoint next to execute the approved tool and carry the run to completion; /resume streams the remainder of the run as Server-Sent Events, just like the original run call. To reject instead, call the /reject endpoint — the run then follows the tool’s rejection_behavior.

Approve (or reject) and resume are separate operations: the decision is auditable on its own, and the resume replays into the same session with the run’s files intact. When a reviewer acts in the dashboard, both steps happen from the same screen.

The approval audit trail

Every approval decision is part of the run’s permanent record. A completed run carries the IDs of the approval requests it raised (approval_request_ids) and the embedded requests themselves (approval_requests) — each with its status, the tool it gated, who requested it (requested_by_user_id), who decided it (decided_by_user_id), and any decision_note the reviewer left. If a rejection ended a run, the run’s termination_reason records why.

Crucially, the trail records the decision, not the payload: the tool arguments and any credentials are never embedded in it. You get a defensible record of who approved what, without leaking the sensitive data that was under review. See Observability & audit.

Human review

Reviewers don’t have to work the API directly: pending approvals surface in the agent’s run view in the dashboard, where a reviewer sees the tool the agent wants to call and the arguments it intends to pass, and can approve or reject in place. Because approvals are part of the agent revision, the same policy applies to every run of that revision — whether it was triggered by an API call, a webhook, a schedule, or a Gmail inbox message.