Andrew Bengston

Log Review Agent

A local log analysis agent that runs on the engineer’s laptop

A Tier 3 engineer gets a customer log bundle. An example bundle I used during development is 875MB compressed, 1.23GB expanded, 883 files, 19.6 million lines. Somewhere in it is the reason the customer opened a case.

Today that review is manual. The engineer greps, opens files by hand, and works from recall of which of the 883 files matter for which symptom. Nothing carries forward either. When the same fault turns up on another system six months later, the next engineer starts over.

The other half of the problem is that the knowledge exists and cannot be reached. Over the last 25 months, Tier 2 escalated 1,184 consults to Tier 3 across 8,921 emails. Roughly one in three reached a Jira defect. The rest were answered in a mailbox and never written down anywhere a person could search.

How it works

The parser is the engine, the agent is the interface, and defect matching is a secondary feature. I arrived at that ordering by correcting the design twice.

The parser does the extraction deterministically, and everything on screen is parser output rendered directly. The model is a way to ask questions about what the parser already found. It is not the thing that finds it. The practical consequence showed up again and again: when the tool failed to answer a question an engineer actually had, the fix was almost always in the parser and not the model.

The whole thing runs on a 16GB laptop with no network connection. It parses a bundle in seconds, renders it as a readable case report, flags problems as structured findings, and lets an engineer ask about it in plain language. Where a parsed error lines up with a known defect in the on-prem Jira corpus, it surfaces that link.

The hardware envelope is what sets the model choice. A 16GB laptop with no network connection is a hard ceiling, and Phi-4-mini is what fits inside it. The model sits behind a boundary the rest of the application does not depend on, so putting a different one in its place is a minor adjustment and not a rebuild.

The case report screen showing a conversation panel, a system identity strip with values masked, collection health, system state checks, unresolved unknowns, and the first finding.
The case report. System identifiers are masked here; everything else is as an engineer sees it.

What makes it an agent

The model runs a bounded tool-call loop. It receives the question, a trimmed digest of the case, and a set of callable tools. It picks which to call, reads the results, and either calls again or answers. Iterations are capped at five.

There are six tools: full-text search across the Jira defect corpus, a single defect record, a single parsed finding from the current bundle, log line search with explicit scope state, per-disk detail down to enclosure position and slot, and a bounded search across all findings in the bundle.

That loop is what separates this from a chatbot pointed at a document. It retrieves selectively, reasons over what it retrieved, and returns grounded options.

What I learned about how the model behaves

Two properties, each one measured repeatedly on the same bundle and the same question.

A tool shaped like the question changes tool selection. Data that was present but not behind a purpose-shaped tool got ignored in every test. The same data behind a tool was reached on the first call.

Text does not change tool selection, in any position. Four separate attempts, all negative: the case digest, a dedicated narrow-scope advisory note, an instrumented field carrying an explicit hint that named the exact call to make, and a live tool description computed per turn. In the most conclusive test the digest carried three explicit problem flags on three different axes, and the model went to an unrelated search it invented on its own.

Text can change what the model says. It does not change what it does.

That is the most portable thing this project has produced. It means anything that must not happen has to be made structurally impossible, not advised against. Five structural guards now sit where advisory text had failed, and each one removes a decision instead of narrating it. An inconclusive search result carries no match count key at all, so there is nothing to misread as searched and found nothing. The schema cannot express an invalid search scope. Absence assertion is gated on coverage, including unreadable files. A missing decompression library fails at package import, so it cannot degrade quietly in the background.

What the model does, and what it does not

The local model is Phi-4-mini. It does two things: a narrative case summary on explicit request, cached, and the conversation. Nothing runs in the background, and nothing runs on parse or page load.

The exclusions are recorded with reasons. No model-written knowledge contributions, enforced by a test asserting the inference path cannot import the write path. No model-set severity, which comes from structural evidence in the data. No model judgment on relevance. No model-driven deletion or pruning. No background inference of any kind.

The reasoning behind all of that is measurement. The model’s judgment accuracy came in at 30%. That figure describes a small model working inside a laptop’s constraints and is not a ceiling on the approach, so the design keeps consequential decisions away from it and stays trustworthy whichever model occupies the slot. Model-suggested defect candidates exist behind a settings toggle that ships off.

Human judgment is captured instead. An engineer can mark any suggestion correct, incorrect, or unclear, and record the correct defect key and CRM incident when they know them. That record is read by people and feeds the knowledge pack. It never feeds retrieval or ranking.

The verdict capture controls beneath a suggested defect: options to mark it correct, incorrect or unclear, with fields for the correct defect key, solution category, CRM incident, and a note.
Every suggestion can be judged, and the judgement is recorded with the correcting detail.

Security and data handling

The isolation is a property of how the application is built, not a setting. Routing inference through a cloud API would have made no-egress something a person could switch off, so I kept inference local.

There is no outbound internet from the app, because there is no code path for it. Customer log data is read-only and stays on the machine. Jira access is on-prem Data Center, read-only client, PAT authentication. There is no MCP and there are no remote tool servers, because the tool-call loop is local and in-process.

The export boundary is enforced in code and verified by reading it. The knowledge records an engineer can export have no parameter capable of carrying a tool result, a disk serial, a hostname, or an IP. Two log files that carry customer hostnames in their binary structure are excluded by name, and redaction of known identifiers happens at query time on every search result.

Where it stands

The tool is in use with our Tier 3 group today, and the goal is the full department.

Working today: the parser, a knowledge pack holding 72,017 defects and 39,588 comments, a case report that states what it could not determine alongside what it found, search across the bundle with links from a finding to the defects it may match, export and import of knowledge records between engineers, re-parse with a diff against the previous run, and the conversation with the tool loop above. Scope is BlackPearl and Vail, with the full product line as the intended extension.

Search runs in tiers. A live tier of 153 precisely defined files is indexed as a contentless FTS5 index, built lazily in the background on first search while a live scan answers immediately. Query latency went from 58.5 seconds to roughly a tenth of a second. The archive tier of compressed rotations is reached by explicit request, or automatically when the live tier returns nothing, with the cost stated.

The consult corpus is the newest and largest source of knowledge. 1,184 threads over 25 months, parsed from the CRM consult template, so the structure is read and not guessed at. Those threads yielded 6,864 distinct log signatures, meaning normalized message shapes with the variable parts stripped out, 507 of which recur. It is worth more than it looks. Jira defects record what was wrong once someone understood it, and resolution notes record the conclusion. A consult thread captures what the symptom looked like before anyone knew what it was, what Tier 2 tried, which question cracked it, and what the false leads were. A consult only happens when Tier 2 is stuck, so the corpus is pre-filtered to hard cases.

The verification pass on that corpus is the part I would point at. A check of the first ten extracted records found six of them wrong. Both causes were systematic: normalization running a second time on already-normalized strings, which produced wrong hashes for a whole class of signature, and two cited defects that did not hold up when the actual Jira issue was opened. Both were fixed and the corpus re-derived before anything was imported. An unverified pass would have put six wrong records out of ten into the knowledge base Tier 3 is meant to trust.

What’s next

Near term is finishing the consult distillation into the pack, batch by batch, with verification between batches instead of at the end, and publishing the knowledge articles to the staging wiki space.

After that comes the curation layer, in order: corpus enrichment aimed at cases currently missed, known-issue records keyed by product and version, an error string glossary keyed on parsed exception text, and diagnostic playbooks. Playbooks have the highest ceiling and come last on purpose.

The lab server is still where the deployment goes. The design is two-tier: a larger, more capable agent hosted on a lab server, with the laptop agent linking to its knowledge base whenever it is on the corporate network and falling back to what it carries when it is not. That keeps capability high where compute allows without giving up the isolation that makes the local version worth having.

Server hardware lifts the model constraint at the same time. The isolated laptop build stays either way, because secure customer sites and travel need something that carries its own knowledge and connects to nothing. On a capable server a substantially stronger model can sit behind the same tool loop, and every part of the work that depends on model judgment would be expected to improve with it.

The method

The tool is one deliverable and the way it was built is the other.

Nothing gets claimed here without a file and line behind it, every proposal gets measured before it gets built, and negative results get written down. That last one is why four failed attempts at steering the model with text appear on this page at all, and why they turned into the most useful thing the project produced.

The pattern under every defect I found was the same: something asserted instead of checked. A field selected because its name sounded right and never compared against actual values. A search reporting no evidence from a space nobody had confirmed it covered. Each was caught by ground truth or by a later measurement, never by the system noticing on its own, which is why the guards earlier on this page are structural.