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.
Current end-to-end pipeline
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.
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.
| Column | Type | Purpose |
|---|---|---|
incident_id | String | Stable incident GUID used as the deduplication key |
incident_number | Number | Human-readable Sentinel incident number |
status | String | Currently written as completed |
processed_at | Date | UTC timestamp when completion is recorded |
discord_message_id | String | Reserved for future delivery traceability |
error | String | Reserved 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.
{{ $json.incidentId }}The workflow deliberately uses the normalised incidentId field, rather than assuming the raw Sentinel payload has the same shape at every node.
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.
{{ $('Loop Over Items').item.json.firstActivityTimeUtc }}{{ 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.
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.
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.
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 incidentThis 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.
What the manual runs demonstrated
| Test | Observation | Interpretation |
|---|---|---|
| Data Table deduplication | One previously recorded incident was excluded from a retrieved batch. | Stored incident IDs can prevent repeat processing. |
| Looping with batch size 1 | A seven-iteration test successfully retrieved the entity for each incident. | Per-incident iteration and entity retrieval worked. |
| Two-incident end-to-end run | Incidents 18821 and 18820 produced completed records. | Multiple incidents reached the end of the workflow. |
| Discord fan-out | Four completion rows appeared per incident. | Message chunks were treated as separate output items. |
| Aggregate fix | Confirmed working in the subsequent workflow. | Completion writes can be reduced to one item per incident. |
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.
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.