Human Approval
Pause or gate an agent action before it performs a sensitive operation. Use approvals for actions that are non-reversible, expensive, high-impact, or externally visible: sending messages, making API writes, granting access, deleting data, or processing refunds.
ZenSearch has three approval-like paths. They look similar in the UI, but they are routed differently.
| Path | When it is requested | Who can decide | Where it appears |
|---|---|---|---|
| Automatic policy approval | A tool call matches a team policy, risk threshold, or the built-in T3+ default | Team admins and owners | Originating web, Slack, or Teams conversation, plus the Governance queue |
| Delegated human approval | The agent explicitly calls delegate_to_human for a specific proposed action | The resolved approver or a team admin/owner, depending on surface | Email, Slack DM when configured, and Governance web link |
| Tool confirmation | A write tool is marked as requiring confirmation before execution | The user confirming the current chat proposal | Current chat card only |
Automatic policy approvals
Before each tool execution, ZenSearch evaluates governance policy for the team. A tool requires approval when:
- An explicit tool policy for that team and tool says
require_approval. - The tool's risk tier is at or above the team's configured approval threshold.
- No threshold is configured and the tool's built-in risk tier is
T3or higher. - The tool is unknown or dynamically loaded, which defaults to
T4unless a team policy overrides it.
When this happens, ZenSearch creates a durable approval request, saves a resumable checkpoint, and pauses the run. If the request is approved, the checkpoint resumes and the approved tool call continues. If it is denied or expires, the action does not run.
Automatic policy approvals are not routed through the delegated approver resolver. They are decided by team admins or owners from the originating chat surface or from Governance.
Delegated human approvals
Agents also have a built-in delegate_to_human tool that lets them say: "I'm about to do X — should I?" Use this when the agent has already chosen the real action and concrete parameters, but wants a human to sign off before proceeding.
When delegate_to_human is called, the run pauses, an approval request is recorded, and ZenSearch resolves who should be notified. The agent does not consume further model calls or take the proposed action while paused.
When the approver responds:
- Approve → the agent resumes with the decision in context and continues from the checkpoint.
- Deny → the paused run terminates without taking the proposed action.
- No response by the deadline → the run times out with an approval-deadline failure.
The pause is durable. If the platform restarts during a paused state, the request remains visible and the checkpoint can still resume when the decision arrives.
Where approvals are decided
| Surface | Applies to | Notes |
|---|---|---|
| Web chat card | Automatic policy approvals and local tool confirmations | Shown in the conversation that triggered the gate. |
| Slack or Teams conversation card | Automatic policy approvals from those bot surfaces | Team admins and owners can approve or deny from the originating conversation. |
| Slack DM | Delegated human approvals | Sent to resolved approvers when the team Slack app and approver identity link are available. |
| Email reply | Delegated human approvals | Approver can reply to signed one-time approve/deny addresses when inbound approval replies are configured. |
| Governance dashboard | Durable approval requests | Approval links open /governance?approval_id=<id> and focus the request. |
You do not have to pick one delegated surface. ZenSearch attempts every configured delivery channel for the resolved approvers, and the first valid decision wins.
Picking the delegated approver
Delegated approvals are resolved at the moment the agent pauses, in this order:
- Explicit approver UUID from the
preferred_approvertool parameter. - Preferred approver email from
preferred_approverwhen it matches a member of the team. - Service owner + current on-call when
proposed_actionreferences a knownconnector_idorcollection_idand that service's owning team has an active mapped on-call user. - Requester's manager from the org chart.
- Team owners as the final fallback.
Each fallback is optional. If a step has no match, the resolver skips it and tries the next one. See Approval Routing for setup.
Configuring delegated approval steps
In the agent prompt or automation config, instruct the agent to call delegate_to_human immediately before the action you want to gate. A simple example:
Before sending any external email or making any write API call,
delegate to a human for approval. Provide:
- reason: a one-line summary of why approval is needed
- proposed_action: {"tool": "the_real_tool", "params": {...}}
- deadline_hours: how long the approver has
- preferred_approver: optional user UUID or team-member email
Make proposed_action specific enough for a human to decide without rereading the whole run. If the action targets a connector or collection and you want on-call routing, include its ZenSearch connector_id or collection_id inside proposed_action or its nested params object.
You can also set a platform default deadline. Delegated approvals without an explicit deadline_hours use that default, usually one business day.
Limits and behavior
- Resume budgets: approved resumes get a fresh budget allowance. Automations can cap resume attempts to prevent unbounded chains.
- Single decision: the first valid decision wins. Later button clicks or replies become no-ops.
- Bound reply tokens: email reply addresses include signed single-use tokens bound to the intended approver's email address and approval deadline.
- Audit trail: approval request, decision, timestamp, decision reason when available, and linked tool action are visible from Governance and run traces.
- Automation behavior: approval denial fails the paused automation run; approval expiry marks it timed out.
Best practices
- Only gate the narrow action that needs a human — wrapping the entire run in an approval breaks the agent's ability to research and plan freely.
- Make the
proposed_actionfield specific. "Send an email" is bad; "Reply to acme.com saying we'll refund $250 to invoice #4521" is good. The approver should be able to decide without re-reading the run history. - Pick a realistic deadline for the surface you use. Slack approvals turn around in minutes; email approvals can stretch overnight.
- Pair with shadow-mode automations before a sensitive action goes live so you can confirm the approval prompt is what you want.
Related
- Approval Routing — how approvers are resolved
- Agents — overall agent framework