SOC Engineering / Agentic Automation / Stage 04 / October 2026

From a single investigation to stateful incident processing

Extending a local AI SOC proof of concept to process multiple Microsoft Sentinel incidents sequentially, skip incidents already investigated, and record completion only after Discord delivery.

n8n 2.43.4Microsoft SentinelData TablesLoop Over ItemsQwen3:14bAzure MCPDiscord
Batch size 1Sequential investigations
1 row / incidentCompletion record after aggregation
On demandCurrent execution mode; scheduling deferred
01 / Why this iteration mattered

Turning a working demonstration into a repeatable workflow

The previous stage demonstrated that an n8n AI Agent could retrieve Sentinel incident context, ask a locally hosted Qwen model to investigate Cowrie SSH honeypot telemetry through Azure MCP, and send a SOC-style report to Discord. That proved tool use and reporting, but it was still essentially a one-incident experiment.

This stage tackled a different engineering problem: what happens when several incidents are available, and the workflow is run again later? Without state, the agent would repeatedly investigate the same incidents. Without controlled iteration, incident metadata could become mixed between reports. Without aggregation, a multi-message Discord report could create several processing-history records.

Outcome: Manual tests demonstrated sequential multi-incident execution and persistent tracking. The Discord aggregation fix was subsequently confirmed working. Automatic scheduling has deliberately not been enabled.
02 / Architecture

Current end-to-end pipeline

01 / Manual triggerRun on demand
02 / Get incidentsMicrosoft Sentinel
03 / Edit FieldsNormalise incident metadata
04 / IF filterExisting conditional gate
05 / Data Table checkPass only unseen incident IDs
06 / Loop Over ItemsOne incident per iteration
07 / Get entitiesResolve source IP
08 / AI AgentQwen + Azure MCP KQL
09 / JavaScriptSplit long reports into chunks
10 / DiscordSend each report chunk
11 / AggregateCollapse message responses
12 / Insert rowRecord completed incident; return to loop

The loop output follows the investigation path; the completion branch returns to the Loop Over Items input. The loop's “done” output marks the end of the batch.

The investigation engine remains unchanged: Ollama → Qwen3:14b → n8n MCP Client → Azure MCP Server → Sentinel Log Analytics. This stage adds orchestration and persistence around that existing capability.

03 / Persistent processing history

Remember which incidents have already been handled

An n8n Data Table named sentinel_processed_incidents provides a lightweight persistent ledger. Before the agent runs, If Row Does Not Exist checks whether the normalised incident GUID is already present. Existing records are excluded from the investigation loop.

ColumnTypePurpose
incident_idStringStable incident GUID used as the deduplication key
incident_numberNumberHuman-readable Sentinel incident number
statusStringCurrently written as completed
processed_atDateUTC timestamp when completion is recorded
discord_message_idStringReserved for future delivery traceability
errorStringReserved for future failure details

For example, the manually seeded incident 18812 was filtered out during testing. The subsequent multi-incident test processed previously unseen incidents 18821 and 18820. The table persists across workflow runs, unlike temporary n8n execution data.

Illustrative n8n expression — incident identity
{{ $json.incidentId }}

The workflow deliberately uses the normalised incidentId field, rather than assuming the raw Sentinel payload has the same shape at every node.

04 / Controlled iteration

One incident, one investigation context

The Loop Over Items node is configured with a batch size of 1. Each iteration retrieves the entities for its incident and supplies the source IP and incident activity times to the AI Agent. This prevents an entire incident batch from being handed to the agent as one undifferentiated input.

Incident-specific context

The agent receives the source IP from the current entity and first/last activity timestamps from the current loop item. Its query window extends one hour before the first activity and one hour after the last.

Sequential execution

Only after the investigation, Discord delivery and completion record does the flow return to the loop to advance to the next incident.

Example n8n expression — incident timestamp
{{ $('Loop Over Items').item.json.firstActivityTimeUtc }}
Example n8n expression — investigation start
{{ DateTime.fromISO($('Loop Over Items').item.json.firstActivityTimeUtc, { zone: 'utc' }).minus({ hours: 1 }).toISO() }}

These are configuration examples, not a standalone JavaScript program. n8n item linking must be preserved across downstream nodes.

05 / Debugging a subtle fan-out

Four Discord messages should not mean four completed incidents

The JavaScript formatting node splits a long AI-generated report into smaller messages to accommodate Discord's message-size limits. During the first multi-incident test, each investigation generated four Discord message items. Because the Data Table Insert node was connected directly after Discord, it inserted four rows for the same incident.

Before

Duplicate history entries

Incident 18821 appeared four times; incident 18820 also appeared four times. The timestamps differed by milliseconds. This was not evidence of four separate AI investigations per incident.

After

Aggregate before writing state

An Aggregate node was inserted between Discord and Data Table Insert, collecting the message responses into a single output item. The user confirmed that the aggregation is working.

AI Agent
   |
   v
JavaScript: split report into message chunks
   |
   v
Discord: send each chunk  (multiple items)
   |
   v
Aggregate: All Item Data  (one item)
   |
   v
Data Table: Insert completed  (one row)
   |
   +----> Loop Over Items: next incident

This was a useful lesson in n8n's item-based execution model: downstream nodes run against the items they receive. A node that fans out a report must be reconciled before a one-per-incident side effect.

06 / Test evidence

What the manual runs demonstrated

TestObservationInterpretation
Data Table deduplicationOne previously recorded incident was excluded from a retrieved batch.Stored incident IDs can prevent repeat processing.
Looping with batch size 1A seven-iteration test successfully retrieved the entity for each incident.Per-incident iteration and entity retrieval worked.
Two-incident end-to-end runIncidents 18821 and 18820 produced completed records.Multiple incidents reached the end of the workflow.
Discord fan-outFour completion rows appeared per incident.Message chunks were treated as separate output items.
Aggregate fixConfirmed working in the subsequent workflow.Completion writes can be reduced to one item per incident.
Evidence standard: These results demonstrate functional orchestration in a controlled homelab. They do not establish production reliability, comprehensive detection coverage or that every AI-generated statement is independently verified.
07 / Scope and safeguards

What this version does—and does not—guarantee

Current scope

The workflow is executed manually; the observed Cowrie incidents expose one source-IP entity per incident; the AI Agent queries telemetry via MCP; and the completion ledger is written after the Discord path.

Not yet production hardened

The deduplication check matches an existing incident ID regardless of status. There is no robust in_progress lease, retry queue, unique database constraint, or overlapping-execution protection.

Incident coverage

Testing used small retrieval limits, including two incidents for the end-to-end run. A future scheduled workflow needs a safe backlog strategy so older unprocessed incidents cannot fall outside the retrieval window.

Analyst validation

Successful honeypot logins are not evidence of a real host compromise. Model-written findings still require comparison with source events, especially when interpreting commands or recommending response actions.

Intentional stopping point: Scheduled execution remains disabled. On-demand runs are sufficient for the current learning and portfolio objective. A recurring trigger without concurrency controls could duplicate investigations while a prior batch is still running.
08 / Outcome and future work

A repeatable, state-aware agentic SOC proof of concept

This fourth stage adds something more valuable than another prompt or query: operational state. The system can select unprocessed incidents, investigate them individually, deliver multi-part reports, and maintain a record of what it has already handled. The AI reasoning component remains local, while Azure MCP supplies access to real Sentinel telemetry.

If the project is extended later, the next engineering work would be a scheduled trigger with bounded concurrency, a reliable incident backlog and retry strategy, status-aware state transitions, message-ID tracking, and broader entity handling. A later Sentinel transition into the Defender portal may also offer an opportunity to evaluate Microsoft's hosted Sentinel MCP tools without rebuilding the orchestration stack.

Current status: On-demand multi-incident processing completed; Aggregate fix confirmed; unattended execution intentionally deferred.

Stage 01 / Local AI briefingStage 02 / Azure MCP integrationStage 03 / Single-incident investigationStage 04 / Looping + history