Insurance Claims Adjudication

Claim-to-policy matching, coverage verification, and graduated adjudication. The insurance industry processes billions of claims annually, many through manual review queues that this pipeline helps reduce.

What Gets Automated

Matching claims to policies on policy number, member ID, and date of service. Auto-adjudicating clean claims that fall within coverage limits and have standard procedure codes. AI analysis of coding ambiguities, coverage edge cases, and multi-provider claims.

What Humans Still Own

Complex multi-party claims. Fraud referrals. Policy exception decisions. Appeal adjudication on contested denials.

Pipeline

flowchart TD A[Input: New Claims + Policy Records] --> B[Matcher: Claim-to-Policy] B -->|Policy found| C[Matcher: Duplicate Detection] B -->|No policy match| D[Deny: No Coverage] C -->|No duplicate| E{Auto-Approve Eligible?} C -->|Duplicate found| F[Flag + Halt] E -->|Clean claim ~60%| G[Auto-Adjudicate] E -->|Requires review ~40%| H[ReAct Agent] H --> H1[Verify coverage terms] H1 --> H2[Validate procedure codes] H2 --> H3[Calculate allowed amount] H3 -->|High confidence| I[Auto-Resolve] H3 -->|Low confidence| J[Human Adjudicator] J -->|Approve| K[Process Payment] J -->|Deny| L[Issue Denial Code] J -->|Refer SIU| M[Flag for Investigation] D --> N[Custom Table: Adjudication Log] G --> N I --> N K --> N L --> N F --> N style B fill:#e8a84c,color:#09090b,stroke:none style C fill:#e8a84c,color:#09090b,stroke:none style H fill:#4ade80,color:#09090b,stroke:none style J fill:#60a5fa,color:#09090b,stroke:none

This template uses two matcher steps in sequence: first for claim-to-policy matching, then for duplicate detection. This is the only template with chained matchers.

## Workflow Definition
json
{
  "name": "claims_adjudication",
  "definition": {
    "actions": [
      {
        "type": "matcher",
        "properties": {
          "left": "@input.claims",
          "right": "@input.policies",
          "matchOn": ["policy_number", "member_id"],
          "dateWindowDays": 0,
          "outputMatched": "claims_with_policy",
          "outputUnmatchedLeft": "no_policy_claims",
          "outputUnmatchedRight": "unused_policies"
        }
      },
      {
        "type": "matcher",
        "filter": {
          "condition": {
            "greaterThan": [{ "length": "@claims_with_policy" }, 0]
          }
        },
        "properties": {
          "left": "@input.claims",
          "right": "@input.recent_claims",
          "matchOn": ["member_id", "procedure_code", "service_date"],
          "tolerance": 0,
          "dateWindowDays": 1,
          "outputMatched": "potential_duplicates",
          "outputUnmatchedLeft": "unique_claims",
          "outputUnmatchedRight": "no_dup_match"
        }
      },
      {
        "type": "loop",
        "filter": {
          "condition": {
            "greaterThan": [{ "length": "@unique_claims" }, 0]
          }
        },
        "properties": {
          "mode": "foreach",
          "items_path": "@unique_claims",
          "item_variable_name": "claim",
          "actions_to_execute": [
            {
              "type": "custom-table",
              "properties": {
                "table": "claim_adjudication_cases",
                "operation": "upsert",
                "key_fields": ["run_id", "claim_id"],
                "keys": ["run_id", "claim_id", "policy_number", "procedure_code", "billed_amount", "status"],
                "values": ["@__run_id", "@claim.claim_id", "@claim.policy_number", "@claim.procedure_code", "@claim.billed_amount", "pending_review"]
              }
            }
          ],
          "max_concurrency": 10,
          "failure_strategy": "fail_fast",
          "collect_results": false,
          "result_key": "claim_case_writes"
        }
      },
      {
        "type": "loop",
        "filter": {
          "condition": {
            "greaterThan": [{ "length": "@unique_claims" }, 0]
          }
        },
        "properties": {
          "mode": "react",
          "objective": "Read the current run's claim adjudication cases. For each claim, verify coverage, procedure eligibility, benefit limits, and network status with the declared tools. Recommend approval, denial with a reason code, or human escalation. Do not submit a claim decision.",
          "tools": [
            { "type": "action", "name": "read_claim_adjudication_cases" },
            { "type": "action", "name": "verify_coverage" },
            { "type": "action", "name": "lookup_procedure_codes" },
            { "type": "action", "name": "check_benefit_limits" },
            { "type": "action", "name": "calculate_allowed_amount" }
          ],
          "max_iterations": 15,
          "on_stuck": {
            "iterations": 4,
            "action": "escalate"
          },
          "result_key": "all_adjudications"
        }
      },
      {
        "type": "PbotApproval",
        "properties": {
          "comment": "{{unique_claims.length}} claims adjudicated. {{potential_duplicates.length}} duplicates flagged. Review AI decisions.",
          "request_payload": {
            "adjudications": "@all_adjudications",
            "duplicates": "@potential_duplicates",
            "no_policy_denials": "@no_policy_claims.length"
          }
        }
      },
      {
        "type": "custom-table",
        "properties": {
          "table": "adjudication_log",
          "operation": "write",
          "keys": ["batch_id"],
          "values": ["@__run_id"],
          "fields": {
            "claims_processed": "@input.claims.length",
            "auto_denied_no_policy": "@no_policy_claims.length",
            "duplicates_flagged": "@potential_duplicates.length",
            "adjudicated": "@unique_claims.length",
            "completed_at": "@now"
          }
        }
      }
    ]
  }
}

Required Registered Actions

Action Kind Purpose
verify_coverage http Check policy status and effective dates
lookup_procedure_codes db Retrieve allowed procedure codes for policy type
check_benefit_limits db Query remaining benefit limits for member/year
calculate_allowed_amount http Compute allowed amount per fee schedule
read_claim_adjudication_cases custom-table Read the current run's persisted claim rows

The workflow writes unique claims to claim_adjudication_cases, keyed by run_id and claim_id. Bind read_claim_adjudication_cases to that table with operation: "read" and where: { "run_id": "@__run_id" }. The agent gets a read-only batch view and the approval remains the decision boundary.

Customization Notes

Duplicate detection window. The 1-day dateWindowDays on the second matcher catches same-day duplicate submissions. Extend to 3-5 days if your intake has batch delays.

Batch size. Keep each agent batch within the model and tool limits you have configured. For one agent per claim, launch bounded agent runs from your application with the claim facts or a doc: reference in each objective.

Stuck detection. The escalate action on stuck sends complex claims directly to a human adjudicator rather than retrying: appropriate for claims where incorrect auto-decisions have financial and regulatory consequences.