Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: "ConnectWise Automate Alerts" description: > Use this skill when working with ConnectWise Automate alerts - listing active alerts, acknowledging alerts, viewing alert history, and creating tickets from alerts. Covers alert sources (monitors, scripts, events), alert severity levels, alert lifecycle management, and ticket integration. when_to_use: "When listing active alerts, acknowledging alerts, viewing alert history, and creating tickets from alerts" triggers:
- automate alert
- automate notification
- alert acknowledgment
- alert history
- alert ticket
- monitor alert
- labtech alert
- automate incident
ConnectWise Automate Alert Management
Overview
Alerts in ConnectWise Automate are notifications generated by monitors, scripts, or system events that require attention. This skill covers alert listing, acknowledgment, history tracking, and ticket creation workflows.
Key Concepts
Alert Sources
| Source | Description | Example | |
|---|---|---|---|
| Monitor | Generated by monitor threshold | CPU > 90% | |
| Script | Generated by script execution | Backup failed | |
| Event Log | Windows Event Log trigger | Security event | |
| System | Automate system events | Agent offline | |
| Manual | User-created alerts | Maintenance note |
Alert Severity Levels
| Level | Value | Description | Response Time | |
|---|---|---|---|---|
Information | 1 | Informational only | Review at convenience | |
Warning | 2 | Potential issue | Investigate within hours | |
Error | 3 | Failure detected | Respond within SLA | |
Critical | 4 | Severe/emergency | Immediate response |
Alert Lifecycle
Generated → Active → Acknowledged → Resolved│ ││ └── Ticket Created│└── Auto-Cleared (if condition clears)
Alert Status
| Status | Description | |
|---|---|---|
New | Just generated, unread | |
Active | Open, unacknowledged | |
Acknowledged | Someone is working on it | |
Resolved | Issue fixed, alert closed | |
Cleared | Condition auto-cleared | |
Suppressed | Temporarily hidden |
Field Reference
Alert Fields
interface Alert {// IdentifiersAlertID: number; // Primary keyAlertGUID: string; // Global unique ID// SourceSource: AlertSource; // Monitor, Script, EventLog, SystemSourceID: number; // ID of source (MonitorID, ScriptID, etc.)SourceName: string; // Name of source// TargetComputerID: number; // Affected computerComputerName: string; // Computer hostnameClientID: number; // Parent clientClientName: string; // Client nameLocationID: number; // Location ID// Alert DetailsSubject: string; // Alert titleMessage: string; // Detailed messageSeverity: AlertSeverity; // 1-4 severity levelStatus: AlertStatus; // Current status// TimestampsTimeGenerated: string; // When createdTimeAcknowledged: string; // When acknowledgedTimeResolved: string; // When resolvedLastUpdate: string; // Last status change// AcknowledgmentAcknowledgedBy: string; // User who acknowledgedNotes: string; // Acknowledgment notes// Ticket IntegrationTicketID: number; // Linked ticket IDTicketStatus: string; // Ticket status// ContextCategory: string; // Alert categoryAdditionalData: object; // Extra context data}type AlertSource = 'Monitor' | 'Script' | 'EventLog' | 'System' | 'Manual';type AlertSeverity = 1 | 2 | 3 | 4;type AlertStatus = 'New' | 'Active' | 'Acknowledged' | 'Resolved' | 'Cleared' | 'Suppressed';
Alert History Fields
interface AlertHistory {HistoryID: number;AlertID: number;Action: string; // Status change, note added, etc.ActionBy: string; // User who made changeActionTime: string; // When action occurredPreviousStatus: string;NewStatus: string;Notes: string;}
API Patterns
List Active Alerts
GET /cwa/api/v1/Alerts?condition=Status in ('New','Active')&pageSize=100Authorization: Bearer {token}
Response:
[{"AlertID": 54321,"Subject": "Disk C: Low Space","Message": "Disk C: is 8% free on ACME-DC01","Severity": 2,"Status": "Active","ComputerID": 12345,"ComputerName": "ACME-DC01","ClientName": "Acme Corporation","Source": "Monitor","SourceName": "Disk Space Monitor","TimeGenerated": "2024-02-15T08:30:00Z","Category": "Performance"}]
Get Alert Details
GET /cwa/api/v1/Alerts/{alertID}Authorization: Bearer {token}
Response:
{"AlertID": 54321,"AlertGUID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890","Subject": "Disk C: Low Space","Message": "Disk C: is 8% free on ACME-DC01\n\nTotal: 500 GB\nFree: 40 GB\nThreshold: 10%","Severity": 2,"Status": "Active","ComputerID": 12345,"ComputerName": "ACME-DC01","ClientID": 100,"ClientName": "Acme Corporation","LocationID": 1,"Source": "Monitor","SourceID": 5001,"SourceName": "Disk Space Monitor","TimeGenerated": "2024-02-15T08:30:00Z","Category": "Performance","AdditionalData": {"DriveLetter": "C:","FreeSpaceGB": 40,"TotalSpaceGB": 500,"FreePercent": 8}}
Filter Alerts by Client
GET /cwa/api/v1/Alerts?condition=ClientID = 100 and Status = 'Active'&pageSize=100Authorization: Bearer {token}
Filter Alerts by Severity
GET /cwa/api/v1/Alerts?condition=Severity >= 3 and Status = 'Active'&pageSize=100Authorization: Bearer {token}
Acknowledge Alert
POST /cwa/api/v1/Alerts/{alertID}/AcknowledgeAuthorization: Bearer {token}Content-Type: application/json{"Notes": "Investigating disk space issue"}
Response:
{"AlertID": 54321,"Status": "Acknowledged","AcknowledgedBy": "admin@example.com","TimeAcknowledged": "2024-02-15T10:45:00Z"}
Resolve Alert
POST /cwa/api/v1/Alerts/{alertID}/ResolveAuthorization: Bearer {token}Content-Type: application/json{"Notes": "Cleared 50GB of temp files. Disk now at 18% free."}
Add Note to Alert
POST /cwa/api/v1/Alerts/{alertID}/NotesAuthorization: Bearer {token}Content-Type: application/json{"Note": "Contacted user about large files in Downloads folder"}
Create Ticket from Alert
POST /cwa/api/v1/Alerts/{alertID}/CreateTicketAuthorization: Bearer {token}Content-Type: application/json{"TicketSubject": "Disk Space Critical on ACME-DC01","Priority": 2,"BoardID": 1,"Notes": "Auto-created from Automate alert"}
Response:
{"AlertID": 54321,"TicketID": 98765,"TicketNumber": "TKT-2024-00123","TicketStatus": "New"}
Get Alert History
GET /cwa/api/v1/Alerts/{alertID}/HistoryAuthorization: Bearer {token}
Response:
[{"HistoryID": 1,"Action": "Created","ActionTime": "2024-02-15T08:30:00Z","NewStatus": "New"},{"HistoryID": 2,"Action": "Acknowledged","ActionBy": "admin@example.com","ActionTime": "2024-02-15T10:45:00Z","PreviousStatus": "Active","NewStatus": "Acknowledged","Notes": "Investigating disk space issue"}]
Suppress Alert
POST /cwa/api/v1/Alerts/{alertID}/SuppressAuthorization: Bearer {token}Content-Type: application/json{"Duration": 3600,"Reason": "Scheduled maintenance window"}
Bulk Acknowledge Alerts
POST /cwa/api/v1/Alerts/BulkAcknowledgeAuthorization: Bearer {token}Content-Type: application/json{"AlertIDs": [54321, 54322, 54323],"Notes": "Bulk acknowledgment for server maintenance"}
Workflows
Get Critical Alerts Dashboard
async function getCriticalAlertsDashboard(client) {const criticalAlerts = await client.request(`/Alerts?condition=Severity >= 3 and Status in ('New','Active')&pageSize=100`);const dashboard = {totalCritical: criticalAlerts.length,byClient: {},byCategory: {},oldest: null};for (const alert of criticalAlerts) {// Group by clientconst clientName = alert.ClientName || 'Unknown';if (!dashboard.byClient[clientName]) {dashboard.byClient[clientName] = [];}dashboard.byClient[clientName].push({id: alert.AlertID,subject: alert.Subject,computer: alert.ComputerName,severity: alert.Severity,age: getAlertAge(alert.TimeGenerated)});// Group by categoryconst category = alert.Category || 'Uncategorized';dashboard.byCategory[category] = (dashboard.byCategory[category] || 0) + 1;// Track oldestif (!dashboard.oldest || new Date(alert.TimeGenerated) < new Date(dashboard.oldest.TimeGenerated)) {dashboard.oldest = alert;}}return dashboard;}function getAlertAge(timeGenerated) {const now = new Date();const generated = new Date(timeGenerated);const diffMs = now - generated;const diffMins = Math.floor(diffMs / 60000);if (diffMins < 60) return `${diffMins} minutes`;if (diffMins < 1440) return `${Math.floor(diffMins / 60)} hours`;return `${Math.floor(diffMins / 1440)} days`;}
Acknowledge and Create Ticket Workflow
async function acknowledgeAndCreateTicket(client, alertId, options = {}) {const {notes = 'Acknowledged and ticket created',priority = 2,boardId = 1} = options;// Get alert detailsconst alert = await client.request(`/Alerts/${alertId}`);// Acknowledge the alertawait client.request(`/Alerts/${alertId}/Acknowledge`, {method: 'POST',body: JSON.stringify({ Notes: notes })});// Create ticketconst ticketResponse = await client.request(`/Alerts/${alertId}/CreateTicket`, {method: 'POST',body: JSON.stringify({TicketSubject: alert.Subject,Priority: alert.Severity >= 3 ? 1 : priority,BoardID: boardId,Notes: `Auto-created from Automate alert\n\n${alert.Message}`})});return {alert: {id: alertId,subject: alert.Subject,status: 'Acknowledged'},ticket: {id: ticketResponse.TicketID,number: ticketResponse.TicketNumber}};}
Alert Triage by Client
async function triageAlertsByClient(client, clientId) {const alerts = await client.request(`/Alerts?condition=ClientID = ${clientId} and Status in ('New','Active')&pageSize=200`);const triage = {client: clientId,total: alerts.length,critical: [],error: [],warning: [],info: []};for (const alert of alerts) {const summary = {id: alert.AlertID,subject: alert.Subject,computer: alert.ComputerName,source: alert.SourceName,age: getAlertAge(alert.TimeGenerated)};switch (alert.Severity) {case 4: triage.critical.push(summary); break;case 3: triage.error.push(summary); break;case 2: triage.warning.push(summary); break;default: triage.info.push(summary);}}return triage;}
Bulk Alert Resolution
async function bulkResolveAlerts(client, alertIds, notes) {const results = [];for (const alertId of alertIds) {try {await client.request(`/Alerts/${alertId}/Resolve`, {method: 'POST',body: JSON.stringify({ Notes: notes })});results.push({ alertId, status: 'resolved' });} catch (error) {results.push({ alertId, status: 'failed', error: error.message });}// Respect rate limitsawait sleep(100);}return {resolved: results.filter(r => r.status === 'resolved').length,failed: results.filter(r => r.status === 'failed').length,details: results};}
Alert Escalation Check
async function checkAlertEscalation(client) {const alerts = await client.request(`/Alerts?condition=Status = 'Active' and Severity >= 2&pageSize=500`);const escalations = [];const now = new Date();for (const alert of alerts) {const generated = new Date(alert.TimeGenerated);const ageMinutes = (now - generated) / 60000;// Escalation rules based on severity and agelet shouldEscalate = false;let reason = '';switch (alert.Severity) {case 4: // Criticalif (ageMinutes > 15) {shouldEscalate = true;reason = 'Critical alert unacknowledged for 15+ minutes';}break;case 3: // Errorif (ageMinutes > 60) {shouldEscalate = true;reason = 'Error alert unacknowledged for 1+ hour';}break;case 2: // Warningif (ageMinutes > 240) {shouldEscalate = true;reason = 'Warning alert unacknowledged for 4+ hours';}break;}if (shouldEscalate) {escalations.push({alertId: alert.AlertID,subject: alert.Subject,client: alert.ClientName,computer: alert.ComputerName,severity: alert.Severity,ageMinutes: Math.round(ageMinutes),reason});}}return escalations;}
Error Handling
Common Alert API Errors
| Error | Status | Cause | Resolution | |
|---|---|---|---|---|
| Alert not found | 404 | Invalid AlertID | Verify alert exists | |
| Already resolved | 400 | Alert already closed | Check current status | |
| Permission denied | 403 | No access to alert | Check user permissions | |
| Invalid status | 400 | Invalid status transition | Follow lifecycle rules | |
| Ticket creation failed | 400 | PSA integration error | Check ticket board config |
Error Response Example
{"error": {"code": "BadRequest","message": "Cannot acknowledge already resolved alert"}}
Safe Alert Resolution
async function safeResolveAlert(client, alertId, notes) {// Get current alert statusconst alert = await client.request(`/Alerts/${alertId}`);if (alert.Status === 'Resolved' || alert.Status === 'Cleared') {return {success: false,error: `Alert already ${alert.Status.toLowerCase()}`};}try {await client.request(`/Alerts/${alertId}/Resolve`, {method: 'POST',body: JSON.stringify({ Notes: notes })});return {success: true,alertId,previousStatus: alert.Status,newStatus: 'Resolved'};} catch (error) {return {success: false,error: error.message};}}
Best Practices
- Acknowledge promptly - Shows someone is working on it
- Add meaningful notes - Document investigation steps
- Create tickets for tracking - Long-running issues need tickets
- Use bulk operations - Handle related alerts together
- Set up escalation rules - Don't let alerts age
- Filter by severity - Focus on critical first
- Review alert history - Understand recurring patterns
- Suppress during maintenance - Avoid alert fatigue
- Link to documentation - Reference runbooks in notes
- Regular alert review - Audit old/stale alerts
Alert Response Workflow Template
async function standardAlertResponse(client, alertId) {const workflow = {steps: [],success: true};try {// Step 1: Get alert detailsconst alert = await client.request(`/Alerts/${alertId}`);workflow.steps.push({step: 'Get Alert',status: 'success',data: {subject: alert.Subject,severity: alert.Severity,computer: alert.ComputerName}});// Step 2: Acknowledge if not alreadyif (alert.Status === 'New' || alert.Status === 'Active') {await client.request(`/Alerts/${alertId}/Acknowledge`, {method: 'POST',body: JSON.stringify({ Notes: 'Investigating alert' })});workflow.steps.push({ step: 'Acknowledge', status: 'success' });}// Step 3: Create ticket if critical/errorif (alert.Severity >= 3) {const ticket = await client.request(`/Alerts/${alertId}/CreateTicket`, {method: 'POST',body: JSON.stringify({TicketSubject: alert.Subject,Priority: alert.Severity === 4 ? 1 : 2,BoardID: 1})});workflow.steps.push({step: 'Create Ticket',status: 'success',ticketId: ticket.TicketID});}// Step 4: Check computer statusconst computer = await client.request(`/Computers/${alert.ComputerID}`);workflow.steps.push({step: 'Check Computer',status: 'success',computerStatus: computer.Status});} catch (error) {workflow.success = false;workflow.steps.push({step: 'Error',status: 'failed',error: error.message});}return workflow;}
Related Skills
- ConnectWise Automate Monitors - Alert sources
- ConnectWise Automate Computers - Alert targets
- ConnectWise Automate Scripts - Remediation scripts
- ConnectWise Automate API Patterns - Authentication and pagination