Approvals
When policy resolves to a hold, the call pauses and a person is asked. The request shows exactly what will happen, and the agent's run stays alive until it is answered.
The alternative to autonomy is not oversight — it is a human copying commands out of a chat window, which produces no record and does not scale. Approval has to live inside the execution path or it becomes theatre.
A hold is not a failure
What the approver sees
The resolved arguments, the diff or query, the environment, the agent, its owner, and the policy that raised the hold — never a summary standing in for the real request.
Cirvix · approval required APP Agent deploy-bot (agt_3H8N1P) Owner marcus@example.com Action k8s.apply → production/checkout Policy require-approval-prod-deploy Waiting 00:42 ── manifest diff ───────────────────────────── replicas: 3 → 5 image: checkout:1.9.2 → checkout:1.9.3 ────────────────────────────────────────────── [ Approve ] [ Deny ] [ Open in Cirvix ] Expires in 15m · escalates to #platform-oncallWhere approvals happen
- Slack
- Microsoft Teams
- A signed webhook
- The control-plane API, and the console
Working the queue over the API
$ curl -s $CIRVIX_API/v1/approvals -H "authorization: Bearer $TOKEN" $ curl -X POST $CIRVIX_API/v1/approvals/apr_4H2N/decide \ -H "authorization: Bearer $TOKEN" \ -H "content-type: application/json" \ -d '{"decision":"approved","reason":"release 1.9.3 signed off"}'Raising an approval needs decision:write — an agent does that. Deciding one needs approval:decide, which is admin-level. The two are deliberately different authorities, so an agent that can ask cannot answer.
Approvals are evidence
Who approved what, when, and against which policy is written into the audit chain as part of the decision record, not as a separate log someone has to correlate.
Limits
- Approval quality depends on the approver reading the request. Cirvix shows the resolved action specifically to make that reading possible, but it cannot make a person careful.
- A held call consumes a slot for as long as it waits. Timeouts and escalation exist so a forgotten request fails closed rather than hanging a run indefinitely.
