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.

Loss notificatioExtract loss detValidate extractAdjuster triageAccepted?Open claim in CRRefer to SIU

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

Purpose

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.

How it works

What it does

  • Webhook fnol receives the free-text loss description (plus policy ref / reporter email).
  • Extract loss details → Validate 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.

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"
              }
            }
          }
        },
        "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"
              }
            }
          }
        },
        "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"
        },
        "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
        },
        "worker_type": "generic-worker",
        "position": {
          "x": 1020,
          "y": 220
        }
      },
      {
        "id": "branch_accept",
        "type": "control.branch",
        "label": "Accepted?",
        "config": {
          "mode": "first_match"
        },
        "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 }}"
          }
        },
        "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 }}"
        },
        "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
      }
    ]
  }
}

Requirements

The connections and permissions each step needs, from the node contracts in the catalog.

  • AnthropicAPI key

    Used by Extract loss details.

    Credential: {"api_key"}

    • The provider adapter is chosen from the connection; `model` must belong to it.
  • SendGridAPI key

    Used by Refer to SIU.

    Credential: {"api_key"} or {"username", "password"}

Setup

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

Sample input and output

Synthetic examples: node-contract samples or placeholders, never customer data.

Input

The fields the template declares or reads from the request body. Values are placeholders.

{
  "description": "<description>",
  "policyReferenceId": "<policyReferenceId>",
  "reporterEmail": "<reporterEmail>",
  "loss_type": "<loss_type>",
  "loss_date": "<loss_date>"
}

Output

Open claim in CRM http.request

{
  "body": null,
  "headers": {},
  "status_code": 0
}

Refer to SIU mail.send

{
  "body": null,
  "message_id": "",
  "provider": "",
  "sent": true,
  "status_code": 0,
  "thread_id": ""
}

Failure handling

What the graph does when a step fails, read from its retry settings, error branches and error policies.

  • Validate extraction: invalid input fails the step, so nothing after it runs on bad data.
  • Adjuster triage: the step fails if nobody answers within 1 day.
  • A step that fails, after any retries, fails the run. The failed step is kept with its input and error.

See it run, then make it yours.

Templates install as drafts. Edit any step, and Workflow Health re-checks the graph on every save.