OCNORA
insuranceintermediate25 min setupby Mantle

First notice of loss: extract, validate, triage

A claim notification arrives by webhook; AI extracts the loss details, the payload is validated, an adjuster triages it and the claim is opened in Iris.

Drag to pan, pinch to zoom. This is the real graph the template installs.

How it works

What it does

  • Webhook fnol receives the free-text loss description (plus policy ref / reporter email).
  • Extract loss detailsValidate extraction guarantees loss_type and loss_date are present before a person sees it.
  • Adjuster triage pauses the run for a decision (24 h timeout); Open claim in Iris or Refer to SIU.

Setup

  • AI connection on the extractor; Iris connection on Open claim in Iris (adjust entity_type / payload); SendGrid/SMTP on the referral email.

Nodes 7

  1. 01Loss notificationtrigger.webhookTrigger
  2. 02Extract loss detailsai.extractAI
  3. 03Validate extractiondata.json_validateData
  4. 04Adjuster triagehuman.promptHuman
  5. 05Accepted?control.branchLogic
  6. 06Open claim in CRMhttp.requestHTTP
  7. 07Refer to SIUmail.sendDestination
View template JSON
{
  "format": "mantle-workflow/v1",
  "id": "insurance-fnol-triage",
  "name": "First notice of loss: extract, validate, triage",
  "graph": {
    "nodes": [
      {
        "id": "webhook",
        "type": "trigger.webhook",
        "label": "Loss notification",
        "config": {
          "slug": "fnol",
          "input_schema": {
            "required": [
              "description"
            ],
            "properties": {
              "description": {
                "type": "string"
              },
              "policyReferenceId": {
                "type": "string"
              },
              "reporterEmail": {
                "type": "string"
              }
            }
          }
        },
        "connection_id": null,
        "worker_type": "generic-worker",
        "position": {
          "x": 60,
          "y": 220
        }
      },
      {
        "id": "ai_extract",
        "type": "ai.extract",
        "label": "Extract loss details",
        "config": {
          "model": "claude-sonnet-4-5",
          "temperature": 0,
          "text": "{{ $json.description }}",
          "schema": {
            "type": "object",
            "required": [
              "loss_type",
              "loss_date"
            ],
            "properties": {
              "loss_type": {
                "type": "string",
                "enum": [
                  "collision",
                  "theft",
                  "fire",
                  "water",
                  "liability",
                  "other"
                ]
              },
              "loss_date": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "location": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "estimated_amount": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "injuries": {
                "type": "boolean"
              }
            }
          }
        },
        "connection_id": null,
        "worker_type": "ai-worker",
        "position": {
          "x": 380,
          "y": 220
        }
      },
      {
        "id": "validate",
        "type": "data.json_validate",
        "label": "Validate extraction",
        "config": {
          "path": "response",
          "schema": {
            "type": "object",
            "required": [
              "loss_type",
              "loss_date"
            ],
            "properties": {
              "loss_type": {
                "type": "string"
              },
              "loss_date": {
                "type": "string"
              }
            }
          },
          "on_fail": "error"
        },
        "connection_id": null,
        "worker_type": "generic-worker",
        "position": {
          "x": 700,
          "y": 220
        }
      },
      {
        "id": "adjuster_triage",
        "type": "human.prompt",
        "label": "Adjuster triage",
        "config": {
          "prompt_text": "New {{ steps.ai_extract.response.loss_type }} loss on {{ steps.ai_extract.response.loss_date }} (est. {{ steps.ai_extract.response.estimated_amount }}). Injuries: {{ steps.ai_extract.response.injuries }}.\n\nAccept the claim or refer it?",
          "options": [
            {
              "id": "accept",
              "label": "Open claim"
            },
            {
              "id": "refer",
              "label": "Refer to SIU"
            }
          ],
          "timeout_seconds": 86400
        },
        "connection_id": null,
        "worker_type": "generic-worker",
        "position": {
          "x": 1020,
          "y": 220
        }
      },
      {
        "id": "branch_accept",
        "type": "control.branch",
        "label": "Accepted?",
        "config": {
          "mode": "first_match"
        },
        "connection_id": null,
        "worker_type": "generic-worker",
        "position": {
          "x": 1340,
          "y": 220
        }
      },
      {
        "id": "create_claim",
        "type": "http.request",
        "label": "Open claim in CRM",
        "config": {
          "method": "POST",
          "url": "https://crm.example.com/api/claims",
          "json": {
            "policyReferenceId": "{{ steps.webhook.policyReferenceId }}",
            "lossType": "{{ steps.ai_extract.response.loss_type }}",
            "lossDate": "{{ steps.ai_extract.response.loss_date }}",
            "estimatedAmount": "{{ steps.ai_extract.response.estimated_amount }}",
            "description": "{{ steps.webhook.description }}"
          }
        },
        "connection_id": null,
        "worker_type": "generic-worker",
        "position": {
          "x": 1660,
          "y": 30
        }
      },
      {
        "id": "send_referral",
        "type": "mail.send",
        "label": "Refer to SIU",
        "config": {
          "to": "siu@example.com",
          "subject": "Referral: {{ steps.ai_extract.response.loss_type }} loss, policy {{ steps.webhook.policyReferenceId }}",
          "body_text": "{{ steps.webhook.description }}"
        },
        "connection_id": null,
        "worker_type": "generic-worker",
        "position": {
          "x": 1660,
          "y": 410
        }
      }
    ],
    "edges": [
      {
        "from": "webhook",
        "to": "ai_extract"
      },
      {
        "from": "ai_extract",
        "to": "validate"
      },
      {
        "from": "validate",
        "to": "adjuster_triage"
      },
      {
        "from": "adjuster_triage",
        "to": "branch_accept"
      },
      {
        "from": "branch_accept",
        "to": "create_claim",
        "branch": "true",
        "condition": {
          "match": "all",
          "rules": [
            {
              "left": "response",
              "op": "equals",
              "right": "accept"
            }
          ]
        },
        "label": "open"
      },
      {
        "from": "branch_accept",
        "to": "send_referral",
        "branch": "false",
        "label": "refer",
        "priority": 1
      }
    ]
  }
}

Use it, then make it yours.

Templates install as drafts. Change anything, and Workflow Health re-checks the graph on every save.