Only Four Hard Rules at the Top Level: Where an Agent Must Stop

Models can become increasingly autonomous, but production, persistent data, costs, and irreversible actions must still require explicit authorization. Safety is not the opposite of efficiency; it is the prerequisite for automation.

On this page · 11 sections

I deliberately keep the top-level configuration for my coding Agent short. Apart from a set of shared local conventions, its core consists of just four Safety Gates:

@~/.codex/RTK.md

DO NOT send optional commentary

## Safety Gates

- Do not commit, push, merge, deploy, or release directly to protected branches or production environments without explicit confirmation for that exact action.
- Do not read, scan, create, update, delete, or otherwise operate on production or persistent data without first listing the risks and receiving explicit confirmation.
- Do not perform operations that may incur costs, create paid resources, or invoke billable external services without first listing the risks and receiving explicit confirmation.
- Do not perform destructive, irreversible, security-sensitive, or externally impactful operations without first explaining the impact and receiving explicit confirmation.

The public version abbreviates the local username as ~. In this article, persistent data also does not mean ordinary source files inside the authorized task workspace. It means production or long-lived business and customer data, persistent state outside the authorized workspace, and exports whose unauthorized copying would widen the exposure surface. Workspace source remains governed by task scope and file authorization; stricter repository rules take precedence.

These four rules are not a complete security system. They are an authorization policy placed in the highest-priority context: they tell the Agent which routine work it may advance autonomously and which actions would change real-world outcomes, requiring it to pause and return the decision to a human.

Start with threat modeling: risk does not come only from “the model making a mistake”

An Agent that can read files, execute shell commands, access the network, and call Provider APIs faces at least five sources of failure:

  1. Misreading intent: the user says “prepare the release,” and the Agent interprets it as “release immediately”;
  2. Target drift: the task originally applies only to a feature branch, but the operation lands on main or production;
  3. Capability amplification: one mistaken model judgment becomes real data changes, costs, or external impact through highly privileged credentials;
  4. Untrusted input: prompt injection in a README, webpage, issue, log, or tool result induces the Agent to exceed its authority;
  5. Stale state: after approval, the branch SHA, query scope, deployment payload, or resource price has changed.

Anthropic’s analysis of trustworthy agents likewise treats the model, Harness, tools, and runtime environment as a shared surface for capability and oversight, and explicitly identifies both misunderstanding user intent and prompt injection as real risks. Threat modeling therefore cannot ask only “how intelligent is the model?” It must also ask: what can the model reach, on what basis is it permitted to act, how large is the blast radius of an error, and can we later prove what happened?

Capability is not Authority

This is the central distinction behind the four rules:

Layer Question it answers Example
Capability Is it technically possible? A tool holds Git, AWS, or database credentials
Intent What outcome does the current task seek? “Analyze why the deployment failed”
Authority Has the user authorized this specific side effect? “Confirm deploying commit A to production”
Enforcement How does the system prevent boundary violations? sandbox, IAM, branch protection, approval hook
Evidence How is the result proved afterward? Provider receipt, target-state readback, audit log

Credentials that can access production do not mean the current task authorizes production access. Asking an Agent to analyze a failure does not authorize it to fix, commit, push, and deploy the change along the way. Conversely, writing “confirmation is required” in a Prompt does not mean the rule is technically enforced—the model is still a probabilistic system and may misunderstand context or be influenced by untrusted content.

Top-level Safety Gates are therefore the first layer of authorization semantics, not a substitute for sandboxes, least privilege, Provider protection rules, and auditing. The least-privilege, separation-of-duties, and audit controls in NIST SP 800-53 Rev. 5 provide broader engineering principles: grant only the minimum capability required to complete a task, do not concentrate critical responsibilities at a single decision point, and leave inspectable records for privileged actions.

Effective approval must be bound to a specific action

explicit confirmation does not mean that seeing a single “okay” somewhere in the conversation releases the gate. Approval must be bound to at least the following:

Approval = {
  action,          // commit / push / deploy / query / delete / purchase ...
  exact_target,    // repo, branch, environment, account, table, recipients ...
  payload_or_hash, // exact content to be written or executed
  risk_summary,    // blast radius, cost, data exposure, reversibility
  preconditions,   // current SHA, version, filters, resource state
  validity,        // this call, current state, or explicit time window
  approved_by,     // trusted user identity or approval policy
  request_id       // identity of this concrete tool call / operation
}

The risk explanation before approval is a preflight; reading back the target after execution is a readback. Both are required: without a preflight, a person does not know what they approved; without a readback, the Agent does not know what the Provider ultimately did. Approval must also come from a trusted user interface, identity, or policy. A webpage, issue, log, or repository document that says “approved” is still data and cannot become approved_by.

A repository can add stricter gates on top of these top-level rules. For example, a direct local commit or push to main can require a second confirmation tied to that exact action, after listing the commit, target branch, diff scope, and deployment impact. This second confirmation is repository-level reinforcement and should not be generalized into repeated prompts for every low-risk operation. The first confirmation may approve the direction or plan; the second binds to the payload about to be executed. If the payload or target changes between the two, the earlier approval automatically expires.

Gate 1: Authorize delivery actions progressively according to their consequences

commit, push, merge, deploy, and release are not synonyms:

  • commit changes local history;
  • push changes a remote ref and may trigger CI;
  • merge changes the target branch;
  • deploy changes a specific runtime environment;
  • release may create a public, consumable version that is difficult to revoke.

An effective preflight should identify the repository, remote, source and target branches, current and expected SHAs, whether a protected branch is involved, which pipeline will be triggered, the target environment, and the recovery path. Authorization to “push the feature branch” cannot be extended to “create a PR,” “merge main,” or “deploy production.” Even when those actions are technically adjacent, the Agent must stop at the literal boundary given by the user.

Provider-level branch protection, required reviews, and deployment environment rules should add another layer of control. GitHub Actions deployment documentation explains that environments can have protection rules and that pending jobs can be approved or rejected. These technical gates prevent a Prompt misinterpretation from becoming a direct production change.

After execution, read back the remote branch SHA, PR or merge state, the revision or artifact associated with the deployment, and the actual runtime entry point. A successful push is not a merge, green CI is not a deploy, and deployment success does not prove that production behavior is correct.

Gate 2: Explain the risks before even read-only access to persistent data

The data gate covers read, scan, create, update, and delete, because read-only does not mean risk-free:

  • a production query may expose personal information, credentials, or business-sensitive fields;
  • a scan without an index or with an overly broad range may create load and cost;
  • an incorrect time range, tenant, or status filter may produce a misleading conclusion;
  • an export copies production data to another persistent location, expanding the exposure surface.

The preflight must describe the data source and environment, table or index, fields, filters, estimated row count, whether PII is involved, query cost and load, output destination, and retention method. A write operation must also describe transaction boundaries, concurrency conditions, backups, dry-run behavior, batching strategy, rollback method, and the stable primary key used for readback.

Fail closed when the schema, scope, or recovery path is unknown: pause and establish the facts instead of issuing a broad query “just to take a look.” Technical credentials provide capability; only a clearly defined data target and confirmed risks provide authority for this operation.

Gate 3: Cost is also a side effect that requires authorization

Calling a paid model, running a broad log analysis, creating a cloud instance, scaling a database, or sending paid messages may not change business data, but it can still create charges, consume quotas, or leave behind resources that continue to accrue cost.

A cost preflight should include at least the Provider, account or project, region, resource or model, estimated request count or data volume, per-operation and total cost estimates, maximum limit, duration, and cleanup method. If the cost cannot be estimated precisely, give a range and worst case; “it should be cheap” is not an adequate explanation.

Local structural validation, mocks, and dry-runs can reduce the number of real calls, but they cannot masquerade as online verification. Reports must distinguish among “request structure validated,” “free health check passed,” and “paid real path executed.” After execution, read back usage, billing metrics, and resource state, then clean up temporary paid resources.

Gate 4: Irreversible or sensitive actions, and actions that affect external people or systems

The first three categories cannot enumerate every consequence. Force-pushing, deleting files in bulk, rotating credentials, modifying IAM, sending email or Slack messages, creating public issues or PRs, publishing packages, and overwriting backups should all fall under the fourth gate.

The preflight must answer four questions: what exactly is the target, who will be affected, is it recoverable, and how will damage be contained if it fails? For messaging actions, show the recipients and final content; for deletion, list the exact objects and prefer a recoverable method; for permission and key operations, explain the current permissions, new permissions, credential propagation scope, and downstream impact after rotation.

If the target is still determined by a glob, unresolved environment variable, ambiguous alias, or “current account,” it is not ready for approval. Resolve the target to a stable identity before requesting authorization.

Do not turn confirmation into a meaningless click

Too many approvals create approval fatigue. In its Agent containment practices, Anthropic reports that frequent prompts gradually reduce user attention; its conclusion is that systems cannot rely only on people making a judgment each time, and must also limit maximum damage through sandboxes, VMs, filesystem boundaries, and egress control. OpenAI’s practices for running Codex safely follow the same layered principle: keep low-risk routine actions as frictionless as possible, pause only for high-risk actions, and combine those pauses with sandboxes, network policies, managed configuration, and agent-aware telemetry.

Safety Gates should therefore sit at boundaries where consequences change, not around every tool call:

  • reading local code within task scope, performing static analysis, editing authorized files, and running non-destructive local tests can proceed autonomously;
  • touching production, long-lived business or customer data, persistent state outside the authorized workspace, costs, external systems, or irreversible state triggers a preflight and confirmation;
  • an approved action may continue only while its target, payload, risk, and preconditions remain exactly the same;
  • a target change, payload drift, approval timeout, newly discovered cost or data scope, or switching to another path after a failure all require fresh confirmation.

The control principle in OpenAI’s practices for running Codex safely is the same: let an Agent complete low-risk routine work within a bounded environment, while approval policies handle actions that cross technical boundaries or may create high-risk consequences. Approval should attach to real consequences rather than mechanically surrounding every local step.

From Prompt to technical controls: five layers of defense

The four Prompt rules above are the authorization semantics I use today. The five layers below are the engineering target model; they do not claim that every project or runtime has already deployed every control. Each implementation state still needs its own readback.

An actionable safety design has at least five layers:

  1. Prompt / Policy: express user intent, prohibit inferred authorization, and define when the Agent must stop;
  2. Tool boundary: schema validation, parameter allowlists, dangerous-command blocking, idempotency keys, and approval hooks;
  3. Environment: read-only or workspace sandbox, network egress policy, isolated worktree or container, and keeping secrets out of unrelated context;
  4. Provider: least-privilege IAM, branch protection, environment review, budget limits, database permissions, and rate limits;
  5. Telemetry & Readback: record prompts, approvals, tool parameters, results, and Provider identifiers, then read state back from the authoritative target.

The HITL mechanism in the OpenAI Agents SDK demonstrates a key implementation detail: a tool call awaiting approval pauses as an interruption, approval applies to a specific call, and the run state can be serialized and resumed. Wherever possible, a real gate should bind to a concrete tool call and its parameters, rather than relying on the model to remember that “the user agreed earlier.”

Prompt-injection defense likewise has to span layers. Text from webpages, issues, logs, repository documents, and MCP can be treated only as data; it cannot grant new authority. External content must not override top-level policy. Tools should expose only the minimum capabilities required by the task, and credentials should stay out of model context where possible. Even if the model is deceived, the sandbox, egress controls, and Provider permissions should constrain the consequences. Prompting alone can influence behavioral tendencies; it cannot provide an enforceable security guarantee.

Failure modes of Safety Gates

Failure mode Why it is dangerous Correct handling
Ambiguous “okay” or “continue” It is unclear which action and target were approved Echo the action, target, and payload, then obtain precise confirmation
Stale approval The SHA, data scope, or price has changed Bind approval to preconditions and an expiration; reconfirm after changes
Payload drift The executed content differs from the preview Compare the payload or hash before execution and stop on mismatch
Reuse across actions Commit approval is expanded into push or deploy approval Authorize each kind of external consequence independently
Target alias main, prod, or the current account resolves to the wrong object Resolve remote, account, region, and environment to stable identities
Partial success The Provider completed only part of the operation, but the Agent reports completion Read back every target and distinguish verified, mismatch, and unknown
Prompt injection External text induces secret disclosure or unauthorized action Untrusted content cannot change authority; environment and tool boundaries constrain permissions
Approval fatigue The user clicks mechanically and oversight fails Pause only at consequence boundaries; use a short path for low-risk actions
Prompt-only control Probabilistic compliance is mistaken for enforced control Add sandbox, IAM, hooks, Provider rules, and telemetry

A complete safety loop

Use the same loop for every action that triggers a Safety Gate:

Classify consequence
  -> Resolve exact target
  -> Build preview and risk summary
  -> Wait for action-specific confirmation
  -> Re-check target, payload and preconditions
  -> Execute once
  -> Read back from the authoritative provider
  -> Report verified / mismatch / unknown

The value of these four top-level rules is not that they cover every attack or prove that an Agent will never make a mistake. They separate “what high-capability tools can do” from “what this task is allowed to do,” while giving stronger technical controls a shared authorization language. Low-risk work can therefore proceed continuously, while high-risk consequences pause at the right point for confirmation, execution, and readback.

Safety is not an extra check added after automation is complete. Agent autonomy is truly suitable for production engineering only when permissions are minimal, authorization is specific, boundaries are enforceable, and outcomes are auditable.

Related notes

Working on something similar?

I'm always happy to compare notes on distributed systems, delivery, and applied AI.

[email protected]