{
  "name": "AI Extract + Threshold Check + Conditional Alert + KG Sync",
  "goal": "Extract structured metrics from free-form text, compare to configured thresholds, update an external system, alert on breaches only, and persist to the KG for trending.",
  "description": "Pattern 06 (conditional routing) + pattern 09 (KG history). Generic shape for any 'extract-then-monitor' flow: meeting transcripts → KPIs, support tickets → SLA metrics, incident reports → severity. Configure the target CRM/system, alert channel, and thresholds in input pages.",
  "status": "draft",
  "context": {
    "executionInputConfig": {
      "title": "Process Input",
      "description": "Paste the free-form text to extract metrics from.",
      "runCTALabel": "Process",
      "fields": [
        { "name": "source_text", "label": "Source text", "type": "textarea", "required": true },
        { "name": "entity_id", "label": "External entity id (e.g. CRM record id)", "type": "text", "required": true },
        { "name": "language", "label": "Language", "type": "select", "options": ["en", "fr", "es", "de"], "required": true }
      ]
    },
    "inputPages": [
      {
        "title": "Alert Settings",
        "pathname": "alert-settings",
        "configuration": {
          "contextKey": "alertSettings",
          "shortDescriptionFields": ["slackChannel"],
          "fields": [
            { "name": "slackWebhookUrl", "label": "Slack incoming webhook URL", "type": "text", "required": true },
            { "name": "slackChannel", "label": "Slack channel", "type": "text", "required": true }
          ]
        }
      },
      {
        "title": "Thresholds",
        "pathname": "thresholds",
        "configuration": {
          "contextKey": "thresholds",
          "fields": [
            { "name": "metric_a_min", "label": "Metric A floor", "type": "numeric" },
            { "name": "metric_b_max", "label": "Metric B ceiling", "type": "numeric" },
            { "name": "metric_c_min", "label": "Metric C minimum", "type": "numeric" }
          ]
        }
      }
    ]
  },
  "steps": [
    {
      "id": "start",
      "type": "trigger",
      "name": "Manual Start",
      "pipelineStepStartConditions": { "trigger": { "type": "manual" } },
      "next": { "stepId": "extract-metrics" }
    },
    {
      "id": "extract-metrics",
      "type": "aiAction",
      "name": "Extract Metrics (multilingual)",
      "pipelineStepPrompt": {
        "template": "Extract the three target metrics (metric_a, metric_b, metric_c) from this {{input.language}} text. Return null for any metric you cannot confidently extract. Normalize units consistently.\n\nText:\n{{input.source_text}}",
        "responseStructure": {
          "metric_a": "number | null",
          "metric_b": "number | null",
          "metric_c": "number | null",
          "notes": "string"
        }
      },
      "creditCost": 10,
      "next": { "stepId": "check-thresholds" }
    },
    {
      "id": "check-thresholds",
      "type": "code",
      "name": "Compare to Thresholds",
      "codeConfig": {
        "language": "javascript",
        "code": "const k = steps['extract-metrics']; const t = context.thresholds || {}; const breaches = []; if (k.metric_a != null && t.metric_a_min != null && k.metric_a < t.metric_a_min) breaches.push({ metric: 'metric_a', value: k.metric_a, threshold: t.metric_a_min }); if (k.metric_b != null && t.metric_b_max != null && k.metric_b > t.metric_b_max) breaches.push({ metric: 'metric_b', value: k.metric_b, threshold: t.metric_b_max }); if (k.metric_c != null && t.metric_c_min != null && k.metric_c < t.metric_c_min) breaches.push({ metric: 'metric_c', value: k.metric_c, threshold: t.metric_c_min }); return { breaches, breach_count: breaches.length, summary: breaches.map(b => `${b.metric}=${b.value} (limit ${b.threshold})`).join(', ') };"
      },
      "next": { "stepId": "update-external-system" }
    },
    {
      "id": "update-external-system",
      "type": "appAction",
      "name": "Update External System",
      "app": { "id": "http-request", "actionId": "http-request.request", "source": "native" },
      "stepInputData": {
        "url": "https://example.com/api/entities/{{input.entity_id}}",
        "method": "PATCH",
        "body": "{\"metrics\": {{steps.extract-metrics}}}"
      },
      "next": { "stepId": "alert-on-breach" }
    },
    {
      "id": "alert-on-breach",
      "type": "appAction",
      "name": "Slack Alert (breaches only)",
      "app": { "id": "webhook", "actionId": "webhook.trigger", "source": "native" },
      "entryConditions": {
        "onCriteriaFail": "skip",
        "conditionText": "Only alert when at least one threshold is breached.",
        "criteria": [
          { "variable": "{{steps.check-thresholds.breach_count}}", "operator": ">", "value": 0 },
          { "variable": "{{context.alertSettings.slackWebhookUrl}}", "operator": "isNotNull" }
        ]
      },
      "stepInputData": {
        "webhookUrl": "{{context.alertSettings.slackWebhookUrl}}",
        "inputsJson": "{\"text\":\"Threshold breach for {{input.entity_id}}: {{steps.check-thresholds.summary}}\",\"channel\":\"{{context.alertSettings.slackChannel}}\"}"
      },
      "next": { "stepId": "store-history" }
    },
    {
      "id": "store-history",
      "type": "knowledgeSync",
      "name": "Store Metric History",
      "knowledgeSync": {
        "source": { "stepId": "extract-metrics" },
        "listKey": "metric_history",
        "fieldMapping": {
          "metric_a": "metric_a",
          "metric_b": "metric_b",
          "metric_c": "metric_c",
          "notes": "notes"
        }
      },
      "next": { "stepId": "done" }
    },
    {
      "id": "done",
      "type": "milestone",
      "name": "Done"
    }
  ]
}
