Every AI system ships with risk left over. Prompt injection against an agent that reads email cannot be driven to zero with today's techniques, a summariser will still hallucinate occasionally, and a retrieval system will sometimes surface a document a user should not have seen. After you have assessed a risk and applied the controls you can afford, someone has to decide that the remainder is tolerable and that the system may run anyway. That decision is risk acceptance.

Done badly, acceptance is a signature that turns a known problem into an invisible one. Done well, it is a dated, scoped, conditional record that names an accountable person, states what would make the decision invalid, expires on its own, and is enforced by the deployment pipeline rather than by memory. This article covers the decision itself: when acceptance is legitimate, who may sign, what the record must contain, how expiry and revocation work for AI systems whose behaviour changes with every model or prompt update, and how to make an expired acceptance block a release. Scoring residual risk is covered in AI risk register, and setting the thresholds in AI risk appetite.

What acceptance is, and is not

Risk treatment has four classic options: reduce the risk with controls, avoid it by not doing the activity, transfer or share it through contracts or insurance, or accept it. Acceptance is the only option that changes nothing about the system, which is exactly why it needs the most paperwork. ISO/IEC 27001 asks risk owners to approve the treatment plan and the residual risk that remains, and the EU AI Act's risk-management requirements for high-risk systems expect residual risk to be judged acceptable. Neither tells you how to make that judgement. Your process has to.

It helps to separate acceptance from three things it is often confused with:

  • Ignoring a risk. A risk nobody assessed has not been accepted. Acceptance presupposes an assessment with a stated likelihood, impact and residual level.
  • A policy exception. An exception waives a specific control requirement, for example running without output filtering on one internal tool. It often comes with a risk acceptance, but the two records answer different questions: which rule is waived, and which consequence is tolerated.
  • Within-tolerance operation. If residual risk is inside tolerance, many organisations record it as accepted by default under the system owner. That is fine, as long as it is written down and the same expiry and trigger rules apply. Explicit, escalated acceptance is reserved for residual risk above tolerance.

When acceptance is legitimate

Acceptance is legitimate only when four preconditions hold. Make them fields in the request form so a reviewer can reject an incomplete request without a meeting.

  1. The risk is assessed. There is a register entry with a residual score and the evidence behind it: red-team results, eval pass rates, incident history.
  2. Treatment options were costed. The request lists at least one control that would reduce the risk further and why it is not being applied now: cost, latency, lead time, or no known technique. "We did not look" is not a reason.
  3. The impact is bounded. Someone can state the worst plausible outcome in concrete terms, such as "an attacker can make the agent send one email to an internal address". Unbounded impact, such as an agent with write access to production databases and no blast-radius limit, cannot be accepted, only reduced.
  4. The signer owns the consequence. The person accepting must be the one whose budget, customers or licence absorb the loss. An engineer cannot accept a risk on behalf of the legal team.

Who may sign: an authority matrix

Authority scales with the residual score from the register. A small team needs only three bands; more bands add argument without adding control. The maximum term shortens as the band rises, because the more you are tolerating, the sooner you should look again.

Residual bandWho may acceptMaximum termExtra requirement
Within toleranceSystem owner12 monthsRecorded in the register
Medium: exceeds a tolerance, impact boundedBusiness unit head plus security lead6 monthsCompensating controls and a treatment plan with dates
High: exceeds a tolerance, severe impactExecutive risk owner (for example CRO or COO)90 daysGovernance council review; board reporting if it is renewed
Unbounded or legally prohibitedNobodyNot applicableMust be reduced or avoided

Two rules keep the matrix honest. First, the requester cannot be the signer at any band. Second, splitting a risk into smaller pieces to keep each one below a band is forbidden: if three acceptances share a root cause, their bands are combined. A reviewer should check for the same threat, asset and control gap appearing in several requests from one team in one quarter.

Anatomy of an acceptance record

The record is the product of the process. Keep it as structured data next to the system's code, not as a PDF in a document store, so tools can read it. A minimal schema:

id: RA-2026-031
risk_ref: RISK-114          # register entry; scores live there
system: support-agent
scope:
  model: vendor-model-2026-07   # exact version the evidence was gathered on
  prompt_hash: 9f2c41d0
  tools: [search_kb, draft_reply, send_internal_email]
  tenants: [internal-support]
residual_band: medium
statement: >
  Indirect prompt injection in customer tickets can cause the agent to
  send at most one internal email per ticket containing ticket text.
evidence: [redteam-2026-09-run4, eval-inj-suite-v7]
conditions:
  - kri: injection_success_rate_weekly
    max: 0.02
  - control: outbound_email_allowlist
    must_be: enabled
treatment_plan: "Move send_internal_email behind human approval by 2026-12-15"
requested_by: support-platform-lead
accepted_by: vp-customer-operations
co_signed_by: security-lead
signed_on: 2026-10-06
expires_on: 2027-01-04
revoke_on: [model_change, tool_added, tenant_added, sev2_incident]

Three fields matter most for AI systems. Scope pins the exact model version, prompt hash and tool list, because the evidence was gathered on that configuration and says little about any other. Conditions are measurable: a key risk indicator with a ceiling, or a control that must stay enabled. revoke_on lists the events that void the acceptance immediately, before its expiry date.

Revocation triggers for AI systems

Traditional software risk acceptances often run a year untouched, because the system does not change much. AI systems change constantly, and many changes alter the risk without touching application code. Treat these as revocation triggers:

  • Model change. A vendor model update or a new fine-tune changes susceptibility to injection and the hallucination rate. The old red-team result no longer describes the system.
  • Prompt or tool change. Adding a tool widens the blast radius. Editing the system prompt can remove a mitigation someone relied on.
  • Scope change. New tenants, external users or new data sources change who is exposed and who can attack.
  • Condition breach. A KRI above its ceiling for a set period, or a compensating control found disabled. AI risk monitoring covers building indicators that actually warn.
  • New attack class. A published technique that defeats the controls the acceptance assumed.
  • Incident. Any incident at or above an agreed severity that is attributable to the accepted risk.

Revocation does not have to mean shutdown. The record should say what happens: fall back to a safer mode such as disabling the risky tool, re-sign within a set number of days on fresh evidence, or stop the system.

Enforcing acceptance at deploy time

Risk acceptance lifecycle: a dated, owned, conditional decisionAssessed residualfrom the registerAcceptance requestoptions, conditionsAuthority checkband decides signerSigned recordexpiry, scopeDeploy gateCI reads the recordMonitored conditionsKRIs, evals, scopeTrigger firesbreach, change, expiryRevokedtreat, avoid or re-signRenewal reviewfresh evidence onlyNew recordnew id, new termNo path leads from expiry back to the same record: renewal always creates a new decision.
The lifecycle. The deploy gate reads the signed record, monitoring checks its conditions, and every exit path either reduces the risk or produces a new record.

An acceptance nobody checks is a wish. The cheapest enforcement point is the deploy pipeline. It already knows the model version, prompt hash and tool list it is about to ship, so it can compare them with the scope of every acceptance that system depends on. The check below fails the release when an acceptance has expired, has been revoked, or was signed for a different configuration.

import datetime as dt
import yaml

class AcceptanceError(Exception):
    pass

def check_acceptances(records, release, today=None):
    """records: parsed acceptance YAML; release: what CI is about to ship."""
    today = today or dt.date.today()
    problems = []
    for r in records:
        if r["system"] != release["system"]:
            continue
        rid, scope = r["id"], r["scope"]
        if r.get("revoked"):
            problems.append(f"{rid}: revoked ({r['revoked']})")
        if dt.date.fromisoformat(str(r["expires_on"])) < today:
            problems.append(f"{rid}: expired {r['expires_on']}")
        if scope["model"] != release["model"]:
            problems.append(f"{rid}: signed for {scope['model']}, shipping {release['model']}")
        if scope["prompt_hash"] != release["prompt_hash"]:
            problems.append(f"{rid}: prompt changed since signing")
        extra = set(release["tools"]) - set(scope["tools"])
        if extra:
            problems.append(f"{rid}: tools not covered: {sorted(extra)}")
        if r["accepted_by"] == r["requested_by"]:
            problems.append(f"{rid}: requester signed own acceptance")
    if problems:
        raise AcceptanceError("; ".join(problems))

records = yaml.safe_load(open("risk/acceptances.yaml"))
check_acceptances(records, {
    "system": "support-agent", "model": "vendor-model-2026-07",
    "prompt_hash": "9f2c41d0",
    "tools": ["search_kb", "draft_reply", "send_internal_email"],
})

Run the check in two places. In CI it blocks a release that drifts outside the signed scope. In a daily scheduled job it catches expiry and condition breaches on a system nobody is deploying. That second check is the one that stops a forgotten acceptance from quietly passing its end date. The daily job should also read the KRI values named in conditions and open a revocation ticket when one is breached.

Worked example: injection risk in a support agent

Take the support agent in the record above. It reads customer tickets, searches a knowledge base, drafts replies and can email internal teams. A September red-team run found that 3.1 percent of crafted tickets caused the agent to send an internal email containing attacker-chosen text. The worst plausible outcome is a convincing phishing message from a trusted internal sender. The register scores the residual as medium: it exceeds the injection tolerance, but the impact is bounded.

The team costs three treatments. Human approval on every outbound email removes the risk but needs a review queue that will not be staffed until December. Removing the tool breaks escalations, which customers rely on. An allowlist of recipient addresses plus a banner marking agent-sent mail cuts the measured success rate to 1.4 percent and is shippable this week. They ship the allowlist and banner, then request acceptance of the remainder with a treatment plan to add approval by 15 December.

Under the matrix the signer is the business unit head, with the security lead co-signing, for at most six months. They choose 90 days, because the treatment plan finishes sooner. The conditions are a weekly injection success rate on a canary suite below 2 percent and the allowlist staying enabled. In November the vendor ships a new model version. The deploy gate fails with "signed for vendor-model-2026-07", the team reruns the injection suite on the new model, the rate comes back at 1.2 percent, and a new acceptance with a new id is signed against the new scope. The old record stays in history, marked superseded.

Renewal without rot

Renewal is where acceptance processes rot. The pattern is familiar: the first acceptance is argued carefully, the second is copied forward, and by the fourth nobody remembers why the risk was tolerable. Three rules prevent this.

  • No automatic renewal. Expiry blocks deploys and pages the owner. Renewal is a new record that cites new evidence gathered within the last 30 days.
  • Escalate on repetition. A second renewal of an above-tolerance acceptance moves up one authority band. A third goes to the governance council with the question "why has the treatment plan not happened?"
  • Track the treatment plan. If the plan's date passes without delivery, the acceptance is revoked rather than extended. Acceptance buys time to treat; it is not a substitute for treating.

Failure modes

  • Rubber-stamp signing. Executives sign whatever reaches them. Counter it with a one-page request whose first line is the worst plausible outcome in plain language, and by tracking the rejection rate: zero rejections in a year is a warning.
  • Scope rot. The acceptance was signed for one model and two tools; the system now runs a different model with five tools. The deploy-time scope check exists to prevent exactly this.
  • Orphaned records. The signer leaves the company. Acceptances belong to a role, with a named holder; a role change triggers re-confirmation by the new holder within 30 days.
  • Unmeasurable conditions. "Monitor closely" is not a condition. If nobody can write the query, the condition does not exist.
  • Accepting someone else's risk. Vendor or customer exposure accepted by an internal team without the affected party knowing. Contractual risk needs the contract owner's signature.
  • Evidence from a friendlier configuration. Red-team results gathered with output filtering on, while production runs with it off for latency. Record the configuration the evidence came from and compare it with production.

Trade-offs

Short terms keep acceptances honest but cost review time. If every acceptance runs 30 days, signers drown and start rubber-stamping, which defeats the purpose. Long terms save effort but let model drift outrun the evidence. The compromise above, terms that shrink as risk rises plus event-based revocation, puts review effort where the risk is.

Tight scope pinning is the other trade-off. Pinning the prompt hash means every prompt tweak forces a re-sign, which feels bureaucratic for a typo fix. Some teams pin a prompt policy version instead and bump it only for changes that touch safety instructions. That works only if the classification is reviewed. Otherwise "not safety-relevant" becomes the way every change avoids review. Start strict, measure how many re-signs you trigger, and loosen deliberately. For audits, see LLM audit preparation: an auditor will sample acceptances, so every record should stand on its own.

What to do next

  1. List every AI system and ask its owner which known risks it runs with. Each answer without a record is an unrecorded acceptance; write those records first.
  2. Adopt a three-band authority matrix with maximum terms, and the rule that requesters never sign.
  3. Store acceptances as YAML beside the code, with scope pinned to model version, prompt hash, tools and tenants.
  4. Add the deploy-time check to CI and the same check as a daily job; fail closed on expiry, scope drift and self-signing.
  5. Write at least one measurable condition and one revocation trigger per acceptance, and wire the KRI into monitoring.
  6. Ban automatic renewal: escalate on the second renewal, and revoke when the treatment plan date passes.
  7. Review the portfolio quarterly: count by band, age and renewal number, and look for split risks sharing a root cause.
Key takeaway: Risk acceptance is a decision to run a system with known residual risk. It is legitimate only after assessment, costed treatment options and a bounded impact, and only when signed by someone who owns the consequence and is not the requester. Record it as data scoped to the exact model, prompt and tools, give it measurable conditions, revocation triggers and an expiry that shrinks as risk rises, and let the deploy pipeline refuse to ship when any of those no longer hold.