Docs navigation
Get started
AI agents
Connect
Operate
Day to day
When it breaks
Govern access
Team & account
Access
Identity concepts
Provider guides
Account
Policies & approvals
Every run dispatch passes through your account's policy before it's sent to a runner. The policy makes one of three decisions: run it, pause it for approval, or deny the execution.
How a decision is made#
Each pack action declares its risk tier — neither the caller nor the control plane can change it. A policy then decides whether the run is dispatched, paused for approval, or denied.
The policy is selected by scope, most specific first: the runner's own ruleset, then its group's, then the account default.
A policy can define per-action overrides. It walks the ordered list of action ID
patterns — for example,
nomad.job_*
requires approval,
*.delete_*
denies. The first match wins, so put the most specific patterns first.
If no override matches, the action's risk tier defaults
(low / medium / high /
critical) make the decision. In the policy these decisions are
>allow, require_approval,
and deny. When the policy cannot answer — a missing
policy, an unknown tier — it denies.
A sensible first policy#
Keep the shipped defaults, then add overrides where real use shows you need them:
- Run a week with the defaults. Watch the Approvals queue — the requests that keep showing up are your override candidates.
-
Deny anything you never want an agent to touch
(
*.purge_*→deny) — a written rule beats everyone remembering. -
Turn repeated approvals into expiring standing grants instead of
allowoverrides — a grant stays tied to one key and expires on its own.
An override can also remove waiting. Some reads are high risk because their output can leak secrets — a full config dump may contain a credential — so the shipped policy holds them for a person. If your configs hold no secrets, or the exposure is acceptable, allow the action:
overrides: - name: allow-journal-reads action: linux.journalctl* decision: allow - name: allow-nginx-config-dump action: nginx.config_dump decision: allow
Redaction still masks credential patterns it recognizes, but it can miss — treat the output as sensitive when you allow a full dump.
Editing the policy#
Open Policies in the console sidebar. Owners and admins can edit; operators and viewers can read. The editor shows the four tier menus above the ordered override list. A higher tier can never be more permissive than a lower one — the editor and the API both refuse it.
The preview runs your edited rules against the scope's real catalog, so you see each action's decision before saving.
Saving a change bumps the policy version and applies from the next dispatch. Every save writes an audit event, and every run records the policy version that gated it — so you can always see which rules were in force.
Scope it to a runner or group#
The default policy governs the fleet. When one runner or group needs different rules — a locked-down database host, a permissive staging group — add a targeted ruleset for it in Policies.
A ruleset replaces the default policy for its runner or group — what you see for a scope is exactly what runs there. Remove it and the scope falls back to the next-broader policy.
Give the staging
group a ruleset that sets every tier to
allow
with no approvals. An agent can reproduce a bug, test a fix, and verify the result
without waiting — and the production change it hands you is still held for approval
by your stricter default.
Approvals#
When the decision is require_approval, the run is
held and an approval request is created. Owners, admins, and operators get an email
with a direct link, and the request appears under Approvals
in the console with a live badge.
- — One approval releases a run by default. For destructive work, require two approvers with self-approval off — the requester cannot approve their own request.
- — If an action or pack is unavailable, the decision panel explains the block. After restoring it, choose Recheck. Your note and reuse choices stay in place. Rechecking does not approve the request or switch it to a newer pack version.
- — If the required reviewers are unavailable, an owner or admin can use Approve with override. They must give a reason; it is recorded with the decision. The exception waives the missing reviews and, when necessary, the self-approval rule; it creates no standing grant and gets its own audit record. Scope, expiry, cancellation, pack trust, dispatch signatures, initiator access, and runner admission still apply.
- — Undecided requests expire after 24 hours and the held run is cancelled.
-
—
An LLM waiting on an approval long-polls
wait_for_runand picks the result up the moment a human decides. - — Each vote and final decision is audited with its approver, run ID, decision, and reason. Follow the run ID for the requester, action, arguments, and dispatch reason.
Standing grants#
Approving the same
nomad job revert
for each of 20 allocations helps nobody. Approval applies to
This run only
by default. When standing grants are enabled, choose
Allow the agent to reuse this approval
and a duration allowed by your account
so matching future calls skip the queue:
- — Scoped tight. A grant is bound to one API key and action, and optionally one runner. When you approve, choose whether it covers only these exact arguments or any arguments.
- — Capped and revocable. A grant can carry a use limit, always expires, and is listed under Approvals where you can choose Revoke and confirm to end it early. Every use is still a fully audited run.
The reason requirement#
Every dispatch — console or MCP — must include a reason.
Approvers see it, and the run and audit event keep it. For an agent, the reason says
why it ran nomad job revert;
the action name only says what.
An MCP caller can also send
evidence
— prior findings or run IDs that informed the call — and
expected
— the outcome that confirms success. Together with the reason, they preserve what the
agent saw, why it acted, and what it expected. Operator and runbook dispatches leave
both empty.