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 1We 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-GUARDRead 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 userInside 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
show output the instant something fails, using $_cli_result. Invaluable for intermittent problems you cannot catch by hand.cron timer event runs a nightly config backup or a health check - the router schedules its own housekeeping.Cautions
- Set
maxrun. Bound how long an applet can run, or a misbehaving policy can hang. The lab usedmaxrun 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
ratelimitso 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.