Pipeline template

Forge → ServiceNow

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.

Setup: ~10 minutes Direct: no shim needed Auth: Basic or OAuth bearer Target: Table API /api/now/table/incident

Before and after

Manual

  1. An operator notices a reading drifting, or does not.
  2. They finish the shift and mention it, or do not.
  3. Someone opens an incident by hand, hours later.
  4. The description says "spindle sounds rough".
  5. No machine ID, no reading, no trend, no timestamp.
  6. Triage starts by re-gathering what the machine already knew.

With Forge

  1. Forge evaluates every normalize event against your condition.
  2. The moment it breaches, an incident opens itself.
  3. Machine ID, canonical field, actual value, and threshold are in the body.
  4. Urgency and impact are set from the rule that fired.
  5. It routes to the right assignment group on creation.
  6. Delivery is logged with the ServiceNow sys_id and status code.

Pick your trigger path

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.

PathCondition typeDeliveryStatus
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
Both paths carry the same information. The difference is only whether Forge can shape and sign the outbound request itself. Start with the threshold path, which is a direct integration, and add forecasting once the incident flow is proven.

Field mapping

What Forge knows, and where it lands in a ServiceNow incident record.

ServiceNow fieldSourceExample
short_descriptiontrigger name + machine + fieldSpindle load breach on mint_7f3a91c4
descriptionfield, actual value, threshold, timestamp, recommended actionmulti-line, see payload below
urgencyfixed per trigger (1 high, 2 medium, 3 low)"2"
impactfixed per trigger, usually by machine criticality"2"
categoryfixed"Hardware"
assignment_groupfixed, your maintenance group sys_id or name"Plant Maintenance"
cmdb_ci{{machine_id}}, if your CMDB keys on itmint_7f3a91c4
correlation_id{{trigger_id}}, dedupes repeat fires4f2c8b1e-...
Urgency is per trigger, not computed. Forge interpolates values into a fixed template; it does not evaluate expressions, so you cannot derive urgency from the value inside the payload. Create one trigger per severity band, each pointing at a tool with its own urgency, and you get the same result with clearer rules. The example below shows the high-urgency band.

Set it up

  1. Create a ServiceNow integration user

    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
  2. Register ServiceNow as a Forge tool

    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}}"
        }
      }'
    ServiceNow accepts urgency and impact as strings and coerces them, so the quoted "1" above is correct and not a workaround.
  3. Create the automation

    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 conditions are accepted but do not fire yet. The kernel validates 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.
  4. Add a second band, then verify

    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"

The incident Forge creates

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"
}

The forecast path

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
  }'
Why a shim is required here. When a prediction fires, the kernel posts a fixed body to 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"
Predictions are alerts, never settlements. Forge records every predicted-breach alert with payout_eligible: false, so a forecast can open a work order but can never settle a parametric payout. Payouts settle on attested actuals only.

Next