graph loanApproval {

  node fetchApplication : FetchApplicationOperator {
    input {
      appId = ctx.appId
    }
    timeout = 3s
  }

  node checkCredit : CheckCreditOperator {
    depends_on = [fetchApplication]
    input {
      userId = fetchApplication.output.userId
    }
    retry = { attempts: 3, backoff: 200ms, strategy: exponential }
    fallback = { score: 0, level: "unknown" }
  }

  node detectFraud : DetectFraudOperator {
    depends_on = [fetchApplication]
    input {
      userId = fetchApplication.output.userId
      amount = fetchApplication.output.amount
    }
    timeout = 5s
    fallback = { riskScore: 1.0, flags: ["service_unavailable"] }
  }

  node verifyIncome : VerifyIncomeOperator {
    depends_on = [fetchApplication]
    input {
      userId = fetchApplication.output.userId
    }
    timeout = 5s
  }

  node checkBlacklist : CheckBlacklistOperator {
    depends_on = [fetchApplication]
    input {
      userId = fetchApplication.output.userId
    }
    timeout = 3s
  }

  node aggregateRisk : AggregateRiskOperator {
    depends_on = [checkCredit, detectFraud, verifyIncome, checkBlacklist]
    input {
      credit    = checkCredit.output
      fraud     = detectFraud.output
      income    = verifyIncome.output
      blacklist = checkBlacklist.output
    }
  }

  node makeDecision : MakeDecisionOperator {
    depends_on = [aggregateRisk]
    input {
      risk        = aggregateRisk.output
      application = fetchApplication.output
    }
  }

  branch on makeDecision.output.decision {
    "approved"  -> approveLoan
    "rejected"  -> rejectLoan
    otherwise   -> manualReview
  }

  node approveLoan : ApproveLoanOperator {
    depends_on = [makeDecision]
    input {
      application = fetchApplication.output
      risk        = aggregateRisk.output
    }
  }

  node rejectLoan : RejectLoanOperator {
    depends_on = [makeDecision]
    input {
      reason = makeDecision.output.reason
    }
  }

  node manualReview : ManualReviewOperator {
    depends_on = [makeDecision]
    input {
      application = fetchApplication.output
      risk        = aggregateRisk.output
    }
  }
}
