Deploy via n8n

Deploy Scanner SOC agents as n8n workflows. Import, configure credentials, activate.

n8narrow-up-right is an open-source workflow automation platform. You build workflows as a graph of nodes: triggers, actions, and AI nodes. Scanner agents ship as importable workflow.json files from the scanner-inc/agentsarrow-up-right repository.

What these agents do

Alert triage agent

A webhook-triggered agent that investigates Scanner detection alerts and posts a structured finding to Slack. When a detection fires, the agent:

  1. Reviews the alert and generates 2 to 4 hypotheses for what caused it (benign activity, misconfiguration, real attack, insider threat).

  2. Queries Scanner MCP for evidence in a 4 to 6 hour window around the event — related activity from the same user, IP, or account, and expansion indicators like privilege escalation, lateral movement, or persistence.

  3. Classifies the alert as BENIGN, SUSPICIOUS, or MALICIOUS with a confidence percentage.

  4. Runs two self-critique passes before committing to a classification.

  5. Posts a Slack finding with a TL;DR, classification, timeline, hypothesis testing, key evidence, MITRE ATT&CK tags (for MALICIOUS classifications), and recommended next questions.

Why run it. Most detection alerts in a mature SOC are false positives. Manual triage is repetitive work that analysts would rather spend on real threats. This agent does that work in seconds per alert, filters the obvious benign cases, and gives analysts a pre-populated finding for the interesting ones. Analysts skim the Slack thread, verify or override the classification, and act.

Alert triage workflow in n8n: webhook trigger, AI Agent with Anthropic, Scanner MCP, and threat-intel HTTP tools, Slack post.

See n8n/alert-triage/arrow-up-right for the workflow, the system prompt (prompts/triage-agent.md), and sample webhook payloads for local testing.

Daily posture reporting agent

A scheduled agent that posts a daily posture digest of the Scanner environment to Slack. Each run:

  1. Discovers available indices and source types via get_scanner_context.

  2. Pages through all active detection rules via the Detection Rules REST API, collecting names, severities, MITRE tags, query text, and last-fired timestamps.

  3. Queries Scanner MCP for log volume and detection alert counts over the last 24 hours.

  4. Computes coverage gaps: log sources producing volume but targeted by no rules, MITRE ATT&CK tactics (of 14) with zero covered techniques, and zombie rules that have not fired in more than 90 days.

  5. Generates recommendations grounded in canonical reference lists baked into the prompt: the full MITRE tag namespace Scanner uses (14 tactics, roughly 180 techniques), Scanner's native supported log sources, and sources bridgeable via Monad.

  6. Posts a compact Slack digest: environment totals, top log sources by volume, 24-hour alert activity, coverage gaps, and specific "expand log sources" and "expand MITRE coverage" recommendations.

Why run it. Detection coverage drifts silently. Logs get ingested that nobody writes rules for, new MITRE techniques emerge, rules go stale. A daily digest keeps detection engineering on the team's radar without anyone having to remember to check. Recommendations are specific: "write a rule for techniques.t1568.dynamic_resolution (Command and Control) using the Route 53 Resolver logs you already ingest" beats "improve coverage".

Daily posture reporting workflow in n8n: schedule trigger, AI Agent with Anthropic, Scanner MCP, and the Detection Rules API HTTP tool, Slack post.

See n8n/daily-reporting/arrow-up-right for the workflow and the system prompt.

Threat hunting agent

A scheduled agent that proactively hunts for evidence of compromise across historical Scanner logs. Runs every 6 hours by default. Each run:

  1. Discovers indices and source types via get_scanner_context.

  2. Reviews fresh CISA KEV entries (top 5 most recently added) and pulls related IOCs (IPs, domains, hashes) from three threat intel sources, exposed as HTTP Request Tool nodes rather than an MCP server: ThreatFox, AlienVault OTX, and Feodo Tracker. Filters for indicators relevant to the customer's ingested log sources.

  3. Sweeps historical Scanner logs for the IOCs using wildcard field search. Pivots to targeted behavioral queries on the matching index when hits land, to build context.

  4. Correlates across log sources, builds a timeline, maps to MITRE ATT&CK, and flags visibility gaps.

  5. Posts a single Slack findings report: hunt target, IOCs searched, results (evidence found / inconclusive / no evidence), timeline, MITRE tags, visibility gaps, and recommended next questions.

Why run it. Known-bad IOCs land in public feeds daily. A SOC without a threat hunting program typically has no systematic way to check for them across its log history. This agent runs while the team sleeps, checks every IOC in a fresh batch against Scanner's full log history, and only pages the team when a hit lands or when a clean sweep is itself notable (e.g., a high-priority CVE just dropped and the environment is verified clear).

Also available as an AWS deployment — see Deploy via AWS if you need it inside your VPC. The n8n version differs in two ways worth knowing: it posts a single findings report rather than separate "hunt starting" and "hunt complete" messages, and it wires three threat intel sources directly as HTTP Request Tools (ThreatFox, OTX, Feodo) instead of going through the dedicated mcp-threatintel-server the AWS version uses.

Threat hunting workflow in n8n: schedule trigger, CISA KEV pre-fetch, AI Agent with Anthropic, Scanner MCP, ThreatFox, OTX, and Feodo Tracker tools, Slack post.

See n8n/threat-hunting/arrow-up-right for the workflow, the system prompt, and the threat intel HTTP tool wiring.

Slack bot agent

An interactive Scanner SOC assistant you @ mention in Slack. The bot reads thread or channel context, summarizes what you asked, posts a plan, then executes the plan against Scanner MCP and posts the finding — all in the same thread.

Three chained AI Agent nodes, not one. n8n's AI Agent node is a black box: it runs its full reasoning loop internally and emits a single output, with no way to interleave Slack posts mid-execution. To show progress to the user, the workflow splits the work across three separate agents with a Slack post between each one:

  1. Summarize — one-line restatement of what the user asked, prefixed *[1/3]* 💭. No tools.

  2. Plan — a 3 to 6 bullet investigation plan, prefixed *[2/3]* 📋. Has a Scanner MCP node, but a deliberately filtered one (see below).

  3. Execute — runs the plan against Scanner MCP, produces the finding, prefixed *[3/3]* ✅. Has the unfiltered MCP client. Retry On Fail enabled here only — the user has already seen the summary and plan, so a transient overload doesn't lose context.

This split serves as a visibility checkpoint without baking approval logic into an agent loop. If Execute goes wrong, the user already sees the plan it was working from.

Schema-only MCP for the planning step. Two MCP Client Tool nodes are wired into the workflow: one filtered to get_scanner_context, get_top_columns, and get_docs, and one unfiltered. Plan gets the filtered node; Execute gets the unfiltered one. The schema tools physically return metadata, not log events, so Plan can ground its bullets in the tenant's actual indexes and fields without being able to slip into investigation. This is the pattern most worth lifting if you build your own multi-phase agent: separate "planning that grounds in schema" from "execution that touches data" by tool surface, not by prompt discipline.

Other details worth knowing. The trigger is a Slack Trigger node on app_mention events (handles URL verification and request signing automatically). A 👀 reaction is added to the mention message in parallel with the rest of the flow as immediate acknowledgment. Thread context is read via direct HTTP calls to conversations.replies because the Slack node version doesn't expose a thread-replies operation. User IDs in the context are resolved to display names via users.info so the model sees @Alice instead of <U12345>.

Slack bot workflow in n8n: Slack Trigger and context-building, then three chained AI Agents (Summarize, Plan, Execute) with intermediate Slack posts. Both Scanner MCP nodes are wired: schema-only into Plan, full client into Execute.

See n8n/slack-bot/arrow-up-right for the workflow, the three system prompts (prompts/{summarize,plan,execute}.md), the Slack app manifest requirements, and a sample app_mention payload.

Prerequisites

  • An n8n instance. Options:

    • n8n Cloud (n8n.io/cloudarrow-up-right): fastest to start. 14-day trial. Pro plan required for team workspaces and variables.

    • Self-hosted Docker:

      The --tunnel flag gives you a public URL so Scanner can POST webhooks to your laptop during development. For production, host n8n somewhere with a stable public URL (Railway, Fly.io, Render, or your own VPC).

  • An Anthropic API key.

  • A Scanner API key with read access to your tenant's MCP and Detection Rules API.

  • A Slack workspace and a channel where agent findings will be posted.

Import a workflow

Pick an agent from scanner-inc/agents/n8narrow-up-right and download its workflow.json. In n8n: WorkflowsImport from File → select the workflow.json.

Create credentials

The imported workflow references credentials by name. Create each one in Credentials before activating the workflow. Names must match exactly.

  • Anthropic account (type: Anthropic API) — your Anthropic API key.

  • Bearer Auth account (type: HTTP Bearer Auth) — your Scanner API key. n8n adds the Bearer prefix automatically. The same credential is used for the Scanner MCP and the Detection Rules REST API.

  • Slack account (type: Slack OAuth2 or Slack API) — follow n8n's prompts to connect your workspace.

  • Header Auth account (type: HTTP Header Auth) — only needed by alert-triage/. Name the header x-scanner-to-n8n-webhook-key and set the value to a random secret you generate. Scanner will include this header on every webhook POST.

  • OTX API account and abuse.ch API account — only needed by threat-hunting/. Free keys from otx.alienvault.comarrow-up-right and abuse.charrow-up-right (the abuse.ch key authenticates both ThreatFox and Feodo Tracker). Wire them as Header Auth credentials on the corresponding HTTP Request Tool nodes.

Configure environment-specific values

Open each node in the imported workflow and replace placeholders:

  • Scanner MCP node (URL field): replace mcp.your-env.scanner.dev with your tenant's MCP hostname.

  • Detection Rules API node (URL field, daily-reporting only): replace api.your-env.scanner.dev with your tenant's REST API hostname. Also set the tenant_id query parameter's value to your actual tenant UUID (find it in Scanner under Settings).

  • Send a message (Slack) node: replace the placeholder channel ID with your reporting channel.

Wire up the trigger

For alert-triage/ (webhook)

  1. In Scanner, go to SettingsEvent SinksCreate New SinkWebhook.

  2. URL: the Production URL from the Webhook node in n8n (or the tunnel URL during local development). The path is /webhook/scanner-alert.

  3. Headers: add a custom header matching your n8n Header Auth credential:

    • Name: x-scanner-to-n8n-webhook-key

    • Value: the same secret you stored in n8n

  4. Save the event sink. Click Send Test Event to verify the round trip.

  5. Attach the event sink to the detection rules you want triaged.

For daily-reporting/ (schedule)

The imported workflow has a Schedule Trigger set to 0 8 * * * (08:00 UTC daily). Edit to suit your team's timezone. Then activate the workflow.

For threat-hunting/ (schedule)

The imported workflow has a Schedule Trigger set to 0 */6 * * * (every 6 hours). Adjust to suit your team. Then activate the workflow.

For slack-bot/ (Slack app_mention event)

The imported workflow uses a Slack Trigger node, not a generic Webhook. You wire the Slack app's Events API to it:

  1. Activate the workflow and copy the Production URL from the Slack Trigger node.

  2. In your Slack app's API configarrow-up-right, under Event Subscriptions, paste the URL into Request URL (Slack will verify it automatically), then subscribe to the app_mention bot event.

  3. Under OAuth & Permissions, the bot needs at minimum: app_mentions:read, channels:history, groups:history, chat:write, reactions:write, and users:read (for resolving Slack user IDs to display names).

  4. Reinstall the app to your workspace so the new scopes take effect.

The repo's slack-bot/setup.mdarrow-up-right ships a ready-to-paste Slack app manifest if you'd rather not configure scopes by hand.

Verify

  1. Activate the workflow.

  2. For alert-triage/: run curl against the webhook URL with a sample payload (one is included in the repo's sample-payloads/ directory). The execution appears in n8n; the Slack node posts the finding.

  3. For daily-reporting/ and threat-hunting/: click Execute workflow in the n8n UI to run it once manually without waiting for the cron.

  4. For slack-bot/: @ mention the bot in any channel it's been invited to. You should see the 👀 reaction immediately, then three threaded posts (*[1/3]* summary, *[2/3]* plan, *[3/3]* finding). The Slack Trigger node also has a sample app_mention payload pinned, so you can execute the workflow from the canvas without sending a real Slack event.

Troubleshooting

My imported workflow.json misbehaves (often after AI generation)

This is the single most common cause of weird n8n issues with these agents. AI assistants like Claude Code don't reliably know the current typeVersion of n8n nodes — they tend to write deprecated values into generated workflow.json files. After import, those nodes silently use old behavior:

  • MCP Client Tool < 1.2 falls back to SSE transport. Scanner MCP requires Streamable HTTP and rejects with 401 "Non-200 status code".

  • Anthropic Chat Model < 1.3 doesn't list Claude 4.x in the model dropdown, so the workflow points at a Claude 3.x model that may not behave as expected.

  • A workflow that worked before an n8n upgrade can break afterwards because typeVersion is sticky on existing nodes — docker pull n8nio/n8n updates the image but doesn't update existing nodes already on the canvas.

The reliable workaround. Don't hand-edit typeVersions and don't trust the AI's guess:

  1. In n8n, drag the node fresh from the palette (e.g., add a new MCP Client Tool node, then delete the broken one and reconnect the wires).

  2. Save and export the workflow.

  3. Open the exported workflow.json and copy the actual typeVersion value the n8n UI just produced.

  4. Tell Claude Code (or whichever AI you're using) the correct typeVersion for that node going forward.

This is a one-time cost per node type in your environment.

Other common errors

  • Webhook 401 (alert-triage): the x-scanner-to-n8n-webhook-key header is missing or does not match your credential value. Check the Scanner event sink header config.

  • Slack Trigger fails URL verification (slack-bot): the Slack Trigger node has to be saved and the workflow activated before Slack will accept the Request URL. If you re-create the trigger node, the URL changes and Slack needs to re-verify.

  • Anthropic "Overloaded" errors: enable Retry On Fail on the AI Agent node (3 tries, 5 to 10 second wait). If overloads persist, switch to a less-loaded model.

  • Agent leaks preamble into Slack output ("I have enough data..." before the formatted finding): the workflows ship with a defensive expression on the Slack node's text field that slices from the expected emoji character. If you rebuild the Slack node, apply the same pattern.

See each workflow's own README in the repository for workflow-specific details and the canonical list of known issues.

Last updated

Was this helpful?