Human approval (human-in-the-loop) lets you mark, per credential, the operations that must not run on the credential's own authority. A marked operation does not execute: it becomes an approval request pinned to the exact call, a person with management access approves or denies it in the clientarea, and only then — re-submitted with the approval id — does the operation run. Once.
This exists for the customer who hands an AI agent a credential and still wants a person in front of the irreversible calls. Scopes decide what a credential may do at all; spend ceilings decide how much it may spend; this decides who says yes to the calls that matter.
The policy
A policy is configured per credential in the clientarea (API Management → Approvals), by the account owner. It names:
| Field | Meaning |
|---|---|
classes |
Operation classes to gate: destructive (delete, uninstall, terminate, cancel), spend (orders, upgrades, payments), security (rotate or revoke credentials, mint sub-credentials, export or rotate the .onion key, install the Impreza agent). |
operations |
Individual MCP tool names to gate, e.g. impreza_order_vps. |
ttl_minutes |
How long a request lives: 15–60 minutes, default 30. |
Default is off. A credential with no policy behaves exactly as before — existing credentials change nothing until the owner marks them. A sub-credential never loosens its parent: the effective policy is the union of the parent chain's policies, so a child inherits every requirement and can only add more, and tightening a parent later tightens every child with it.
What happens when an operation is marked
- The agent calls the operation. It does not run. The answer is a stable
approval_requiredresult with theapproval_id, the expiry, and the clientarea link — nothing was executed and nothing was changed. - A webhook event
agent.human_approval_requestedis queued for the account (throttled per credential, like the spend-ceiling notices). - A person approves or denies in API Management → Approvals. The page shows the operation, the credential, and a summary of the call. Argument values that could be secrets were never stored, so the page cannot show them.
- Once approved, the agent re-submits the same call with
approval_id="apr_…". The operation then runs. - Denied and expired requests also become webhook events
(
agent.human_approval_denied,agent.human_approval_expired).
The rules that make it safe
- Pinned to the exact call. The request stores a digest of the normalized arguments. Re-submit with any argument changed and the execution is refused — approving "uninstall dpl_a" approves exactly that, not "uninstall anything".
- Single use. Each approval executes exactly once. Two concurrent re-submissions race on an atomic claim and only one dispatches.
- A credential never approves. There is no API route and no MCP tool that approves, denies, or edits a policy. Decisions exist only as clientarea POSTs behind a session, a team permission and a CSRF token — so an agent cannot approve itself, through a sub-credential, or through an API key. Read-only members see the queue but cannot decide; only a person with the manage products permission can approve or deny, and only the owner changes policies.
- Independent of the other guards. The scope ladder, the two-step confirmation and the daily/monthly spend ceilings all still apply to an approved call. Human approval adds a check; it never removes one.
Plan-bound host request limits
The VPS reinstall pilot requires a separate owner grant for each credential, operation and server, followed by approval of the exact stored plan. Its request limit counts plans created over the last 24 hours across all servers for the credential, rather than starting a new counter for each server. The pending plan/operation limit uses the same shared scope. Denied, expired and completed requests still count toward the 24-hour request limit until they age out.
For a sub-credential, each credential in its parent chain is checked against its shared counts. The selected server grant and the strictest parent limits apply; plans requested by siblings also use the parent's allowance. Granting another server or increasing one server's limit does not reset these counters. A grant never replaces the human decision or permits an operation on another server.
Reading the state
- REST:
GET /v1/approvals(the queue),GET /v1/approvals/{approval_id}(one request),GET /v1/credentials/{id}/hitl-policy(a credential's stored and effective policy). All read-only. - MCP:
impreza_list_approvals,impreza_get_approvalandimpreza_get_credential_policy— the same reads for the agent, so it can tell you what is parked instead of blindly retrying. Approving is not a tool and never will be. - Minting:
impreza_mint_subcredential(andPOST /v1/credentials) accepts ahitl_policyat creation — it can only add requirements, never drop one the parent carries.
Audit trail
The per-credential activity extract (GET /v1/credentials/activity?format=csv,
or impreza_agent_activity) records the whole lifecycle next to the tool
calls: hitl:request, hitl:approve or hitl:deny with who decided,
hitl:execute when the approved call ran, and hitl:expire. Secret values and
sensitive parameters are never written — the rows carry identifiers only.
Revoking plan-bound host permissions
The account owner can revoke the VPS reinstall pilot's explicit host grant even while the owned server is suspended. The credential must still be active and owned by the account. New or renewed grants require an active server.
Reactivation does not undo a revocation. The revoked marker stays stored, so the credential cannot fall back to the legacy reinstall route. A previously approved plan is refused before dispatch. Restoring permission requires a new explicit owner grant after the service is active again; it does not revive an older plan. Revocation does not cancel an operation already submitted to the provider, whose receipt can still be reconciled without restoring the old grant.