Turn a machine condition into a ServiceNow incident, with the machine ID, the reading, the recommended action, and an urgency derived from how much time is left.
Forge can act on what a machine is doing now, or on what it is forecast to do. The two paths deliver differently, so choose deliberately.
| Path | Condition type | Delivery | Status |
|---|---|---|---|
| Threshold breached the reading crossed the line |
simple / compound |
actions[] → your registered tool, exact body, tool auth applied |
Works today, documented below |
| Breach forecast it will cross the line in N hours |
predicted_breach |
Fixed-shape POST to a plain webhook_url, no templating, no tool auth |
Needs a shim, see the last section |
What Forge knows, and where it lands in a ServiceNow incident record.
| ServiceNow field | Source | Example |
|---|---|---|
short_description | trigger name + machine + field | Spindle load breach on mint_7f3a91c4 |
description | field, actual value, threshold, timestamp, recommended action | multi-line, see payload below |
urgency | fixed per trigger (1 high, 2 medium, 3 low) | "2" |
impact | fixed per trigger, usually by machine criticality | "2" |
category | fixed | "Hardware" |
assignment_group | fixed, your maintenance group sys_id or name | "Plant Maintenance" |
cmdb_ci | {{machine_id}}, if your CMDB keys on it | mint_7f3a91c4 |
correlation_id | {{trigger_id}}, dedupes repeat fires | 4f2c8b1e-... |
In your ServiceNow instance: User Administration → Users → New. Check Web service access only, then grant a role that can insert into incident (itil is the usual choice; a scoped custom role is tighter).
Basic auth is the fastest path and is what this template uses. If your instance requires OAuth, register the app under System OAuth → Application Registry → Create an OAuth API endpoint for external clients, then use "auth_type": "bearer" with the access token instead. Note that ServiceNow OAuth access tokens expire (30 minutes by default), so bearer works for a proof of concept but a production deployment should either use Basic with a service account or refresh the token on a schedule.
Instance URL: https://YOUR_INSTANCE.service-now.com Endpoint: POST /api/now/table/incident Credentials: forge.integration : YOUR_PASSWORD
Forge accepts user:pass raw and base64-encodes it for you. The secret is encrypted at rest and cannot be read back.
curl -sS -X POST https://forge.foundrynet.io/v1/tools \
-H "Authorization: Bearer $FORGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "ServiceNow incident (high urgency)",
"description": "Open a P2 incident for a confirmed machine threshold breach",
"url": "https://YOUR_INSTANCE.service-now.com/api/now/table/incident",
"method": "POST",
"auth_type": "basic",
"auth_secret": "forge.integration:YOUR_PASSWORD",
"headers": { "Accept": "application/json" },
"payload_template": {
"short_description": "{{trigger_name}} on {{machine_id}}",
"description": "Forge detected a threshold breach.\n\nMachine: {{machine_id}}\nOEM / model: {{oem}} {{model}}\nSite: {{site}}\nCanonical field: {{field}}\nActual value: {{value}}\nThreshold: {{threshold}}\nDetected at: {{timestamp}}\n\nRecommended action: inspect the spindle drive and coolant delivery before the next production run. Confirm the reading at the controller, then clear or escalate.\n\nForge trigger: {{trigger_name}} ({{trigger_id}})",
"urgency": "1",
"impact": "2",
"category": "Hardware",
"assignment_group": "Plant Maintenance",
"cmdb_ci": "{{machine_id}}",
"correlation_id": "{{trigger_id}}"
}
}'
urgency and impact as strings and coerces them, so the quoted "1" above is correct and not a workaround.
In plain terms: when spindle load stays above 95 percent, open an incident with the prediction details, machine ID, recommended action, and urgency.
curl -sS -X POST https://forge.foundrynet.io/v1/triggers \
-H "Authorization: Bearer $FORGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Spindle load critical",
"machine_id": "YOUR_MACHINE_ID",
"condition": { "field": "spindle_load_pct", "op": "gt", "value": 95 },
"actions": [ { "tool_id": "TOOL_ID_FROM_STEP_2" } ],
"enabled": true
}'
For a rule that should only fire on a sustained condition rather than a single spike, add a duration:
"condition": { "field": "spindle_load_pct", "op": "gt", "value": 95, "sustained_for": "10m" }
sustained_for and stores the trigger, but the evaluation engine treats stateful conditions as no-ops until the state-tracking layer ships. Use a plain threshold today, or the incident will never open.
Register a second tool identical to step 2 but with "urgency": "3" and a lower threshold, then a matching trigger. Two rules, two urgencies, no expression logic.
Confirm delivery, including the ServiceNow response body with the created sys_id:
curl -sS https://forge.foundrynet.io/v1/triggers/TRIGGER_ID/executions \ -H "Authorization: Bearer $FORGE_API_KEY"
POST /api/now/table/incident
Authorization: Basic Zm9yZ2UuaW50ZWdyYXRpb246...
Content-Type: application/json
Accept: application/json
X-FoundryNet-Trigger-Id: 4f2c8b1e-9a30-4c77-b1e2-0d5f7a3c9e18
{
"short_description": "Spindle load critical on mint_7f3a91c4",
"description": "Forge detected a threshold breach.\n\nMachine: mint_7f3a91c4\nOEM / model: Haas VF-2\nSite: Plant 3 / Cell B\nCanonical field: spindle_load_pct\nActual value: 97.4\nThreshold: 95\nDetected at: 2026-07-28T18:04:11.882714+00:00\n\nRecommended action: inspect the spindle drive and coolant delivery before the next production run...",
"urgency": "1",
"impact": "2",
"category": "Hardware",
"assignment_group": "Plant Maintenance",
"cmdb_ci": "mint_7f3a91c4",
"correlation_id": "4f2c8b1e-9a30-4c77-b1e2-0d5f7a3c9e18"
}
A predicted_breach trigger asks Forge to forecast the series and fire before the threshold is crossed. It is the more valuable signal, and today it delivers differently.
curl -sS -X POST https://forge.foundrynet.io/v1/triggers \
-H "Authorization: Bearer $FORGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Bearing temp will breach within 24h",
"machine_id": "YOUR_MACHINE_ID",
"condition": {
"type": "predicted_breach",
"field": "sensor_readings.bearing_temp",
"threshold": 95,
"direction": "above",
"breach_within_hours": 24,
"confidence_threshold": 0.7
},
"webhook_url": "https://your-shim.example.com/forge/predicted-breach",
"enabled": true
}'
webhook_url and ignores actions[], so there is no payload template and no tool auth on this path. Pointing it straight at ServiceNow would create an incident with no short_description and no credentials. Receive it at your own endpoint and forward it to the Table API.
The forecast payload your shim receives, verbatim:
{
"type": "predicted_breach_alert",
"machine_id": "mint_7f3a91c4",
"trigger": "Bearing temp will breach within 24h",
"kind": "predicted_breach_alert",
"payout_eligible": false,
"field": "sensor_readings.bearing_temp",
"threshold": 95,
"direction": "above",
"forecast": {
"will_breach": true,
"time_to_breach_hours": 9.4,
"breach_within_hours": 24,
"breach_window": [7.1, 12.8],
"confidence": 0.83,
"current_value": 88.6,
"cadence_seconds": 900
},
"action": "draft_work_order",
"note": "ALERT/work-order only — predictions never trigger parametric payouts."
}
Map time_to_breach_hours to urgency in your shim, which is where that logic belongs anyway:
ttb = body["forecast"]["time_to_breach_hours"] urgency = "1" if ttb <= 4 else "2" if ttb <= 12 else "3"
payout_eligible: false, so a forecast can open a work order but can never settle a parametric payout. Payouts settle on attested actuals only.