Data science via agentic exploration: Parsing the NOC inbox

In my last two articles1, I used a local AI agent (pi) to inspect a router configuration and to port a network utility to a different programming language. Those are impressive actions for systems engineering, but they still operate on small, bounded files.

What happens when we point an agent at a pile of unstructured data?

If you run a Network Operations Center (NOC), you know that your mailing lists and ticketing systems are absolute goldmines of operational intelligence. Hidden inside years of noc@cybera.ca emails are trends about fiber cuts, hardware degradation, and routing anomalies. The problem is that parsing years of plain-text emails into a queryable dataset usually requires days of writing custom Python scripts and Regex filters.

Let’s see if our agent can skip the busywork and help us prepare and explore the data. The agent can build the tools and run the queries, but interpreting the results is still our responsibility.

Formatting the raw data

For this exercise, I exported an archive of the Cybera NOC mailing list. The archive ended up as two standard .mbox formatted files, totalling 7.4 GB in size. These files contain thousands of raw email headers, timestamps, and body text spanning several years back.

These archives contain internal staff communications and operational information, so I treated them as sensitive data. The files, the agent, and the inference service all remained on infrastructure controlled by Cybera. Any examples included in this article have been reviewed so that internal details are not unintentionally published.

Before I begin exploring this data, I’d like to know how the agent prefers to have the data available:

Prompt: This directory contains mailing list archives of our NOC, presented as two mbox files, for data analysis purposes. Before we begin analyzing, please suggest the best format we should use. You can create a Python virtual environment in ./venv if that will help. Please ask for permission before installing anything else.

The agent then prompted me with four questions:

Once I answered all of the questions, I approved the package installation it had proposed. The agent then installed the required Python packages and wrote a script to convert the mbox files into Parquet. I have heard of Parquet, but I’ve never used it. This seems like a good opportunity to try a new tool!

When the agent was finished, it presented this report:

 Here's the summary:

 Results

┌───────────────────────────┬───────────────────────────────────┐
│ Metric                    │ Value                             │
├───────────────────────────┼───────────────────────────────────┤
│ Total messages parsed     │ 186,335                           │
├───────────────────────────┼───────────────────────────────────┤
│ Date range                │ 2012-04-01 → 2026-04-27           │
│                           │ (14 years)                        │
├───────────────────────────┼───────────────────────────────────┤
│ Mailing lists             │ noc@cybera.ca (128,465),          │
│                           │ network@cybera.ca (57,869)        │
├───────────────────────────┼───────────────────────────────────┤
│ Messages with attachments │ 12,977 (7%)                       │
├───────────────────────────┼───────────────────────────────────┤
│ Distinct senders          │ 4,197                             │
├───────────────────────────┼───────────────────────────────────┤
│ Distinct subjects         │ 26,291                            │
├───────────────────────────┼───────────────────────────────────┤
│ Parquet file size         │ 347 MB (down from 7.4 GB mbox)    │
└───────────────────────────┴───────────────────────────────────┘

 
 Output file: mailing_lists.parquet

Querying the formatted data

Now that the data is in a more structured form, I can start querying and investigating it.

First, I want to know which emails are “system” emails and which are from real people. This will help with future queries.

Prompt: Please review all emails and determine which emails are from system crons, monitoring systems, alerting, or other automated notifications. Store the results in a file so we can include or exclude them for future queries.

This time the agent has created itself a TODO list, which is a way of keeping track of actions that require several distinct steps.

The agent finishes with:

 Classification complete. Here's the summary:

 Results

 ┌────────────────┬─────────────────┐
 │ Metric         │ Value           │
 ├────────────────┼─────────────────┤
 │ Total messages │ 186,334         │
 ├────────────────┼─────────────────┤
 │ Automated      │ 146,068 (78.4%) │
 ├────────────────┼─────────────────┤
 │ Human          │ 40,266 (21.6%)  │
 └────────────────┴─────────────────┘

 24 Automation Categories Detected

┌───────────────────────────────────────────────────┬───────────┐
│ Category                                          │ Count     │
├───────────────────────────────────────────────────┼───────────┤
│ CMDB Monitoring                                   │ 62,960    │
│ Sensu Monitoring                                  │ 30,125    │
│ DDoS Protection (FastNetMon)                      │ 14,770    │
│ Config Backup (RANCID)                            │ 6,455     │
│ LMC (Library Management)                          │ 6,415     │
│ BGP Alerting (from + subject)                     │ 5,879     │
│ Nagios Monitoring                                 │ 3,533     │
│ NPM (SolarWinds)                                  │ 2,175     │
│ Cron Jobs                                         │ 2,101     │
│ DDoS Protection (FastNetMon Guard)                │ 1,837     │
│ Firewall (Palo Alto Updates)                      │ 1,301     │
│ Syslog (rsyslog)                                  │ 1,294     │
│ Incident Management (PagerDuty)                   │ 1,225     │
│ Vendor (Juniper)                                  │ 1,012     │
│ Firewall (local alerts)                           │ 877       │
│ Internet Monitoring (BGPmon)                      │ 783       │
│ Firewall (Palo Alto Support)                      │ 741       │
│ Network Trace (intrace)                           │ 714       │
│ Internet Monitoring (Kentik)                      │ 638       │
│ ISP/Transit (Hurricane Electric)                  │ 442       │
│ Vendor (Juniper Subscriptions)                    │ 364       │
│ Fail2Ban Security Alerts                          │ 178       │
│ E-commerce Notifications (FS.COM)                 │ 178       │
│ Compliance Reporting (MANRS)                      │ 71        │
└───────────────────────────────────────────────────┴───────────┘

The agent was able to identify 24 different categories of automated messages on its own. Let’s see how it determined these results:

Prompt: What method did you apply to determine these classifications?

The agent responded with a 100-line summary of its method. I then asked it to summarize the method for a non-technical audience:

How We Told Human Emails Apart from Computer-Generated Ones

The basic idea is like sorting a huge pile of mail by looking at who sent it and what it's about.

We went through two steps:

### Step 1: Check the Sender (The Main Filter)

Most automated emails come from recognizable "senders" — not real people, but systems with consistent identities. For example:

- An email from "CMDB Alert" is always the configuration database sending out notices
- An email from "Sensu Monitoring" is always the server health checker
- An email from "nagios@monitor.cybera.ca" is always the network watchdog

For each of these known senders, we created a rule that says: "If the email comes from this sender, it's automated."

But we added a safety check: the sender's email domain must also match. This prevents a false alarm. For example, if a real person happens to have "Cron" in their display name, we check that their email actually comes from a known server like localhost before labeling it as a cron job. This keeps humans from being misclassified.

We built about 35 sender rules covering all the major automated systems we found.

### Step 2: Check the Subject Line (The Safety Net)

Some automated emails come from senders our first pass didn't catch — maybe they're sent through a generic gateway or from a partner organization. For these, we look at the subject line, which often gives it away:

- "This is an alert from your SolarWinds server" → automated monitoring alert
- "MANRS Weekly Report" → automated compliance report
- "BGP alert: hijack" → automated network security notice

These subject-only rules only apply when Step 1 didn't already classify the email, so we never double-count.

### What We Found

Out of 186,334 emails over 14 years:

- 78.4% were automated (146,068 emails from 24 categories of systems)
- 21.6% were human-written (40,266 emails from actual people having conversations)

### Why This Approach Works Well

- Transparent — you can trace any classification decision back to the exact rule that triggered it. No black box.
- Consistent — the same sender will always get the same label.
- Auditable — we saved the full classification list so anyone can review, challenge, or update the results.

### Where It Falls Short

- It only knows what we told it to look for. If a new automated system starts sending emails tomorrow, it won't be caught until we add a rule for it.
- It can't read the message body. Some automated emails are cleverly disguised as human writing, and we wouldn't catch those.
- It requires upfront work. Someone had to look at the data, spot the patterns, and write the rules.

In short: we built a sorting guide based on recognizable sender names and subject-line patterns, with a domain-check safeguard to keep things accurate. It's not artificial intelligence — it's a carefully crafted set of if-then rules that proved effective for this particular collection of emails.

Now, it’s very possible the agent didn’t detect all possible categories, and there are actually more than 24 different types of automated messages. If this was a critical data analysis project, it would be a requirement to review the results in detail as well as spot-check the data by random sample analysis. For this article, I’m going to leave the results as-is.

For the next query:

Prompt: Using the classifications you just created, I want to know what the busiest day of the week is for both automated and non-automated emails. Please create two separate ASCII-formatted histograms showing the daily email traffic for the week, one for automated messages and one for humans. Note that I am located in Calgary, so reports should be based on Mountain Time.

The results are:

Here are the two histograms (Mountain Time, Calgary):

────────────────────────────────────────────────────────────

Automated Emails (78.4% of traffic)

The busiest day is Tuesday — a spike to 28,812 messages. The weekend is notably active too (Saturday at 20k), confirming that monitoring/alerting systems don't observe business hours.

Human Emails (21.6% of traffic)

The busiest day is Wednesday — a flatter 8,637 messages. Human traffic follows a clean Monday–Friday work week pattern and drops to near-zero on weekends (1,026 Sat / 772 Sun).

Comparison

┌───────────┬────────────────────┬────────────────────┬─────────┐
│ Day       │ Automated          │ Human              │ Total   │
├───────────┼────────────────────┼────────────────────┼─────────┤
│ Monday    │ 20,140             │ 7,250              │ 27,390  │
├───────────┼────────────────────┼────────────────────┼─────────┤
│ Tuesday   │ 28,812 ← auto peak │ 8,386              │ 37,198  │
├───────────┼────────────────────┼────────────────────┼─────────┤
│ Wednesday │ 24,455             │ 8,637 ← human peak │ 33,092  │
├───────────┼────────────────────┼────────────────────┼─────────┤
│ Thursday  │ 23,911             │ 7,950              │ 31,861  │
├───────────┼────────────────────┼────────────────────┼─────────┤
│ Friday    │ 16,720             │ 6,245              │ 22,965  │
├───────────┼────────────────────┼────────────────────┼─────────┤
│ Saturday  │ 20,474             │ 1,026              │ 21,500  │
├───────────┼────────────────────┼────────────────────┼─────────┤
│ Sunday    │ 11,556             │ 772                │ 12,328  │
└───────────┴────────────────────┴────────────────────┴─────────┘


Key takeaway: Automated traffic peaks on Tuesday while human traffic peaks on Wednesday — the two busiest days don't align, reflecting the fact that monitoring systems run continuously and their alert patterns (e.g., CMDB sync runs, Sensu checks on assets deployed Tue/Wed) differ from human operational correspondence patterns.

But… no histograms.

Prompt: You didn’t include the ASCII-formatted histograms in your response. Please include them.

+---------------------------------------------------------------+
|        Automated Emails by Day of Week (Mountain Time)        |
+---------------------------------------------------------------+
|Monday     [####################        ]  20,140              |
|Tuesday    [############################]  28,812  <-- BUSIEST |
|Wednesday  [########################    ]  24,455              |
|Thursday   [#######################     ]  23,911              |
|Friday     [################            ]  16,720              |
|Saturday   [####################        ]  20,474              |
|Sunday     [###########                 ]  11,556              |
+---------------------------------------------------------------+


+---------------------------------------------------------------+
|          Human Emails by Day of Week (Mountain Time)          |
+---------------------------------------------------------------+
|Monday     [########################    ]   7,250              |
|Tuesday    [########################### ]   8,386              |
|Wednesday  [############################]   8,637  <-- BUSIEST |
|Thursday   [##########################  ]   7,950              |
|Friday     [####################        ]   6,245              |
|Saturday   [###                         ]   1,026              |
|Sunday     [##                          ]     772              |
+---------------------------------------------------------------+

Let’s do one more. One of the alerts our network team receives is when a member hits their IBG/transit cap, meaning they’re using all of the bandwidth they have subscribed to. Let’s see if there’s a pattern for this happening at a specific time of the year. My guess is the month of May.

Prompt: Please query for emails from Sensu containing “bandwidth_limit” and failing. Create a histogram based on months in the year, to determine which month has the highest frequency of these emails.

Turns out, it’s February:

+---------------------------------------------------------------+
| Sensu 'bandwidth_limit' Failing Alerts  (2022-2026 Combined)  |
|       Aggregated by Calendar Month  (all years summed)        |
+---------------------------------------------------------------+
|  Jan   [####################          ]      605              |
|  Feb   [##############################]      919  <-- BUSIEST |
|  Mar   [############################  ]      859              |
|  Apr   [#################             ]      538              |
|  May   [################              ]      502              |
|  Jun   [#############                 ]      413              |
|  Jul   [#########                     ]      275              |
|  Aug   [#############                 ]      402              |
|  Sep   [##################            ]      563              |
|  Oct   [##################            ]      563              |
|  Nov   [#########################     ]      758              |
|  Dec   [###################           ]      597              |
|                                                               |
+---------------------------------------------------------------+
|  Total:    6,994  alerts across 5 years                       |
|  Peak:       919  alerts in Feb  (13.1% of total)             |
+---------------------------------------------------------------+

The combined pattern shows a clear seasonal shape:

- February (919) is the busiest month overall — the sharp peak is driven heavily by the 2026 February anomaly (516 alerts in one month alone, 55% of that year's total so far).
- March (859) and November (758) are the next highest — November was also the peak in 2023 and 2025 independently, so this is a consistent pattern, not an anomaly.
- July (275) is the absolute trough — a sharp summer collapse seen across all 5 years.
- April–May and August form a shallow valley between the winter peak and the summer low.

The shape suggests two distinct drivers: a winter operational load (Feb–Mar, Nov–Dec) and a summer lull (Jun–Jul), with the 2026 February spike being an outlier on top of an already-strong February baseline.

The 2026 Winter Olympics happened during February, so that explains the anomaly. This was enough to skew February as the overall busiest month. A follow-up query I could have done would have been to omit February 2026 to see the next highest month.

Conclusion

There are so many other queries I could write about: correlation of BGP alerts, potential DDoS attacks, searching for the most common questions and creating a FAQ.

This is the power of agentic exploration. The agent didn’t just give me an answer; it built the bespoke tooling required to find the answer, debugged its own code, and executed the analysis. Historically, it would have taken me at least a day to get this data into a database, and at least a half day to figure out the math and statistics for each of the questions I wanted to ask. This exercise with the agent took 30 minutes.

We now have the opportunity to process and understand knowledge with the ease and speed we’ve never seen before. This alone will open so many new doors, create new opportunities, and increase our understanding of our community.

However, all of this magic comes at a cost. Over the last three posts, I’ve had our local model churning through context windows, writing code, and compiling software. In the coming months, I’ll dig into the economics involved with this new type of processing.


Missed the previous blogs in this series?
Pt. 1: A primer on agentic AI for network administrators
Pt. 2: Inference Services
Pt. 3: Vendor lock-in, open models, and architectural choice
Pt. 4: Using an AI Agent for Network and Systems Operations
Pt. 5: Porting ping with an agent

  1. See above for links to the previous blogs in this series ↩︎

Leave a Comment

Your email address will not be published. Required fields are marked *