Most risk frameworks group the ways to treat a risk into four: reduce it, share it, accept it, or avoid it. The first three get almost all of the engineering attention in AI programs, because they let the project ship. Avoidance, deciding not to start or not to continue the activity that creates the risk, is usually treated as a failure of imagination. That is a mistake for LLM systems in particular. Model behaviour cannot be proven, only sampled, so a control that depends on the model behaving well is weaker than it looks, and the only control that holds with certainty is the absence of the capability.

This article treats avoidance as an engineering tool rather than a veto. It covers where avoidance sits among the treatments, the criteria that make it the right answer, how to apply it at the level of a single feature instead of a whole project, a worked example with the scoring arithmetic, and how to make a 'no' stick: a decision that is not enforced in code decays within a few release cycles.

Where avoidance sits among the treatments

Among its treatment options, ISO 31000 includes avoiding the risk by deciding not to start or continue with the activity that gives rise to it. The NIST AI Risk Management Framework builds the same idea into its MANAGE function in two places. MANAGE 1.1 asks for a determination of whether the AI system achieves its intended purpose and whether its development or deployment should proceed at all. MANAGE 1.3 asks that responses to high-priority risks be developed, planned and documented, and names the options as mitigating, transferring, avoiding, or accepting. Avoidance is therefore not an exceptional escalation; it is a normal output of the process, and a program that never produces one is probably not assessing honestly.

Some avoidance is not a choice. The EU AI Act's Article 5 prohibits a set of practices outright, among them social scoring, untargeted scraping of facial images to build facial recognition databases, and emotion recognition in workplaces and schools outside medical or safety uses. For anything on that list the decision is already made, and the work is detection: making sure a product team does not drift into a prohibited practice by adding one feature to an otherwise lawful system.

The decision flow below shows the ordinary path. Avoidance is reached only after mitigation and transfer have been considered and found insufficient, and it has two forms: declining the whole use case, or cutting the single capability that carries the risk while keeping the rest.

Choosing a treatment for one assessed riskAssessed riskinherent likelihood x impactResidual after feasible controlswithin appetite?yesMitigate / acceptowner signsnoCan the risk be shifted?insurer, vendor, contractpartlyTransfer+ mitigate the restnoAvoidremove the feature or declineScope cutdrop one capabilityDecision record + enforcement + re-review datethe 'no' is a control, not a memoAvoidance is the branch taken when no affordable combination of controls brings residual risk under appetite.
Treatment selection. A scope cut is the usual form of avoidance; declining a whole use case is the rarer one.

When avoidance is the right answer

Four conditions, any one of which is sufficient, make avoidance the right treatment. First, residual risk after every feasible control is still above the stated tolerance; 'feasible' includes cost, because a control that costs more than the feature earns will be quietly switched off later. Second, the harm is severe and irreversible and there is no detective control fast enough to stop it: an agent that can wire money, delete production data, or send messages to thousands of customers needs prevention, not monitoring. Third, the only available mitigation is an instruction to the model. A system prompt that says 'never reveal other customers' data' is a request, not a control, and an assessment that relies on it should score the residual as if the instruction were absent. Fourth, the activity is prohibited, or will be before the system is retired.

The second and third conditions matter most for LLM products. Prompt injection, for example, has no complete fix today: any text the model reads can steer it. A system that combines untrusted input, access to private data, and a channel to send data out has a risk whose likelihood cannot be driven to near zero by filtering. The reliable treatment is to avoid one of the three ingredients, which is exactly a scope cut.

SituationWhy mitigation falls shortAvoidance option
Agent reads inbound email and can send emailinjected text can trigger exfiltrationremove send; draft only
Chatbot open to anonymous users, including minorsage assurance is probabilisticexclude the audience or the topic
Retrieval over HR records for a general assistantaccess checks in the prompt are not enforcedremove the data class from the index
Model executes generated code on shared hostssandbox escape is high impactno execution; return code to a human
Automated decisions on credit or hiringexplanation and appeal duties are heavyadvisory output only

Avoidance at feature granularity

Whole-project declines are rare and politically expensive. Scope cuts are cheap and precise: the project ships, minus the one capability that carried the unacceptable risk. The useful habit is to decompose each high-scoring register entry into the capabilities that produce it and ask, for each, what the product loses without it. The common cuts are: removing a tool; downgrading a tool from write to read; removing a data class from retrieval; removing an audience, a language or a jurisdiction; removing autonomy by putting a human approval step before an action; and removing an output channel such as rendering links or images that can carry data out.

A scope cut is avoidance, not mitigation, when it removes the capability rather than guarding it. A refund tool with a dollar limit is mitigation: the risk exists, smaller. No refund tool at all is avoidance: the risk of the agent issuing a fraudulent refund is gone, and the residual moves to a different, well-understood process. The distinction matters for scoring, because a removed capability needs no monitoring for that risk, only for its reappearance.

Worked example: a support agent with a refund tool

Consider a support agent for an online retailer. The proposal gives it order lookup, address change and refund tools, and it reads customer messages that may contain injected text. The register scores likelihood and impact on 1 to 5 scales, the appetite threshold for customer-facing financial risk is 8, and the team has assessed three controls for the refund risk: a per-refund limit of $50, a daily cap per account, and an anomaly alert reviewed the next morning. The script below is the arithmetic the council saw.

APPETITE = 8                      # max residual score for this risk category

risks = {
    "fraudulent refund via injection": dict(likelihood=4, impact=4,
        controls={"per-refund limit": (0, 1), "daily cap": (1, 0), "next-day alert": (0, 0)}),
    "address change hijack": dict(likelihood=3, impact=4,
        controls={"step-up verification": (2, 0)}),
    "wrong order status": dict(likelihood=3, impact=1, controls={}),
}

def residual(r):
    l, i = r["likelihood"], r["impact"]
    for dl, di in r["controls"].values():     # each control lowers likelihood or impact
        l, i = max(1, l - dl), max(1, i - di)
    return l * i

for name, r in risks.items():
    score = residual(r)
    verdict = "within appetite" if score <= APPETITE else "AVOID or redesign"
    print(f"{name:34s} inherent={r['likelihood'] * r['impact']:2d} residual={score:2d} {verdict}")

The output shows the refund risk at an inherent 16 and a residual of 9: the limit cuts impact from 4 to 3 and the cap cuts likelihood from 4 to 3, while the next-day alert is detective and too slow to change either number. The address change risk falls from 12 to 4 with step-up verification, and order status sits at 3. Only one entry is out of appetite, and it maps to exactly one capability.

The council's options were to find another control, accept the risk above appetite with an executive sign-off, or remove the refund tool. A stronger control existed, human approval of each refund, but it removes the reason for automating refunds in the first place, so it is avoidance in practice and the honest record names it as such. The decision was to ship lookup and address change, cut refunds, and have the agent open a ticket in the existing refund queue with the order details pre-filled. Customers lost a few minutes, the business lost no money to injected refund requests, and the risk register entry closed with a residual of zero for that path plus a new, small entry for ticket spam.

Making the decision stick

An avoidance decision that lives only in meeting minutes erodes in predictable ways: a new engineer adds the tool back because the ticket asked for it, a platform team grants a broader API scope for an unrelated reason, a vendor ships the capability as a default, or a prompt change starts producing the forbidden output. Treat the decision as a control with an ID and enforce it in as many layers as the capability can enter through.

The first layer is a machine-readable avoidance register. The second is a CI check that every agent manifest is compared against it, so the reintroduction fails a build rather than an audit. The third is the tool registry or identity system: the service account behind the agent cannot be granted the refund API scope at all. The fourth is the network: egress rules or the model gateway deny the endpoint. The last is a detector over traces that alerts if anything resembling the avoided action appears, which catches the paths nobody predicted.

Where an avoidance decision is enforcedAvoidance registerAVD-017: no refunds toolCI policy checkrejects agent manifestTool registrytool not grantableGateway / egressendpoint deniedRuntime detectoralerts if the avoided capability appears in tracesSanctioned alternativehuman refund queue with SLAoffered with the noEach layer catches a different way the decision erodes: new code, new grants, new vendors, new prompts.
Defence in depth for a decision. The sanctioned alternative is part of enforcement: it removes the reason to route around the decision.
# avoidance_register.yaml (excerpt)
# - id: AVD-017
#   applies_to: [support-agent]
#   forbid_tools: [issue_refund, create_credit_note]
#   forbid_scopes: [payments.refunds.write]
#   decided: 2026-09-14
#   review_by: 2027-03-14

import sys, yaml, datetime

def check(manifest_path, register_path):
    manifest = yaml.safe_load(open(manifest_path))
    register = yaml.safe_load(open(register_path))
    failures = []
    for d in register:
        if manifest["name"] not in d["applies_to"]:
            continue
        for t in set(manifest.get("tools", [])) & set(d.get("forbid_tools", [])):
            failures.append(f"{d['id']}: tool {t} is avoided")
        for s in set(manifest.get("scopes", [])) & set(d.get("forbid_scopes", [])):
            failures.append(f"{d['id']}: scope {s} is avoided")
        if datetime.date.fromisoformat(str(d["review_by"])) < datetime.date.today():
            failures.append(f"{d['id']}: review overdue; decision must be re-confirmed")
    return failures

if __name__ == "__main__":
    problems = check(sys.argv[1], sys.argv[2])
    print("\n".join(problems) or "avoidance register: ok")
    sys.exit(1 if problems else 0)

Decision records, review and the alternative path

The decision record should let someone who was not in the room understand and re-test the decision. It needs the risk statement and its scores, the controls considered and why each fell short, the exact scope removed, the sanctioned alternative, the owner, and the conditions under which the decision should be reopened. Those conditions are what turn avoidance from a permanent ban into a managed position: a new model whose injection resistance passes a defined evaluation, a new control such as a transaction signing step becoming available, a regulatory change, or a business case large enough to justify an accepted risk at executive level. Give every record a review date as well, so a decision that was right for this year's models is not still blocking next year's.

Communication matters as much as the record. A flat refusal with no alternative is the most reliable way to create unsanctioned use: the business need does not disappear, so teams reach for a personal account on a public chatbot or a browser extension that nobody has assessed. The reason to pair every avoidance with a sanctioned path is not courtesy; it is that the unsanctioned route usually carries more of the same risk with none of the controls.

Failure modes

  • Avoidance theatre. The capability is removed from the UI but the tool remains registered, so a crafted prompt still reaches it. Remove it from the agent definition and the credentials, not just the screen.
  • Risk displacement unmeasured. Cutting automation moves volume to humans; if the queue triples and the SLA slips, staff start approving without checking. Score the new path.
  • Permanent bans. Decisions with no review date harden into folklore. Teams stop asking, or worse, stop telling.
  • Mislabelled mitigation. A tightly guarded capability recorded as 'avoided' makes the register lie; monitoring for it is then never built.
  • Vendor drift. A SaaS model or agent platform enables a new feature by default, such as web browsing or memory, and reintroduces an avoided capability without any internal change.
  • Over-avoidance. Declining every novel use teaches the organization that the risk function is an obstacle, and the work moves out of its sight.

Trade-offs

TreatmentResidual for that riskOngoing costMain weakness
Avoid (decline)nonelost valuepushes demand elsewhere
Avoid (scope cut)none on that pathenforcement + alternativedisplaced work
Mitigatereduced, nonzerocontrols + monitoringdepends on control strength
Transferfinancial share movedpremiums, contractsreputation stays with you
Acceptunchangedmonitoringneeds authority and appetite

What to do next

  1. Pull every register entry whose residual exceeds appetite and decompose each into the capabilities that produce it; the AI risk register article covers how to write those statements so they can be tested.
  2. Rescore any residual that depends on a model instruction as if the instruction were absent.
  3. For each remaining out-of-appetite entry, list the scope cuts and what the product loses with each.
  4. Check thresholds against a written appetite; AI risk appetite shows how to turn board language into numbers.
  5. Bring decisions to the body with the authority to make them, as described in the AI governance council article.
  6. Create a machine-readable avoidance register and wire the manifest check into CI.
  7. Remove avoided capabilities from credentials and network paths, not only from code.
  8. Pair every avoidance with a sanctioned alternative and an owner for it.
  9. Set review dates and reopening conditions, and put them on the cycle in AI policy review cadence.
  10. Report avoidance decisions as part of the program's metrics, alongside the structure in AI governance program structure.
Key takeaway: Risk avoidance is a normal treatment, not a veto: choose it when no affordable set of controls brings residual risk under appetite, when harm is irreversible and undetectable in time, or when the only mitigation is asking the model to behave. Prefer cutting the one capability over declining the project, enforce the cut in CI, credentials and the network, pair it with a sanctioned alternative, and give every decision a review date and explicit reopening conditions.