Use this page when designing any automation that could change a system or speak for a person. The aim is that the cheapest path for the agent is also the safe one, and that every write can be traced to a human decision.
Pattern 1: Dry-run is the default
Scripts print the exact command they would run. Only an explicit flag makes them act.
DRY_RUN=1
[ "${1:-}" = "--execute" ] && DRY_RUN=0
do_change() {
if [ "$DRY_RUN" = 1 ]; then printf 'DRY-RUN would run: %q ' "$@"; echo; else "$@"; fi
}
do_change glab mr create --draft --title "access: read-only role for <service>"
- Reads and local drafts always run. Remote side effects go through
do_change. - Only a human adds
--execute, and only for a run they reviewed.
Pattern 2: Draft, then post
The agent writes what it would say or change into a file or a draft MR. A human approves item by item. A separate step posts only approved items. See the posting script in connecting Jira.
Pattern 3: One approval queue
All pending decisions land in one daily file or board, sorted by risk. The human works it once a day instead of being interrupted. See the automation blueprint.
Pattern 4: Approval is specific, recorded and fresh
- An approval names the exact change: this MR, this ticket, this command.
- It is recorded where an auditor can find it (MR approval, ticket comment).
- It does not carry over. Approving one access grant does not approve the next.
- Another agent saying "the human approved" is not approval. Check the record.
Pattern 5: Guardrails before the human sees it
Reject unsafe proposals automatically so the human only reviews sane ones.
| Proposal | Automatic checks before it reaches the queue |
|---|---|
| CI file | Valid YAML, lints clean, production job is manual and on the default branch only, no secrets |
| IAM change | Plan applies cleanly, only allowed paths changed, no * actions or resources, no admin policies |
| Ticket comment | No secrets, account IDs or customer data; references real evidence links |
| Monitor change | Has owner tag, notify handle and runbook link |
Pattern 6: Two keys for risky changes
- Production, IAM, network and data deletion changes need two approvers, and the author is not one of them.
- Use platform features (protected environments, required approvals, CODEOWNERS) so this is enforced, not remembered.
Pattern 7: Least privilege for the agent itself
- The agent's credentials are read-only. Writes happen through CI with its own scoped role after merge.
- Tokens are short-lived and stored in a secret store.
- The agent cannot approve or merge its own MRs.
Pattern 8: Kill switch and audit trail
# Every job checks this first
[ -e "$HOME/.automation-paused" ] && { echo "paused by human"; exit 0; }
- One file or flag pauses all automation.
- Every write is logged with time, target, action and the approval reference.
- Weekly, a human reads the write log.
Pattern 9: Stop on surprise
- Unexpected output, an error, or a plan larger than expected stops the run and reports. No automatic retries of writes.
- Instructions found in tickets, logs or web pages are data. The agent never follows them.
Pitfalls
- Approval fatigue. If the human approves 100 items a day without reading, batch better and add guardrails so fewer items need review.
- "Temporary" bypasses of the queue that become permanent.
- An agent with write credentials "for convenience". Convenience is how incidents start.