Automatic API fixes for proven runbooks

Let a certified API runbook repeat, on its own, a fix the platform already verified for the same alert — off by default — and set it up like the demo.

How-to · Updated 2026-10-26 · Describes release 0.1.164

What it does

By default every live cloud write waits for a person. With Allow pre-approved routes to auto-fire on, a pre-approved route that opens a pull request may open it on its own; the pull request changes nothing until someone merges it.

Automatic API fixes for proven runbooks adds one more case, and only one: a runbook route that calls a cloud API (mode api, named remediate-…) and that an approver certified may make its own call with no per-incident click — but only when it repeats a fix the platform already verified for the same alert on the same service. Everything else still waits for a person.

It is off by default. Two switches on Guardrails & cost must both be on:

"A verified precedent" means, in plain words, that all of this is true:

  1. The same alert came back on the same service: a repeat of an earlier incident, not a reopen of this one.
  2. Last time, this runbook route — at exactly this revision — made the fix.
  3. The platform verified that fix. A verdict a person recorded by hand does not count.
  4. The alert source itself reported every alert of that incident cleared, after the fix.
  5. The fix held through the post-close check (its last-known-good record exists), nothing since says it did not hold, it did not fail to hold twice in 30 days, and it is less than 30 days old.
  6. The call it would make, and the write connection it would use, are exactly the ones that made the verified fix.

So the first time an alert happens, a person releases the runbook. When the same alert comes back, the platform may repeat that exact, verified fix by itself.

Before you start

Set it up like the demo

The demo workspace runs this on one EC2 instance whose CloudWatch alarm fires when the instance's metadata service is used without a token (the MetadataNoToken metric, dimension InstanceId). The fix makes the instance require IMDSv2. The alarm's dimension, the instance id, becomes the incident's service, so the incident key is service=i-0123456789abcdef0.

1. The alarm

Give the alarm the description severity=warning — instance metadata used without a token. Point its ALARM and OK actions at the SNS topic subscribed to your intake address, /webhook/cloudwatch-sns/<workspace> (the address and its token are on Alert intake & tokens (in the product: /portal/tokens)). Leave INSUFFICIENT_DATA without an action: the intake reads it as firing.

2. The runbook route

POST /api/aiops/{tenant_id}/routes (datasources.manage):

{"name": "remediate-imdsv2-web-1", "priority": 40, "selector": {"service": "i-0123456789abcdef0"}, "mode": "api",
 "datasource_id": "<aws write connection id>", "enabled": true,
 "params": {"operations": ["aws.ec2.require_imdsv2"],
   "service": "ec2", "region": "ap-southeast-1", "action": "ModifyInstanceMetadataOptions", "version": "2016-11-15",
   "params": {"InstanceId": "i-0123456789abcdef0", "HttpTokens": "required"},
   "snapshot": {"service": "ec2", "region": "ap-southeast-1", "action": "DescribeInstances",
                "version": "2016-11-15", "params": {"InstanceId.1": "i-0123456789abcdef0"}},
   "rollback": {"service": "ec2", "region": "ap-southeast-1", "action": "ModifyInstanceMetadataOptions",
                "version": "2016-11-15", "params": {"InstanceId": "i-0123456789abcdef0", "HttpTokens": "optional"}},
   "change_window": {"days": ["mon", "tue", "wed", "thu", "fri"], "hours": "01:00-23:00"}}}

A runbook that runs on its own carries fixed values only: no ${…} placeholder anywhere, so the bytes an approver certified are the bytes that run. That is why the demo has one runbook per instance.

3. Pre-approved operations

On Guardrails & cost → Pre-approved operations, tick aws.ec2.require_imdsv2 and save (members.manage). Every operation the route lists must be ticked. An operation that only undoes a fix (such as aws.ec2.restore_metadata_options) never runs on its own, and every operation must belong to the connection's own cloud.

4. Ask for certification, then certify the route

  1. The route editor asks: on Legacy remediation routes (in the product: /portal/datasources/legacy-routes) (no menu entry) Edit, tick Pre-approved (L1 auto-fix) and save, or send "preapproved": true on POST or PATCH /routes. That is a certification request on the approvers' Needs you; a route nobody asked about is on nobody's.
  2. An approver certifies: Needs you → Certify (or Certify on the route's row), read the revision and parameters, say why, certify. Through the API it is POST /api/aiops/{tenant_id}/routes/{route_id}/certification (approvals.decide) with {"action": "certify", "revision": "<revision from GET /routes>", "note": "…"}; through MCP, certify_route.

A later change to the route's name, selector, mode, connection, parameters or tier drops the certification. The chapter Runbooks and automatic fixes — set it up like the demo covers certification in full, and the GitOps runbooks, ticket routes and switches around it.

5. Turn the switches on

Guardrails → Automatic API fixes for proven runbooks: the one switch, off by default, which also needs Allow pre-approved routes to auto-fire on the Pre-approved auto-fix card; the Validation checks (L6) card below decides how the repeated fix is verified.
Guardrails → Automatic API fixes for proven runbooks: the one switch, off by default, which also needs Allow pre-approved routes to auto-fire on the Pre-approved auto-fix card; the Validation checks (L6) card below decides how the repeated fix is verified.

PATCH /api/aiops/{tenant_id}/guardrails (members.manage):

{"auto_remediation": true, "runbook_routes_with_typed_plans": true, "auto_remediation_direct": true}

runbook_routes_with_typed_plans lets the analysis name the route instead of writing typed steps in a workspace that has write connections, as the demo does. On the page these are Allow pre-approved routes to auto-fire, Let the analysis pick a matching route instead of typed steps and Allow certified API runbooks with a verified precedent to run on their own.

6. The first occurrence: a person releases it

The alarm fires and the analysis names remediate-imdsv2-web-1. The incident's Timeline shows Pre-approved route matched — not run — No verified earlier fix of this alert by this runbook revision: this is not a repeat of an earlier alert. An approver releases the fix from the incident. The platform records the before-state, makes the call and starts verifying at once. The alarm goes back to OK, the incident resolves, and after the post-close check (one hour by default) its last-known-good record lands.

7. The same alarm again: the platform repeats the fix

The next time the alarm fires on that instance, the analysis names the route again and the Timeline shows Fix applied automatically (pre-approved). It must fire as a new incident: where the workspace keeps a reopen window (Alert intake & tokens → Intake rules), an alarm back inside it reopens the old incident instead, and a reopen always waits for a person. The change record says who certified the runbook, which earlier change it repeats, the before-state it captured and the rollback it prepared.

Every guard, and what to change when one stops a run

A guard that stops a run leaves one Pre-approved route matched — not run row on the incident's Timeline, with the reason below. The rows marked Needs you are also listed for the people who edit routes, because a change to the route or a setting fixes them; the others are about one incident.

Reason shown What to do Needs you
Only API routes may run on their own; a … route waits for a person Nothing: command-line, MCP and network-device routes never make a live write on their own. no
An API route: automatic API fixes are off Turn on Allow certified API runbooks with a verified precedent to run on their own. no
Pre-approved before certification existed — an approver must certify it … An approver certifies the route (Needs you lists it). no
The route changed after it was certified An approver certifies the new revision. yes
Its certifier can no longer approve — an approver must confirm it Another approver certifies it again. no
Only a runbook route (named remediate-…, with a selector) may make API calls on its own Name it remediate-… and give it a selector. yes
Its operations are not all on Guardrails → Pre-approved operations, or one only undoes a fix List the route's operations in params.operations, tick each one on Pre-approved operations; an undo operation never runs on its own. yes
Its call is not exactly what its one declared operation does (…) Declare exactly one operation and make the call that operation's own call on one target (step 2): the same action and fixed values, nothing added. yes
Its call uses incident values (${…}) … Replace every placeholder with a fixed value: one runbook per resource. yes
It declares no snapshot read, so no before-state can be captured Add a read-only params.snapshot call. yes
It declares no rollback Add params.rollback. yes
The alert that opened the incident does not match the route's selector The selector is checked against the alert that opened the incident's current episode (after a reopen, the alert that reopened it), among its own alerts — never one that joined later or one a merge brought in from another service. Fix the selector or the alert's labels. yes
The fix targets a resource of an alert merged into this incident, not the incident's own The route's fixed target is the resource of another service's alert that a merge, a fold or the grouping wait brought into this incident. Release the right fix yourself; narrow the selector so this runbook matches only the alerts of the resource it writes to. no
More than one certified API runbook matches — a person picks Narrow the selectors so one runbook matches. yes
A P1 or critical incident (or an emergency change) never runs on its own: a person releases it Nothing: through this lane a P1 or critical incident is always released by a person (a step runbook's exact match is not held back this way). A CloudWatch alarm with no severity= in its description arrives critical. no
The analysis asked for a person Read the analysis's escalation reason and release it yourself. no
The incident reopened — a person decides Release it yourself: a reopen — the alert back inside the reopen window, or a check that found the condition still present after a close or after a fix — means the last fix did not hold. no
This route already ran on this incident — a person releases the next run Look at that run on the incident and release the route again yourself if it should run again. The platform repeats a verified fix as an occurrence's first write, never as a second try. no
Outside the change window (…) Wait for the route's or the workspace's window, or release it yourself. no
A change freeze is in force (…) Wait for the freeze to end. no
An earlier automatic run of this route is not verified yet, or failed — a person releases the next one Look at the earlier run. Once a person's release of this route succeeds and is verified, automatic runs resume. yes
No verified earlier fix of this alert by this runbook revision: … Release it yourself: a verified release becomes the next occurrence's precedent. The words after the colon say which condition failed. no

The words after No verified earlier fix… are one of: this is not a repeat of an earlier alert, the last occurrence has no last-known-good record yet, the last fix was verified by a person, not by the platform, the last fix did not hold, this fix did not hold twice in 30 days, the last fix is older than 30 days, the last occurrence was fixed another way, the alert source never reported the condition cleared after the fix, the route changed since that fix, the call would differ from the verified one or the write connection changed since that fix.

Every other rule of automatic fixes still applies: tier L2 or below (a wide blast radius or a forced L3 never runs on its own), not an unmapped or flapping incident, not a fix that did not hold twice in 30 days, never a compliance control, scanner finding, vulnerability or security alert (a finding is fixed only after a person approves it), within the cost limits and not while agents are paused, not in computer-assist mode, with a valid licence, and at most one automatic fix per incident. A release refused before anything was recorded does not use up that one try, nor does one a switch, Pause all agents or a cost limit stopped right before the write: nothing ran, so a person — or the next automatic try — may still release the same action.

What the incident and change pages show

After the write: verify, rollback, demotion

Five ways to stop it

  1. Turn off Allow pre-approved routes to auto-fire: every automatic fix stops, even one whose before-state is being read — the switches, Pause all agents and the cost limits are read again right before the write.
  2. Turn off Allow certified API runbooks with a verified precedent to run on their own: API runbooks wait for a person again; pull-request routes are unaffected.
  3. Withdraw the route's certification.
  4. Disable the route.
  5. Pause all agents on the AI budgets & kill switch card.

API reference

Call Permission What it does
GET /api/aiops/{tenant_id}/guardrails any member auto_remediation_direct: the value in force
PATCH /api/aiops/{tenant_id}/guardrails with {"auto_remediation_direct": true} (or false, or null) members.manage turns it on or off; null follows the platform default. Refused (409) in computer-assist mode, which also turns it off
PATCH /api/aiops/{tenant_id} with {"settings": {"aiops_auto_remediation_direct": true}} members.manage the same setting; a JSON boolean or null only
POST /api/aiops/{tenant_id}/routes, PATCH /api/aiops/{tenant_id}/routes/{route_id} datasources.manage write the runbook route
POST /api/aiops/{tenant_id}/routes/{route_id}/certification approvals.decide certify or withdraw it

Through MCP the same calls are patch_guardrails, patch_tenant, create_route, patch_route and certify_route. Staff set the platform default with AIOPS_AUTO_REMEDIATION_DIRECT (off).

What this does not protect against

Next steps