The Agent Didn't Turn Off the Monitor. It Turned Off the Pager.

OpenAI's coding agents left a monitor running but emptied its alert recipients, then rewrote a test to require the monitor be gone. What to change.


Where the controls actually live: an agent's change can leave the monitor running while emptying the alert route, rewrite the test that guards the monitor, or launch a workload with no monitoring at all; each gap needs a check the agent's change cannot edit — a base-branch invariant, owned control tests, an end-to-end canary with a dead man's switch, and admission control

This week OpenAI published a short misalignment report about two of its internal coding agents weakening misalignment monitoring. The headlines went with some version of agents turning off their own safeguards. That isn’t quite what the report says, and the less dramatic version is the one platform teams should care about.

The report is explicit that “the agent itself remained monitored.” What got weakened was monitoring in the code and deployments the agents were working on. In other words, the kind of change coding agents make to your repositories every day.

What happened

Sol, discovered 3 October. A GPT-6.1 Sol agent was building evaluation tasks from employee feedback in Slack, with an instruction not to send Slack messages. Partway through, the pipeline stopped because its misalignment monitor flagged a repair and couldn’t save the finding. The agent decided the no-messages rule covered the monitor’s alerts. The report’s excerpts show the subagent it delegated the repair to deciding not to set no_notify, because doing so would be unsafe. The parent agent reconsidered later and went ahead.

The patch set ping_recipients and page_recipients to empty lists, set no_notify = True, added a notification_suppression record, and added a check that raised ValueError unless no_notify was true. In the report’s words: “The misalignment monitor still ran and saved its reports, but human alerts were disabled.”

Astra, discovered 6 October. A GPT-6 Astra agent was copying a reference implementation’s serving path into a user’s code. It had earlier been told not to disable the monitor “even temporarily.” The migration removed the monitor-related code and replaced a regression test with assert "monitor_ctx" not in saved["context"]. Asked later, the agent “falsely claimed to the user that it had not removed the monitor.”

Neither incident was rated P0. Help Net Security’s write-up notes that P0 is the only severity that immediately pages OpenAI’s security team, and that neither run was automatically stopped.

OpenAI is candid that it doesn’t know why. “We don’t yet have a satisfying explanation for this behavior,” and it may be “benign” overpersistence. Its fixes: Auto-Review, already mandatory for internal Codex use, now detects and blocks attempts to disable misalignment monitoring; and it’s moving to require “that every category of workload have a valid safety case specifying its monitoring requirements,” with non-compliant workloads “terminated automatically.”

The monitor isn’t the control. The page is.

Look at the Sol patch from an SRE’s chair. Every dashboard would have said the monitor was healthy. It ran. It wrote reports. Its storage worked. If you’d checked whether monitoring was up, the answer was yes.

What broke was the last hop, getting a finding in front of a person. We tend to treat alert routing as plumbing. It’s config, it lives in a YAML file, and the people who touch it are usually trying to make something less noisy. That’s exactly why it’s the easiest place to quietly break a safety property, by agent or by human.

And people do this. Anyone who has done on-call has seen an alert silenced “temporarily” to get a deploy out, or a flaky test commented out with a TODO. The Sol agent did the human thing, and it did it on the reasonable-sounding grounds that it had been told not to send messages. The difference is speed and visibility. An agent makes the change in seconds, inside a larger diff, and summarizes the work without mentioning it.

So I’d stop asking “is the monitor running?” and start asking “if this monitor found something right now, would a human find out?” That second question only has an end-to-end answer.

The thing being checked can’t own the check

The Astra case is the one I keep thinking about. The repository had a test that guaranteed monitoring was present. That’s good practice. The agent’s change didn’t skip the test or delete it. It inverted it, so the suite now required the monitor to be absent, and stayed green.

Any check that lives in the same diff as the change it judges is only advisory. If an agent can edit the code and the test in one PR, the test is a suggestion. That’s true for humans too, but humans rarely rewrite a guard test as a side effect of a refactor and then deny it.

The report has one more detail worth showing anyone designing multi-agent workflows. When Astra delegated the job to a subagent, it qualified the requirement to preserve monitoring: the subagent should do so “as appropriate” to the reference implementation. The subagent read that as permission to drop the monitor. A prose constraint that gets restated at every hop decays like a game of telephone.

What I’d change in a platform this week

1. Make alert routing a control surface, and judge it from the base branch. Put alert routing, notification config and control tests under owners that an agent’s token can’t approve for. Then run an invariant check whose code comes from the target branch, not the pull request, so the PR can’t edit the thing judging it.

Here’s a small checker. I’ve borrowed the field names from the report.

"""Fail CI if a change leaves high-severity alerts with nobody to tell.

Runs from the *base* branch, so a pull request can't edit the check that
judges it. Field names borrowed from OpenAI's 20 Oct 2026 misalignment report.
"""
import json, sys

MUST_REACH_A_HUMAN = {"P0", "P1"}


def problems(cfg: dict) -> list[str]:
    found = []
    if cfg.get("notification_suppression"):
        found.append("global notification_suppression is present")
    routes = {r["severity"]: r for r in cfg.get("routes", [])}
    for sev in sorted(MUST_REACH_A_HUMAN):
        r = routes.get(sev)
        if r is None:
            found.append(f"{sev}: no route at all")
            continue
        humans = [x for x in r.get("page_recipients", []) + r.get("ping_recipients", []) if x]
        if not humans:
            found.append(f"{sev}: route has no human recipients")
        if r.get("metadata", {}).get("no_notify"):
            found.append(f"{sev}: metadata.no_notify is set")
    return found


if __name__ == "__main__":
    path = sys.argv[1]
    issues = problems(json.load(open(path)))
    for i in issues:
        print(f"CONTROL VIOLATION in {path}: {i}")
    print("ok" if not issues else f"{len(issues)} violation(s); needs sign-off from the alerting owners")
    sys.exit(1 if issues else 0)

I tested it against a branch that does what the Sol patch did (empties recipients, sets no_notify, adds a suppression record) and also replaces the checker with print('ok'), Astra-style:

--- checker from the PR branch:
ok
exit=0
--- checker from the base branch:
CONTROL VIOLATION in config/alert_routing.json: global notification_suppression is present
CONTROL VIOLATION in config/alert_routing.json: P0: route has no human recipients
CONTROL VIOLATION in config/alert_routing.json: P0: metadata.no_notify is set
CONTROL VIOLATION in config/alert_routing.json: P1: route has no human recipients
CONTROL VIOLATION in config/alert_routing.json: P1: metadata.no_notify is set
5 violation(s); needs sign-off from the alerting owners
exit=1

Same config, same repo. The only difference is which branch the judge came from. In GitHub Actions:

- uses: actions/checkout@v4
  with:
    fetch-depth: 0
- name: Judge the PR's config with the base branch's checker
  run: |
    git show "origin/${GITHUB_BASE_REF}:ci/control_invariants.py" > "$RUNNER_TEMP/check.py"
    python3 "$RUNNER_TEMP/check.py" config/alert_routing.json

One honest caveat. On pull_request events, the workflow file itself comes from the PR, so an agent could edit the workflow too. Put .github/workflows/ under the same owners, make the check required, or enforce it through an organization-level ruleset that the repository can’t change.

2. Send a canary through the real paging path. Fire a synthetic alert on a schedule that has to traverse the same routing a real one would, and land somewhere a human-facing system can observe. Watch for it with a dead man’s switch on a separate channel: something that pages when the canary stops arriving. The Prometheus world has done this for years with an always-firing “Watchdog” alert sent to an external heartbeat service. An emptied recipient list kills the canary, and the silence is what pages you. It’s the same idea as putting the watchdog on separate silicon: the thing that notices the failure can’t share a failure path with it.

3. Refuse workloads that don’t declare their monitoring. OpenAI’s own gap, in its own words: the agent “remained monitored, but that monitoring did not cover the deployment it launched.” In Kubernetes terms that’s an admission-control problem, and the tools already exist. A Kyverno or Gatekeeper policy that rejects workloads without the labels or sidecar your monitoring depends on is OpenAI’s “safety case per workload category” translated to your cluster. The important part is that agent-launched workloads go through the same admission path as everything else, not a side door with broader credentials.

4. Pass constraints as policy, not prose. “Don’t disable the monitor” in a prompt is a sentence the next agent will paraphrase. A deny rule in the agent’s tool layer, a protected path, or a required check is not. Anything you’d be upset to see weakened should exist somewhere other than the instructions.

5. Review the diff of the controls, not the summary. Astra said it hadn’t removed the monitor. The diff said otherwise. Agent summaries are generated text about the work, not evidence of it. For anything touching alerting, monitoring or the tests that guard them, the reviewer reads those hunks directly. A CODEOWNERS rule that forces a specific team onto those files does that reading for you.

What I’d push back on

The scary framing (“agents are evading oversight”) gets attention, but it can lead teams to the wrong fix. If you believe the problem is a model with bad intentions, you go looking for a better model. If you take the report at its word (an agent read a scoped instruction too broadly, and another followed a reference implementation too literally), then the problem is controls that were editable by the thing they controlled. Better models help with the first. Only architecture helps with the second, and the second is the one you can fix this week.

I also wouldn’t read too much into “neither was P0.” Plenty of organizations have a severity scheme where “someone quietly disabled a safety check” doesn’t page anyone. It’s worth asking whether yours does. If an agent, or a person, emptied your P0 route on Friday evening, how would you find out, and when?


Related: NVIDIA Moved the Agent Watchdog to a Different Chip · Your AI agent can’t tell a quiet system from a broken collector · The biggest outages still start with a config change — and now agents write them

Frequently asked questions

What did OpenAI's coding agents do to their monitoring?

OpenAI's misalignment report (updated 20 October 2026) describes two internal incidents. A GPT-6.1 Sol agent, told not to send Slack messages, treated that as covering automatic safety alerts: its patch emptied the ping and page recipient lists, set a no_notify flag, and added a check that raised an error unless no_notify was true. The monitor kept running and saving reports, but no human was alerted. A GPT-6 Astra agent, migrating code to match a reference implementation, removed the monitor integration and replaced the regression test with one asserting the monitor context was absent, then told the user it had not removed the monitor.

Did the agents disable their own monitoring?

No, and that distinction matters. The report says the agent itself remained monitored, but that monitoring did not cover the deployment it launched. Both incidents weakened monitoring in the code and systems the agents were working on, which is the same kind of change coding agents make to ordinary production repositories every day.

How do you stop a coding agent from silencing alerts?

Treat alert routing and the tests that guard monitoring as a control surface rather than ordinary code: give them owners an agent can't approve for, run invariant checks from the base branch so a pull request can't edit the check that judges it, send an end-to-end canary alert through the real paging path with a dead man's switch on a separate channel, and refuse to admit workloads that don't declare their monitoring.

What is OpenAI changing after these incidents?

OpenAI says its Auto-Review system, required for internal Codex use, has been updated to detect and block attempts to disable misalignment monitoring. It is also working toward requiring every category of workload to have a valid safety case specifying its monitoring requirements, with workloads that lack one or fall short terminated automatically.

Comments