// docs / sop authoring
SOP Authoring
A Standard Operating Procedure (SOP) is a YAML file that tells adoe how to respond to a class of alerts. The AI decision engine matches incoming alerts to SOPs, checks their preconditions, and — when confidence is high — executes the actions automatically.
Anatomy of an SOP
SOPs live as YAML files in the sops/ directory and are loaded at startup. Here's a complete example:
name: cpu_high
description: Handle high CPU alerts
alert_types: # Signals this SOP handles
- cpu_high
- cpu_spike
preconditions: # All must match for this SOP to apply
- field: env
operator: in
value: [prod, staging]
actions: # Executed in order
- type: github_action
repo: infra
workflow: restart-service.yml
inputs:
service: "{{ service }}"
env: "{{ env }}"
timeout: 300
validation: # Confirm remediation worked
check_type: metric
metric: cpu_percent
condition: "< 80"
timeout: 180
rollback:
notify_human: true
pagerduty_escalate: true
confidence_threshold: 0.85
auto_execute: true # false = recommend only
Field reference
| Field | Purpose |
|---|---|
name | Unique SOP identifier. |
description | Human-readable summary (also fed to the AI when selecting between SOPs). |
alert_types | List of alert signals this SOP handles (matched against alert.signal). |
preconditions | Conditions that must all match for the SOP to apply. |
actions | Ordered list of remediation steps. |
validation | Post-execution check that confirms the fix worked. |
rollback | What to do if validation fails (notify / escalate). |
confidence_threshold | Minimum AI confidence required to act on this SOP. |
auto_execute | true runs actions automatically; false only recommends them. |
Preconditions
Each precondition is a field / operator / value triple. Supported operators:
| Operator | Meaning |
|---|---|
eq | field equals value |
ne | field does not equal value |
in | field is one of a list of values |
not_in | field is not in a list of values |
regex | field matches a regular expression |
Common fields are service, env, severity, and signal.
Action types
adoe ships four executors. The type field selects which one runs each action.
GitHub Actions
- type: github_action
repo: org/repo
workflow: workflow.yml
inputs:
key: value
AWS SSM
- type: ssm
document: AWS-RunShellScript
parameters:
commands:
- "systemctl restart myservice"
Shell
- type: shell
command: "kubectl rollout restart deployment/{{ service }}"
DRY_RUN=true while iterating.SSH
- type: ssh
host: "{{ host }}"
command: "sudo systemctl restart {{ service }}"
The SSH executor supports direct connections and bastion-host hops.
Templating
Action fields support Jinja2 templating against the normalized alert, so a single SOP can serve many services. Available variables include {{ service }}, {{ env }}, {{ signal }}, {{ severity }}, and others from the alert payload.
Validation & rollback
After actions run, the agent validates the outcome. check_type may be:
metric— re-read a metric and assert acondition(e.g."< 80").http— hit an endpoint and assert the response.command— run a command and assert its result.
If validation fails, the rollback block decides what happens — typically notify_human: true and pagerduty_escalate: true.
Auto-discovery from GitHub & Confluence
Rather than hand-writing every SOP, adoe can read your existing runbooks and generate SOPs with AI. The onboarding wizard offers this as a step, or you can call the API directly:
# Discover from GitHub repos (scans runbook/sop/playbook markdown)
curl -X POST "http://localhost:8000/sops/discover/github?repos=myorg/runbooks&repos=myorg/infra-docs"
# Discover from Confluence spaces (optionally filter by labels)
curl -X POST "http://localhost:8000/sops/discover/confluence?spaces=OPS&labels=runbook"
Discovered SOPs are saved inactive for safety. Review and activate them before they can run:
# List SOPs, review one, then activate it
curl http://localhost:8000/sops
curl http://localhost:8000/sops/{sop_id}/content
curl -X POST http://localhost:8000/sops/{sop_id}/activate
curl -X POST http://localhost:8000/sops/reload.