Introduction to Auto‑Remediation and Root Cause Analysis
Auto‑remediation agents observe telemetry, infer a probable fault, and apply corrective actions without human intervention. In network and infrastructure contexts they typically:
- Detect an anomaly (e.g., interface flap, CPU spike, BGP session loss).
- Hypothesize a root cause using rule‑based reasoning, correlation, or lightweight ML models.
- Act by pushing a remediation payload (CLI, NETCONF/RESTCONF, API call) intended to restore service.
The agent operates inside a safe time window (STW) – a pre‑defined interval during which it may attempt auto‑remediation before the risk of uncontrolled change outweighs the benefit. If the agent cannot prove the hypothesized root cause within the STW, it must cease further autonomous action and hand control to operators.
Root cause analysis (RCA) provides the evidentiary basis that a remediation action addresses the underlying fault rather than merely suppressing symptoms. Without proven RCA:
- Mis‑directed changes can exacerbate the problem (e.g., disabling a healthy link while the real issue is a mis‑configured ACL).
- Rollback uncertainty increases because the inverse operation may not be known or safe.
- Operator trust erodes, leading to manual overrides that bypass safety controls.
Consequently, the design of stop conditions, escalation rules, and operator intervention points must be anchored to the agent’s ability to prove causality within the STW.
Stop Conditions for Auto‑Remediation
Time‑Based Stop Conditions
A hard timeout is the most deterministic guard.
| Parameter | Typical Value | Rationale | Implementation Note |
|---|---|---|---|
max_attempt_duration | 90 s | Allows detection, hypothesis, and one remediation try. | Start a monotonic timer when the first anomaly is observed. |
remediation_retry_interval | 20 s | Prevents tight‑loop retries that could overwhelm the device. | After each failed attempt, sleep this interval before re‑evaluating. |
total_allowed_attempts | 3 | Limits blast‑radius exposure. | Counter incremented after each remediation push; abort when reached. |
If elapsed_time > max_attempt_duration or attempt_count >= total_allowed_attempts, the agent must stop further auto‑remediation and trigger the escalation path.
Threshold‑Based Stop Conditions
Telemetry‑driven thresholds stop the agent when the symptom persists or worsens despite remediation.
- Symptom Persistence Threshold – If the observed metric (e.g., packet loss %) remains above
symptom_thresholdfor two consecutive evaluation cycles after a remediation attempt, stop. - Degradation Threshold – If a secondary metric (e.g., CPU utilization) rises >
degradation_delta(e.g., +15 %) after remediation, abort – the action may have introduced a new problem. - Error‑Rate Threshold – If the agent logs >
max_internal_errors(e.g., 5) validation or communication failures within the STW, cease auto‑remediation to avoid cascading faults.
These thresholds are evaluated after each remediation attempt; they are post‑action validation gates.
External Intervention Stop Conditions
External signals can override internal logic:
- Operator‑Issued Pause – CLI command (
agent pause) or API flag (pause=true) set by an NOC analyst. - Maintenance Window – If a scheduled change window begins, the agent must honor a
maintenance_modeflag and suspend autonomous actions. - Higher‑Priority Alarm – Reception of a severity‑critical event (e.g., power loss) from an external EMS triggers an immediate stop, regardless of internal state.
Implementation: the agent subscribes to a lightweight pub/sub topic (e.g., MQTT agent/control) and checks the payload on each evaluation loop. A STOP payload forces an immediate exit from the remediation routine.
Escalation Rules for Unresolved Issues
Escalation Triggers
An escalation is launched when any stop condition fires and the agent cannot prove root cause. Triggers include:
- Timeout Expiry –
max_attempt_durationexceeded. - Threshold Violation – Symptom persists or degradation observed post‑remediation.
- External Stop – Operator pause, maintenance window, or higher‑priority alarm.
- Internal Fault – Repeated validation/communication errors (>
max_internal_errors).
Each trigger carries a severity tag (low, medium, high, critical) derived from the original symptom’s impact classification.
Escalation Levels and Notifications
| Level | When Activated | Notification Channels | Expected Response Time | Responsible Party |
|---|---|---|---|---|
| L1 – Alert | Low‑medium severity, first timeout | Email, Slack channel #net‑ops‑alerts | 5 min | Tier‑1 NOC analyst |
| L2 – Escalate | Medium‑high severity, threshold violation or external stop | PagerDuty, SMS, voice call | 2 min | Tier‑2 Senior Engineer |
| L3 – Critical | Critical severity, repeated failures, or loss of agent health | PagerDuty (escalation policy), phone bridge, incident‑management ticket auto‑creation | 30 s | On‑call Lead / Incident Commander |
Notifications contain a standard payload:
{
"agent_id": "agent-01",
"timestamp": "2025-11-03T14:22:07Z",
"trigger": "timeout",
"symptom": {
"type": "bgp_session_down",
"peer": "10.0.1.5",
"duration_s": 120
},
"attempts": 2,
"last_action": {
"method": "netconf",
"payload": "<config><bgp><neighbor><peer-address>10.0.1.5</peer-address><enabled>false</enabled></neighbor></bgp></config>"
},
"rca_status": "unproven",
"recommended_next": "manual investigation"
}
Escalation Response and Resolution
Upon receipt, the responder follows a runbook that mandates:
- Acknowledge the alert within the SLA (timestamped acknowledgment).
- Collect raw telemetry (interface counters, logs, SNMP walks) for the affected entity.
- Validate the agent’s hypothesis by attempting a manual remediation (if safe) or gathering further evidence.
- Document findings in the incident ticket, marking the RCA status as proven, unproven, or inconclusive.
- Decide on next steps:
- If RCA proven → apply permanent fix, close ticket.
- If RCA unproven but symptom mitigated → observe for recurrence, schedule a post‑mortem.
- If symptom worsens → invoke higher‑level escalation (L2→L3) or initiate a network‑wide safety hold.
All actions are logged to an immutable audit store (e.g., WORM‑enabled S3 bucket) to satisfy compliance and facilitate post‑incident analysis.
Operator Intervention Points
Identification of Intervention Points
Intervention points are deliberately placed before the agent commits a change that cannot be safely reverted automatically.
| Point | Description | Pre‑check | Commit Boundary | Verification Gate | Rollback Trigger | Blast‑Radius | Operator Role |
|---|---|---|---|---|---|---|---|
| P1 – Hypothesis Validation | Agent presents candidate root cause + remediation plan. | Confirm telemetry anomaly exists; check device health (CPU < 80 %, no ongoing maintenance). | None (still planning). | None. | N/A | Single device. | Operator reviews plan, can approve, modify, or reject. |
| P2 – Pre‑Change Safety Check | Dry‑run of remediation (e.g., netconf validate-only or show config replace dry-run). | Validate syntax, check for conflicting configs (e.g., ACL overlap). | None. | Dry‑run success/failure. | If dry‑run fails → abort. | Single device. | Operator can override dry‑run result if confident. |
| P3 – Change Application | Actual push of remediation payload. | None (relies on P2). | Commit – when the device acknowledges the config. | Post‑apply verification (metric returns to baseline within verify_window). | If verification fails → automatic rollback (if supported) or raise alarm for manual rollback. | Limited to the device(s) targeted. | Operator monitors verification; can issue manual rollback command. |
| P4 – Post‑Change Observation | Observation window after successful verification. | None. | None. | Continued metric health for observe_window (e.g., 5 min). | If metric degrades → trigger L2 escalation. | Same as P3. | Operator may decide to extend observation or initiate further actions. |
If the agent cannot prove root cause before P1, it must halt at P1 and escalate.
Operator Notification and Alerting
At each intervention point, the agent emits a structured event to the ops bus:
- P1 –
agent/plan/proposed - P2 –
agent/plan/dryrun(includes dry‑run result) - P3 –
agent/change/applied(includes config diff) - P4 –
agent/change/observed(includes metric snapshot)
Operators subscribe to these topics via a monitoring platform (e.g., Grafana Alerting, Splunk). Alerts include a deep link to the device’s live CLI/snapshot view, enabling rapid inspection.
Operator Intervention Procedures
Standard Operating Procedure (SOP) for a manual intervention at P3 (change application) is:
- Receive
agent/change/appliedevent. - SSH or NETCONF to the target device.
- Verify the applied diff matches the intended remediation (
show config | compare rollback 0). - Check key health indicators (interface state, protocol adjacency, CPU).
- If health is good → acknowledge and close the auto‑remediation ticket.
- If health is degraded → issue the rollback command (if the platform supports atomic rollback, e.g.,
rollback 0on Juniper,configure replace rollback 1on Cisco IOS XR) or apply a known‑good baseline config. - Document the manual action in the incident ticket, marking the RCA status as unproven (since the agent could not prove cause).
All CLI commands used in the SOP are logged automatically via the device’s AAA accounting.
Troubleshooting Unsuccessful Auto‑Remediation
Common Issues and Errors
| Symptom | Likely Cause | Diagnostic Hint |
|---|---|---|
| Agent repeatedly times out without applying change | Network connectivity loss between agent and device (SNMP/NETCONF blocked). | Check telnet <host> 830 or netcat -z <host> 830. |
| Dry‑run succeeds but live apply fails with “invalid configuration” | Device has a pending commit lock or another process holds the config lock. | show configuration session (Juniper) or show lock (IOS XR). |
| Post‑apply verification shows metric unchanged | Remediation did not address the actual fault (mis‑hypothesis). | Compare show tech-support before/after; look for unchanged root‑cause symptom. |
| Rollback command fails with “no rollback buffer” | Platform does not retain rollback history or buffer exceeded. | Verify system rollback settings; increase rollback retention; may need to enable. |
| Agent logs “validation error: missing mandatory leaf” | Payload schema mismatch (e.g., using outdated YANG model). | Pull latest YANG from device (netconf-get-schema) and regenerate payload. |
Debugging and Logging Techniques
- Structured Logging – Emit JSON logs with fields:
timestamp,agent_id,event_type,payload_hash,return_code. Enablelog_level=debugduring troubleshooting. - Packet Capture – Use
tcpdump -i any -s 0 -w agent.pcap port 830 or port 161to capture NETCONF/SNMP exchanges. - Trace IDs – Propagate a UUID (
X-Request-ID) through all agent‑device interactions; correlate logs on both sides. - Metric Snapshots – Before and after each remediation, store a JSON snapshot of relevant MIBs (
ifInOctets,bgpPeerState,cpuUtilization). - Health‑Check Endpoint – Expose
/healthHTTP endpoint returning{status:"ok", last_success:<ts>, pending_attempts:<n>}for external monitoring.
Code Examples for Troubleshooting
Bash snippet to capture NETCONF traffic and validate a dry‑run:
#!/usr/bin/env bash
set -euo pipefail
AGENT_ID="agent-01"
DEVICE="10.0.1.5"
PORT=830
OUTDIR="/var/log/agent/traces"
mkdir -p "$OUTDIR"
TS=$(date +%s)
PCAP="${OUTDIR}/${AGENT_ID}_${DEVICE}_${TS}.pcap"
# Start background capture
tcpdump -i any -s 0 -w "$PCAP" port "$PORT" &
TCPDUMP_PID=$!
# Invoke agent dry-run via its CLI (assuming it exposes a subcommand)
agent-cli --device "$DEVICE" --dry-run --output json > "${OUTDIR}/${AGENT_ID}_${DEVICE}_${TS}_dryrun.json"
DRYRUN_EXIT=$?
# Stop capture
kill "$TCPDUMP_PID"
wait "$TCPDUMP_PID" 2>/dev/null
if [[ $DRYRUN_EXIT -ne 0 ]]; then
echo "Dry‑run failed; see ${OUTDIR}/${AGENT_ID}_${DEVICE}_${TS}_dryrun.json"
exit 1
fi
echo "Dry‑run succeeded. Capture stored at $PCAP"
Python helper to compare pre/post metric snapshots:
import json
from pathlib import Path
def load_snapshot(path: Path) -> dict:
return json.loads(path.read_text())
def compare_snapshots(before: dict, after: dict, keys: list) -> dict:
diff = {}
for k in keys:
b = before.get(k)
a = after.get(k)
if b != a:
diff[k] = {"before": b, "after": a}
return diff
# Example usage
before = load_snapshot(Path("metrics_before.json"))
after = load_snapshot(Path("metrics_after.json"))
relevant_keys = ["ifInOctets", "bgpPeerState", "cpuUtilization"]
changes = compare_snapshots(before, after, relevant_keys)
print(json.dumps(changes, indent=2))
End of document.