AI coding agent admin guide·verified October 21, 2026

deny vs instruct for ai coding agent policies

When to hard-block an agent action and when to let it continue with guidance. A decision table for destructive, ambiguous and convention-breaking actions.

the short answer

Deny when the action must not happen: irreversible, destructive or a security boundary, such as terraform destroy or reading .env. Put the redirect in the deny reason, for example “open a PR instead”. Instruct only when the action may proceed and the agent just needs a fact, such as a cheaper instance type. An instruct never holds the call or waits for a human, so never use it as a safety boundary.

`deny(reason)`
Blocks the call where the event and harness support blocking; the agent gets the reason
`instruct(reason)`
The call continues; guidance is delivered where the harness supports it
`allow(reason?)`
The call continues; the policy does not apply or the action is safe
Precedence
Built-ins run before custom policies; the first deny stops evaluation; instructs combine when nothing denies
Rule of thumb
Must not run: deny with a redirect. May run with a nudge: instruct

A Decision Table

ActionDecisionWhy
terraform destroy, kubectl delete in proddenyIrreversible, large blast radius
terraform apply from a laptopdeny, reason: “save a plan and open a PR”It must go through review, so it must not run
Reading .env or dumping environment variablesdenySecrets enter model context and transcripts
git push --force to a shared branchdenyRewrites history others depend on
aws ec2 run-instances --instance-type p5.48xlargeinstructMaybe intended; the agent should know the cost and the usual default
kubectl apply instead of the reviewed deploy wrapperinstructConvention, not catastrophe
Installing a global npm packageinstructChanges the machine outside the project
DELETE FROM users without WHEREdeny in prod, instruct elsewhereScope the decision to the target

How Each One Reaches the Agent

In enforce mode, a deny blocks the call on events and harnesses that support blocking, and the agent receives the reason. An instruct lets the action continue and delivers the reason as guidance where the harness supports it. On Hermes, for example, the call runs and the guidance is placed at the start of its result. Failproof’s own docs say it plainly: do not use instruct() for a safety boundary. The pack’s warn-* policies, such as warn-destructive-sql and warn-global-package-install, are ready-made instructs.

import { customPolicies, allow, instruct } from "failproofai";

customPolicies.add({
  name: "right-size-instances",
  description: "Steer agents away from very large instance types",
  match: { events: ["PreToolUse"] },
  fn: async (ctx) => {
    if (ctx.toolName !== "Bash") return allow();
    const cmd = String(ctx.toolInput?.command ?? "");
    if (!/run-instances|instance_type|instance-type/.test(cmd)) return allow();
    // Largest GPU and memory sizes only: p5, p5e, p5en, p4d, p4de, big x2iedn, u-*tb.
    if (/\b(p5\w*\.48xlarge|p4de?\.24xlarge|x2iedn\.(16|24|32)xlarge|u\d*-\d+tb\d*\.\w+)\b/.test(cmd)) {
      return instruct("That instance type costs hundreds to thousands of dollars a day on demand. Use m7i.large for dev work unless the engineer asked for this size.");
    }
    return allow();
  },
});

Test Cases

CommandExpected
aws ec2 run-instances --instance-type p5.48xlarge --profile agent-devinstruct
aws ec2 run-instances --instance-type u-12tb1.112xlargeinstruct
aws ec2 run-instances --instance-type p5en.48xlargeinstruct
aws ec2 run-instances --instance-type m7i.largeallow
aws ec2 run-instances --instance-type x2iedn.xlargeallow
aws ec2 describe-instancesallow

Make It Robust with a Decision-Model Check

Sizing is a judgment the instance list can only approximate: it knows a few AWS types and nothing about the task. An instruct-mode check asks the decision model whether the request is clearly larger than the task needs, and only ever warns.

We write custom checks like this one for your own rules: talk to us and tell us what should never happen on your machines. Jev comes with Failproof; turn it on whenever you choose, with failproofai jev setup or a Cloud machine key that carries jev:evaluate.

import { semanticPolicies } from "failproofai";

semanticPolicies.add({
  name: "oversized-compute",
  title: "Requested far more compute than the task needs",
  appliesTo: ["shell", "write"],
  mode: "instruct",           // only ever warns: a nudge, not a block
  userCanOverride: true,
  probes: [
    {
      id: "provisions_compute",
      instructions: "Does this call create or resize cloud compute, such as instances, node groups, clusters or GPU jobs, directly or in infrastructure code?",
    },
    {
      id: "larger_than_needed",
      instructions: "Is the requested size clearly larger than what the user's request needs?",
    },
  ],
  guidance: "This looks larger than the task needs. Use the smallest size that works, such as m7i.large for dev work, unless the engineer asked for this size.",
});
  • A Terraform file the agent writes with instance_type = "p5.48xlarge".
  • gcloud compute instances create --machine-type a3-highgpu-8g, and other clouds the AWS-only list does not cover.
  • A large size the engineer actually asked for: the check is user-overridable, so the request clears the warning.

Specific Guidance Beats Generic Caution

In Failproof’s FIRE study, interrupting an agent at the right moment with a generic “reconsider” or “verify your work” barely moved results. The targeted instruction did. Write instruct text the way you would brief a colleague: the one fact they are missing. More results in do guardrails slow agents down.

Success on 14 policy-covered T-Bench 2.1 tasksbaselinewith that message
30%40%50%60%70%Policy3961Reconsider3943Verify3939Generic3936

FIRE (arXiv:2609.26048): generic messages at the same moment barely moved results (36–43% vs 39%); the targeted instruction reached 61% (+25 points over a timing-matched generic message, p = 0.061).

Write the Reason for the Agent That Must Recover

  • Say what was detected: “This changes Route 53 records.”
  • Say what to do instead: “Put the change in the dns/ module and open a PR.”
  • Avoid vague refusals. “Not allowed” makes a capable agent try another route, which is exactly the bypass behavior you do not want.
  • Keep it short. The reason lands in the agent’s context on every match.

Ambiguous Cases Are Where Decision Models Help Most

Over-provisioning, “is this the production database” and “did the user actually ask for this” are judgments, not string matches. The semantic checks in the FailproofAI/jev-policies pack come in two modes that mirror this split. Deny-mode checks such as production-infra-change and destructive-deletion can block on strong evidence and warn on moderate evidence. Instruct-mode checks such as system-modification and read-outside-workspace never deny on their own, but when one fires and the user did not ask for the call, the deny it reviews stands.

Observe Is a Third Option During Rollout

Before enforcing either decision, deploy the policy in observe mode, as a Cloud deployment or a pack published with --effect observe. It evaluates and records what it would have done without affecting the agent. Reading a week of those records is how you find denies that should have been instructs, and instructs that should have been denies.

FAQ

Does instruct block anything?

Not by design. The call proceeds and the agent receives guidance. Some Hermes builds without plugin middleware hold the call once, but you should not rely on that.

What if two policies disagree?

Built-in policies run before custom ones and the first deny wins and stops evaluation. If no policy denies, multiple instructs can be combined.

Can a decision model turn a deny into an instruct?

Only for policies explicitly marked reviewable, only through the semantic checks the policy names, and only with Jev on. Hard policies are final, and every Cloud-managed policy is hard today.

Sources

Checked against the sources below on October 21, 2026. Harness settings, hook capabilities and cloud features change between versions.

  1. Failproof AI docs: Custom policies (policy SDK)
  2. Failproof AI docs: Policies overview
  3. Failproof AI docs: Agent harnesses and enforcement capability
  4. Failproof AI docs: Policy authority
  5. Failproof AI docs: Jev policies
  6. Failproof AI docs: Deploy a policy
  7. Agarwal and Jain (2026): FIRE, Failure-Informed Runtime Engineering for Reliable Language-Model Agents (arXiv:2609.26048)
  8. OWASP: LLM06:2025 Excessive Agency