Approvals
Pause risky agent work for human review before a gated tool or sub-agent runs, then resume the same execution in place.
Approvals
Approvals enable human-in-the-loop workflows where an agent execution pauses before a sensitive action and waits for a human decision. This is essential for high-stakes operations — sending customer communications, moving money, modifying data — where an automated decision needs human oversight.
Human-in-the-Loop Overview
In API v2 approvals are execution-scoped. A tool or sub-agent attached to an agent version with requires_approval causes the execution to pause at waiting_approval right before that call runs, instead of proceeding automatically.
Approving resumes the same execution and lets the gated call proceed. Denying resumes the execution with a denial the agent must handle — nothing is discarded, and the run continues to a normal terminal state.
Requiring Approval
Approval gating is configured per attachment on the agent version. Set requires_approval on a tool or sub-agent, and set an approval_policy to control who may decide.
Technical detailsGate a tool and set the approval policy
from promptrails import (
PromptAgentConfig,
ApprovalPolicy,
ToolAttachment,
)
client.agents.create_version(
agent_id="your-agent-id",
version="1.1.0",
config=PromptAgentConfig(prompt_id="your-prompt-id"),
tools=[ToolAttachment(mcp_tool_id="send-email-tool", requires_approval=True)],
approval_policy=ApprovalPolicy(mode="admins"),
set_current=True,
message="Require approval before sending customer email",
)| Field | Description |
|---|---|
tools[].requires_approval | Pause the execution before this tool call runs |
sub_agents[].requires_approval | Pause before delegating to / handing off to this sub-agent |
approval_policy.mode | Who may decide: admins (default), assigned, or any_member |
approval_policy.member_ids | Specific members allowed to decide when mode is assigned |
Technical detailsApproval lifecycle and API details
Approval Flow
1. Execution Reaches a Gated Call
When the agent is about to run a tool or sub-agent marked requires_approval, the execution:
- Sets its status to
waiting_approval - Records
approval_expires_at(when the pending decision lapses) - Fires a webhook event (
execution.waiting_approval)
2. A Human Reviews
Paused runs surface in:
- The PromptRails dashboard (Approvals page)
- The execution-scoped approval inbox (
/api/v1/executions/approval-inbox) - Webhook notifications
The reviewer sees the agent, the execution input and progress so far, the pending call, and the expiry.
3. Decision
Approve or deny the paused execution. The endpoints are execution-scoped:
# List runs parked at waiting_approval
inbox = client.executions.approval_inbox()
for execution in inbox.data:
print(execution.id, execution.agent_id, execution.approval_expires_at)
# Approve — resumes the run and lets the gated call proceed
client.executions.approve("execution-id", reason="Response looks accurate")
# Deny — resumes the run with a denial the agent must handle
client.executions.deny("execution-id", reason="Do not send external email")JavaScript SDK
const inbox = await client.executions.approvalInbox()
for (const exec of inbox.data) {
await client.executions.approve(exec.id, { reason: 'looks good' })
// or: await client.executions.deny(exec.id, { reason: 'denied' })
}Go SDK
inbox, _ := client.Executions.ApprovalInbox(ctx, nil)
for _, exec := range inbox.Data {
_, _ = client.Executions.Approve(ctx, exec.ID, &promptrails.DecideParams{Reason: "looks good"})
// or: client.Executions.Deny(ctx, exec.ID, &promptrails.DecideParams{Reason: "denied"})
}4. Execution Continues
- Approved: the gated call runs and the execution proceeds to
completed(orfailed). - Denied: the agent receives the denial and continues without the gated call, reaching a normal terminal state.
Related Execution Fields
| Field | Type | Description |
|---|---|---|
status | string | waiting_approval while paused |
approval_expires_at | timestamp | When the pending decision lapses |
parent_execution_id | KSUID | Set when the gated call is a child in the tree |
trace_id | string | Link to the execution trace |
See Executions for the full execution tree and status model.
Webhook Notifications
When an execution pauses or a decision is made, webhook events fire:
| Event | Description |
|---|---|
execution.waiting_approval | An execution is paused for approval |
execution.approved | A paused execution was approved |
execution.denied | A paused execution was denied |
These can notify reviewers via Slack, email, or other channels.
Best Practices
- Gate the risky call, not the whole agent — Mark only the sensitive tool or sub-agent with
requires_approvalso routine steps are not blocked. - Choose the right policy — Use
adminsfor high-stakes actions andassignedwithmember_idswhen specific reviewers own a workflow. - Watch the expiry —
approval_expires_atprevents stale approvals from blocking the pipeline; set up webhook notifications so reviewers act in time. - Give reviewers context — Ensure the execution input and progress carry enough information to make an informed decision.
- Always provide a reason — Record a reason when denying to help improve the agent.
Related Topics
- Agents — Attaching tools and sub-agents to agents
- Agent Versioning —
requires_approvalandapproval_policy - Executions — Execution status, trees, and the approval inbox
- Agent Triggers — Trigger-driven executions with approvals