Back to all posts
AI & ML

Building an AI SOC Analyst Agent Without Frameworks

Part 5: Bulletproofing the Infrastructure (Config & Logging)

View Code on GitHub

Series: Building an AI SOC Analyst Agent Without Frameworks · Part 5 of 6

  1. 1. Part 1: What AI Agents Actually Are
  2. 2. Part 2: Tool Registries and the Dispatch Pattern
  3. 3. Part 3: The Tools: Giving the Agent Eyes and Memory
  4. 4. Part 4: Prompt Engineering for AI Agents Is Different
  5. 5. Part 5: Bulletproofing the Infrastructure (Config & Logging)
  6. 6. Part 6: Testing AI Agents Without Hitting APIs

Logging Matters More Than Intelligence

Security tools cannot afford to fail silently or leak data.

The core insight is using separate console and file handlers to control data exposure based on environment visibility.

By utilizing a rotating file handler restricted to the DEBUG level and a separate console handler for higher levels, you ensure that sensitive, verbose data (such as the final investigation report) is safely isolated within secure log files. Meanwhile, standard operational events (INFO for tool calls) and system boundaries (WARNING for reaching max iterations) can be safely output to the standard console without accidentally leaking data to terminal viewers.

Configuration Management (config.py)

Hardcoded values quickly became a problem. The specific pain was tight coupling and manual source code manipulation when moving between environments.

Before moving to environment variables, parameters were hardcoded as constants. Because a SOC agent behaves completely differently in Production (e.g., smaller max_iterations value, production models like gpt-4o, and system log paths like /var/log/soc/agent.log) versus Development (testing headroom with larger max_iterations value, local log paths, and cheaper models), switching contexts required manually rewriting code. This created massive friction, broke deployment automation, and risked accidentally pushing local testing configurations live. Following the cloud-native approach, I moved configuration into environment variables:

Following 12-Factor App principles made the project cleaner and easier to deploy.

Data Integrity & Context Enrichment with Pydantic

Passing raw, unvalidated dictionaries through an automated security operations center (SOC) agent is highly risky. In production, if a third-party SIEM log format changes slightly, an unvalidated system risks throwing a KeyError that crashes the execution mid-loop, or silently falling back to None via defensive .get() calls. This can cause the LLM to misinterpret critical telemetry, potentially classifying a malicious event as benign simply due to missing evidence.

To bridge the gap between volatile log inputs and a production-grade security tool, the ingestion architecture was re-engineered around Pydantic v2. This shifted the project from a loose prototype to a deterministic, type-safe data pipeline.

The Guarded Pipeline Architecture

Instead of letting the agent ingest raw JSON directly, data passes through a multi-stage functional parsing and preprocessing pipeline before the LLM ever enters the loop:

Raw JSON → SocAlertSchema → Static Enrichment → EnrichedAlertSchema

By mapping incoming telemetry to strongly typed Pydantic sub-models (encompassing core Alerts, Entities, Event Data, and strictly bounded Severity Levels), the gateway automatically enforces:

Structural Inheritance vs. Inline Mutation

A key architectural choice in this pipeline is leveraging explicit model inheritance—building EnrichedAlertSchema as an extension of SocAlertSchema—rather than mutating the baseline schema on the fly (enrichment.py).

class EnrichedAlertSchema(SocAlertSchema):
    is_after_hours: bool
    ip_is_private: bool
    severity_score: int

def run_soc_agent(alert_data: dict):
    alert = SocAlertSchema(**alert_data)
    enriched = enrich_alert(alert) 

The State Contract Philosophy: If you mutate data inline, all enrichment fields must be declared as Optional[Any] = None. If an external threat intelligence API times out or a script fails silently, the agent loop still boots up, but with empty fields the agent can’t reason over.

By utilizing inheritance and making fields strictly required on the EnrichedAlertSchema, Pydantic guarantees an ironclad state contract. If the enrichment phase misses a dependency, the system raises a loud, catchable ValidationError at the application boundary before wasting downstream API tokens.

During this functional pre-computation phase, three foundational contexts are safely locked in:

Operational Impact on the Agent Loop

Moving validation and enrichment to the structural entry point fundamentally changes how the AI agent operates.

1. A Deterministic Data Contract

Downstream tools and functions no longer need to be cluttered with defensive parsing boilerplate or nested safety checks. It completely eliminates silent data degradation, ensuring that the text formatted into system prompts is correct and complete.

2. Shifting Mindsets: Strategic Execution Over Exploration

Rather than receiving a raw signal and wasting processing cycles performing basic environmental discovery, the agent starts with the high-value answers a Tier 1 analyst would gather in the first 30 seconds of an investigation. The LLM’s role shifts from exploratory data gathering to high-level strategic reasoning and playbook execution.