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:
- Receive security events from a webhook (SIEM alerts, log anomalies, IDS triggers)
- Investigate each event by correlating data from multiple sources (threat intelligence APIs, log lookups, reputation checks)
- Assess severity using AI reasoning based on the correlated data
- Generate an incident report with recommended actions
- 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:
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 --initCreate a .env file:
QUBAX_API_KEY=your_api_key_here
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/... # optional, for alertsCreate the project structure:
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.jsonStep 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:
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:
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:
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:
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:
// 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:
RUN_TEST=1 npx tsx src/index.tsThe agent will:
- Receive the brute-force event
- Call
check_ip_reputationto look up the source IP (and discover it is a known malicious IP) - Call
search_security_logsto find related past events - Reason about the correlation (malicious IP + brute force + targeting admin accounts)
- Assess severity as CRITICAL
- Call
escalate_incidentto notify the on-call engineer - 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:
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:
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:
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.