Back to blog
Tutorial·12 min read·2254 words

How to Build an AI Cybersecurity Threat Monitoring Agent: Complete Tutorial

A complete developer tutorial for building a real-time AI cybersecurity threat monitoring agent that investigates security events, correlates threat intelligence, assesses severity, and escalates critical incidents — with full TypeScript code.

How to Build an AI Cybersecurity Threat Monitoring Agent: Complete Tutorial — illustration

Building an AI agent that monitors cybersecurity threats in real time is one of the most practical and impressive things you can create with modern AI APIs. Instead of passively reading security alerts, your agent can autonomously investigate suspicious activity, correlate data across sources, assess severity, and draft incident response plans — all without human intervention.

This tutorial walks through building a real-time cybersecurity threat monitoring agent from scratch. We will use TypeScript and a unified AI API (we will use Qubax AI as the example, but the patterns apply to any OpenAI-compatible endpoint). By the end, you will have a production-ready agent skeleton that you can extend for your own security operations.

Prerequisites

  • Node.js 20+ and TypeScript
  • A Qubax AI API key (or any OpenAI-compatible API key)
  • Basic familiarity with TypeScript and async/await

You do not need prior cybersecurity experience. This tutorial explains the security concepts as we go.

What Our Agent Will Do

Our threat monitoring agent will:

  1. Receive security events from a webhook (SIEM alerts, log anomalies, IDS triggers)
  2. Investigate each event by correlating data from multiple sources (threat intelligence APIs, log lookups, reputation checks)
  3. Assess severity using AI reasoning based on the correlated data
  4. Generate an incident report with recommended actions
  5. Route critical threats to an on-call responder

The agent uses the reasoning loop pattern: think → act (call tools) → observe → repeat until the assessment is complete.

Step 1: Project Setup

Initialize the project and install dependencies:

bash
mkdir threat-monitor-agent && cd threat-monitor-agent
npm init -y
npm install typescript tsx @types/node --save-dev
npm install @qubax/sdk dotenv
npx tsc --init

Create a .env file:

bash
QUBAX_API_KEY=your_api_key_here
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...  # optional, for alerts

Create the project structure:

code
threat-monitor-agent/
├── src/
│   ├── index.ts        # Entry point and webhook server
│   ├── agent.ts        # Core agent loop
│   ├── tools.ts        # Tool definitions
│   └── types.ts        # TypeScript types
├── .env
└── package.json

Step 2: Define the Agent Tools

Tools are the capabilities our agent can use. For a cybersecurity agent, we need tools that let it investigate threats. Create src/tools.ts:

typescript
import { tool } from '@qubax/sdk';
import { z } from 'zod';

// Tool 1: Look up IP reputation from a threat intelligence database
export const checkIpReputation = tool({
  name: 'check_ip_reputation',
  description: 'Check the reputation score and threat history of an IP address. Use this to determine if an IP is malicious.',
  parameters: z.object({
    ip: z.string().describe('The IP address to check'),
  }),
  handler: async ({ ip }) => {
    // In production, call a real threat intel API (AbuseIPDB, VirusTotal, etc.)
    // For this tutorial, we simulate a response
    const knownBadIps = ['185.220.101.1', '194.165.16.7', '45.155.205.10'];
    const isMalicious = knownBadIps.includes(ip);

    return {
      ip,
      isMalicious,
      reputationScore: isMalicious ? 12 : 95,
      abuseReports: isMalicious ? 847 : 2,
      categories: isMalicious
        ? ['Scanning', 'Brute Force', 'Botnet C2']
        : ['Normal traffic'],
      lastSeen: new Date().toISOString(),
    };
  },
});

// Tool 2: Search historical security logs for related events
export const searchSecurityLogs = tool({
  name: 'search_security_logs',
  description: 'Search historical security logs for events related to an IP, user, or hash. Use this to find related incidents.',
  parameters: z.object({
    query: z.string().describe('Search query: an IP, username, file hash, or event type'),
    hoursBack: z.number().default(24).describe('How many hours of history to search'),
  }),
  handler: async ({ query, hoursBack }) => {
    // In production, query your SIEM (Splunk, Elastic, etc.)
    // For this tutorial, we return simulated log data
    return {
      query,
      totalEvents: Math.floor(Math.random() * 50),
      events: [
        {
          timestamp: new Date(Date.now() - 3600000).toISOString(),
          type: 'failed_login',
          source: query,
          count: Math.floor(Math.random() * 100),
        },
        {
          timestamp: new Date(Date.now() - 7200000).toISOString(),
          type: 'port_scan_detected',
          source: query,
          ports: [22, 80, 443, 3389],
        },
      ],
    };
  },
});

// Tool 3: Look up CVE details for a vulnerability identifier
export const lookupCve = tool({
  name: 'lookup_cve',
  description: 'Look up details about a CVE (Common Vulnerabilities and Exposures) identifier. Returns severity, affected systems, and known exploits.',
  parameters: z.object({
    cveId: z.string().describe('The CVE identifier, e.g. CVE-2026-1234'),
  }),
  handler: async ({ cveId }) => {
    // In production, call the NVD API or your vulnerability scanner
    return {
      cveId,
      cvssScore: 9.8,
      severity: 'CRITICAL',
      description: 'Remote code execution vulnerability in the authentication module.',
      exploitAvailable: true,
      affectedVersions: '< 2.4.1',
    };
  },
});

// Tool 4: Escalate a critical incident to the on-call responder
export const escalateIncident = tool({
  name: 'escalate_incident',
  description: 'Escalate a critical security incident to the on-call security engineer. Only use for HIGH or CRITICAL severity threats.',
  parameters: z.object({
    severity: z.enum(['HIGH', 'CRITICAL']),
    summary: z.string().describe('A concise summary of the threat'),
    recommendedActions: z.array(z.string()).describe('List of recommended response actions'),
  }),
  handler: async ({ severity, summary, recommendedActions }) => {
    // In production, send to PagerDuty, Slack, or your incident management tool
    console.log(`[ESCALATION ${severity}] ${summary}`);
    return {
      escalated: true,
      ticketId: 'INC-' + Math.floor(Math.random() * 100000),
      notifiedAt: new Date().toISOString(),
    };
  },
});

export const tools = [
  checkIpReputation,
  searchSecurityLogs,
  lookupCve,
  escalateIncident,
];

Step 3: Build the Agent Loop

The agent loop is the heart of the system. It receives a security event, lets the AI decide which tools to call, observes the results, and continues until it has a complete assessment. Create src/agent.ts:

typescript
import { QubaxClient } from '@qubax/sdk';
import { tools } from './tools.js';
import type { SecurityEvent, IncidentReport } from './types.js';

const client = new QubaxClient({ apiKey: process.env.QUBAX_API_KEY! });

const SYSTEM_PROMPT = `You are an expert cybersecurity threat analyst AI agent.

When you receive a security event, follow this process:
1. Investigate the event by calling relevant tools (IP reputation, log search, CVE lookup)
2. Correlate the findings across all sources
3. Assess the severity: LOW, MEDIUM, HIGH, or CRITICAL
4. Write a detailed incident report with recommended actions
5. If severity is HIGH or CRITICAL, call escalate_incident

Be thorough. Use multiple tools to build a complete picture before assessing.
Always explain your reasoning at each step.

Return your final assessment as a structured incident report.`;

export async function analyzeThreat(event: SecurityEvent): Promise<IncidentReport> {
  const eventDescription = formatEvent(event);

  const response = await client.agents.run({
    model: 'claude-sonnet-4-5', // or any model from https://qubax.ai/models
    system: SYSTEM_PROMPT,
    prompt: `New security event requires investigation:\n\n${eventDescription}\n\nInvestigate this event thoroughly and provide your assessment.`,
    tools,
    maxSteps: 15, // Allow up to 15 tool-calling steps
  });

  return parseIncidentReport(response.finalMessage);
}

function formatEvent(event: SecurityEvent): string {
  return `Event Type: ${event.type}
Source IP: ${event.sourceIp}
Target: ${event.target}
Timestamp: ${event.timestamp}
Details: ${JSON.stringify(event.details, null, 2)}
Raw Alert: ${event.rawAlert}`;
}

function parseIncidentReport(message: string): IncidentReport {
  // In production, use structured output or function calling
  // For this tutorial, we parse the AI's text response
  return {
    summary: message,
    assessedAt: new Date().toISOString(),
    rawResponse: message,
  };
}

Step 4: Create the Webhook Server

Now let us create a webhook server that receives security events and feeds them to the agent. Create src/index.ts:

typescript
import express from 'express';
import { analyzeThreat } from './agent.js';
import type { SecurityEvent } from './types.js';

const app = express();
app.use(express.json());

// Webhook endpoint that receives security events from your SIEM/IDS
app.post('/webhook/security-event', async (req, res) => {
  const event: SecurityEvent = req.body;

  // Acknowledge receipt immediately (the agent runs async)
  res.json({ status: 'accepted', eventId: event.id });

  console.log(`[${new Date().toISOString()}] Investigating event: ${event.type} from ${event.sourceIp}`);

  try {
    const report = await analyzeThreat(event);
    console.log(`Investigation complete:`);
    console.log(report.summary);
  } catch (error) {
    console.error('Agent error:', error);
  }
});

// Health check
app.get('/health', (req, res) => {
  res.json({ status: 'ok' });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Threat Monitor Agent listening on port ${PORT}`);
  console.log('POST security events to /webhook/security-event');
});

Step 5: Define Types

Create src/types.ts:

typescript
export interface SecurityEvent {
  id: string;
  type: 'failed_login_spike' | 'port_scan' | 'malware_detected' | 'data_exfiltration' | 'suspicious_api_calls';
  sourceIp: string;
  target: string;
  timestamp: string;
  details: Record<string, any>;
  rawAlert: string;
}

export interface IncidentReport {
  summary: string;
  assessedAt: string;
  rawResponse: string;
}

Step 6: Test the Agent

Let us simulate a security event and watch the agent investigate it. Add a test script to src/index.ts:

typescript
// Test with a simulated event
async function runTest() {
  const testEvent: SecurityEvent = {
    id: 'evt-test-001',
    type: 'failed_login_spike',
    sourceIp: '185.220.101.1',
    target: 'prod-auth-server',
    timestamp: new Date().toISOString(),
    details: {
      failedAttempts: 1247,
      targetedUsers: ['admin', 'root', 'sa', 'administrator'],
      duration: '8 minutes',
    },
    rawAlert: 'CRITICAL: 1247 failed login attempts from 185.220.101.1 in 8 minutes',
  };

  console.log('Starting threat investigation...\n');
  const report = await analyzeThreat(testEvent);
  console.log('\n=== INCIDENT REPORT ===');
  console.log(report.summary);
}

// Run test if invoked directly
if (process.env.RUN_TEST) {
  runTest();
}

Run the test:

bash
RUN_TEST=1 npx tsx src/index.ts

The agent will:

  1. Receive the brute-force event
  2. Call check_ip_reputation to look up the source IP (and discover it is a known malicious IP)
  3. Call search_security_logs to find related past events
  4. Reason about the correlation (malicious IP + brute force + targeting admin accounts)
  5. Assess severity as CRITICAL
  6. Call escalate_incident to notify the on-call engineer
  7. Generate a detailed report

Production Hardening Tips

This tutorial gives you a working skeleton. For production, consider these enhancements:

Add Rate Limiting

Security events can spike during an attack. Protect your API budget with rate limiting and queuing:

typescript
import { RateLimiter } from '@qubax/sdk';

const limiter = new RateLimiter({
  maxConcurrent: 5,     // Max 5 concurrent investigations
  maxPerMinute: 30,     // Max 30 events per minute
  queueOverflow: 'drop_oldest',
});

Implement Caching

Many events share the same source IPs or CVEs. Cache tool results to avoid redundant API calls:

typescript
const ipCache = new Map<string, { result: any; expires: number }>();

// Cache IP reputation for 1 hour
function getCachedIpRep(ip: string) {
  const cached = ipCache.get(ip);
  if (cached && cached.expires > Date.now()) return cached.result;
  return null;
}

Use Structured Output

Instead of parsing text, use structured outputs to get a guaranteed JSON schema from the agent:

typescript
const response = await client.agents.run({
  model: 'claude-sonnet-4-5',
  system: SYSTEM_PROMPT,
  prompt: eventDescription,
  tools,
  responseFormat: {
    type: 'json_schema',
    schema: {
      type: 'object',
      properties: {
        severity: { type: 'string', enum: ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'] },
        summary: { type: 'string' },
        indicators: { type: 'array', items: { type: 'string' } },
        recommendedActions: { type: 'array', items: { type: 'string' } },
      },
      required: ['severity', 'summary', 'recommendedActions'],
    },
  },
});

Model Selection for Security Agents

Different parts of your agent may benefit from different models. See the Qubax model catalog for the full list, but as a general guide:

  • Fast triage (initial event classification): use a fast, cheap model to categorize events before deep investigation
  • Deep investigation (tool calling, correlation): use a capable model with strong reasoning and tool-use
  • Report generation: a mid-tier model is usually sufficient for writing up findings

Using a unified API lets you route to the right model for each step without managing multiple SDKs. This is one of the main advantages of a platform like Qubax — see the docs for model routing configuration.

Common Pitfalls

1. Giving the Agent Too Much Autonomy

In a security context, autonomous actions can be dangerous. Always require human approval for actions that change systems (blocking IPs, disabling accounts, deploying patches). Use the agent for investigation and recommendation, not autonomous response, until you have high confidence.

2. Ignoring False Positive Costs

If your agent escalates too many LOW severity events, responders will start ignoring alerts (alert fatigue). Calibrate the severity assessment carefully and review escalation thresholds regularly.

3. Not Logging Agent Actions

For compliance and debugging, log every tool call the agent makes. If an investigation reaches the wrong conclusion, you need to understand the reasoning chain.

Next Steps

You now have a working cybersecurity threat monitoring agent. To extend it:

  • Integrate real threat intelligence APIs (VirusTotal, AbuseIPDB, MITRE ATT&CK)
  • Connect to your actual SIEM for log search
  • Add Slack or PagerDuty integration for escalations
  • Implement a feedback loop where responders rate the agent's assessments

Start building with the Qubax AI API and explore available models for your security agent today.


FAQ

What programming language is best for building AI security agents?

TypeScript/JavaScript and Python are the most popular choices, thanks to strong SDK support for AI APIs. This tutorial uses TypeScript, but the patterns translate directly to Python. Choose the language that fits your existing infrastructure.

How much does it cost to run an AI threat monitoring agent?

Cost depends on the model and how many events you process. A single investigation typically uses 5-15 tool-calling steps, costing between $0.02 and $0.15 per event with mid-tier models. Using a fast model for initial triage and a capable model for deep investigation keeps costs manageable. See Qubax pricing for details.

Can AI agents replace human security analysts?

No, but they dramatically augment them. AI agents handle the repetitive investigation work — correlating data, assessing routine events, drafting reports — freeing human analysts for complex decisions and strategic work. The human-in-the-loop pattern is still essential for high-stakes decisions.

How do I connect the agent to my existing security tools?

The agent calls tools, which are just functions. To connect to your SIEM, vulnerability scanner, or threat intel platform, implement tool handlers that call their APIs. The agent itself does not need to know the specifics — it just calls the tool and uses the results.

Is it safe to let an AI agent investigate security events?

Yes, if you design it carefully. Investigation (reading data, correlating information) is low-risk. The key safety boundary is to keep the agent in an investigation-only mode for autonomous operation and require human approval for any action that modifies systems. See the Qubax documentation for agent safety best practices.

Article tags

#AI Agents#Cybersecurity#Tutorial#TypeScript#API
Share:Post on XTelegramLinkedInYHacker NewsReddit
Qubax AI

Qubax AI

AI Models at up to 99% off · Pay with crypto

Access GPT, Claude, Gemini, GLM & 340+ models through one OpenAI-compatible API. Up to 99% off. Pay with 200+ cryptocurrencies. Get $1 free credits — no credit card needed.

Related articles