Network Automation

Advanced EEM: Tcl, Multi-Event Correlation, and EEM + Python

Advanced EEM - an applet firing and capturing device state with $_cli_result on Cisco IOS XE
In: Network Automation, Labs, CCIE

EEM - the Embedded Event Manager - is the router's built-in automation engine, and it has been there, on every IOS device, since long before "network automation" was a buzzword. It watches for events and takes actions, entirely on the box, with no external system. Most engineers use it for one-line applets and stop there. The expert territory is multi-event correlation, Tcl policies, and EEM as the trigger for on-box Python - which is where EEM becomes genuinely powerful.

This article covers advanced EEM, with a real applet firing and capturing device state from a CML lab. It extends the network automation guide.

The EEM model: event → action

Every EEM policy is an event detector plus a set of actions. When the event fires, the actions run. The event detectors cover an enormous range - syslog patterns, SNMP thresholds, interface state, CLI commands, timers, counters, IP SLA results, and more - and the actions can run CLI commands, send syslog, set counters, email, or launch scripts.

A single-event applet, fired for real

From the lab, an applet that watches for a loopback going down, then captures and logs the interface state:

event manager applet LOOP-FLAP-GUARD
 event syslog pattern "Loopback99, changed state to down" maxrun 60
 action 1.0 syslog msg "EEM triggered: Loopback99 went down"
 action 2.0 cli command "enable"
 action 3.0 cli command "show ip interface brief | include Loopback99"
 action 4.0 syslog msg "EEM captured state: $_cli_result"
 action 5.0 increment flapcount 1

We triggered it by shutting Loopback99, and it ran the full action chain:

R1#show logging | include EEM
%HA_EM-6-LOG: LOOP-FLAP-GUARD: EEM triggered: Loopback99 went down
%HA_EM-6-LOG: LOOP-FLAP-GUARD: EEM captured state:
   Loopback99  10.99.99.99  YES manual administratively down down

R1#show event manager history events | include LOOP
1  1  Actv success  Sun Jul12 09:39:58 2026  syslog  applet: LOOP-FLAP-GUARD

Read what happened: the event fired, the applet issued a live show command, and the crucial part - the $_cli_result built-in variable carried that command's output into the follow-up syslog message. The applet did not just react to the event; it captured the device's state at the moment of the event and logged it. That is the pattern that makes EEM a diagnostic tool: catch the state the instant something happens, before it changes.

Multi-event correlation

A single event is easy. The expert feature is correlating multiple events - "act only if A and B happen within a window", or "act if A or B". This is how you avoid false-positive reactions and build genuinely intelligent triggers.

event manager applet MULTI-EVENT
 event tag EV1 syslog pattern "clock"
 event tag EV2 none
 trigger
  correlate event EV1 or event EV2
 action 1.0 syslog msg "EEM multi-event correlation fired"

Each event gets a tag, and the trigger/correlate block defines the logic - and, or, with optional timing windows. From the lab, the registration confirms the correlation:

R1#show event manager policy registered | include MULTI
2  applet  user  multiple  Off  ...  MULTI-EVENT
 EV2: none: policyname {MULTI-EVENT} sync {yes}

The event type multiple is the tell - this applet is watching several events and applying logic across them, not reacting to one. The real use cases are powerful: "shut the interface only if both the error counter is high and the link is flapping", or "alert if the primary and the backup both fail". Correlation turns EEM from a reflex into a decision.

EEM Tcl policies: when applets are not enough

Applets are declarative and limited - a fixed list of actions. When you need real logic - loops, complex parsing, data structures, calculations - you write an EEM Tcl policy. Tcl (Tool Command Language) is a full scripting language, and IOS runs Tcl policies as EEM events:

event manager directory user policy flash:/eem_scripts
event manager policy monitor_bgp.tcl type user

Inside the Tcl policy, you have the EEM Tcl library - register for an event, run CLI commands, parse their output with Tcl's string handling, make decisions, and take actions. A Tcl policy can do things an applet cannot: iterate over all BGP neighbours and act on each, parse a complex show output, maintain state across runs. IOS also has an interactive tclsh for testing Tcl one-liners on the box.

Tcl is showing its age - Python is the modern choice - but it is deeply embedded in IOS and remains the way to do complex on-box logic within EEM on any platform, including the ones without Guest Shell.

EEM + Python: the modern combination

On platforms with Guest Shell, EEM's most powerful pattern is launching an on-box Python script as an action. The applet detects the event; Python does the heavy lifting:

event manager applet HIGH-CPU-DIAG
 event snmp oid 1.3.6.1.4.1.9.9.109.1.1.1.1.7.1 get-type exact entry-op ge entry-val 90 poll-interval 10
 action 1.0 cli command "guestshell run python /flash/cpu_diagnostics.py"

Now the router responds to a CPU spike by running a full Python diagnostic script - capturing process lists, top talkers, whatever the script does - autonomously. This is the best of both: EEM's rich event detection triggering Python's expressive logic. (It requires a Guest-Shell-capable platform, which our lightweight lab image lacks - the EEM side is fully real, the Python-launch side is documented reference, as covered in the on-box Python article.)

Practical EEM patterns

State capture on event
The lab's pattern - catch show output the instant something fails, using $_cli_result. Invaluable for intermittent problems you cannot catch by hand.
Scheduled maintenance
A cron timer event runs a nightly config backup or a health check - the router schedules its own housekeeping.
Auto-remediation
Detect a known failure signature and fix it - clear a stuck process, bounce an interface, fail over - without waking anyone.
Threshold alerting
An SNMP-threshold event triggers a targeted alert with captured context, richer than a raw trap.

Cautions

  • Set maxrun. Bound how long an applet can run, or a misbehaving policy can hang. The lab used maxrun 60.
  • Beware self-triggering loops. An applet that reacts to a syslog and generates a syslog can trigger itself. Match patterns carefully.
  • Test on a lab device. An auto-remediation applet that gets the logic wrong can make an outage worse. Prove it before deploying.
  • Rate-limit destructive actions. Use counters and ratelimit so a flapping condition does not trigger a destructive action dozens of times.

Key takeaways

  • EEM is the router's on-box automation engine - event detectors plus actions, no external system. It has been in IOS for two decades.
  • The lab's real applet captured device state at the moment of an event using $_cli_result - the pattern that makes EEM a diagnostic tool for intermittent problems.
  • Multi-event correlation (event tags + a trigger/correlate block with and/or logic) turns EEM from a reflex into a decision. Registration shows event type multiple.
  • Tcl policies give you full scripting logic when applets are too limited - loops, parsing, state - on any platform.
  • EEM + on-box Python is the modern combination: rich event detection triggering expressive Python (on a Guest-Shell-capable platform).
  • Always set maxrun, avoid self-triggering loops, rate-limit destructive actions, and test on a lab device first.

Next: model-driven telemetry on IOS XE routers - gRPC dial-out in practice. The full cluster index lives on the network automation pillar.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.