CMDB IRE API and Business RulesThe expectation is that Business Rules will always run for all Inserts/Updates/Deletes, but that is not the case for a lot of server-side API database operations, where multiple interrelated records are updated in batches, and that applies to the database operations done by the CMDB Identification and Reconciliation API. The Input Payload At the end is a script, which gives an IRE payload to this API. This is based on a cut-down Discovery payload, and the types of CI chosen to demonstrate the challenges. It contains items for a: Windows Server CIIP Address CINetwork Adapter CI There are Relations between the items: Server "Owns" the Network AdapterNetwork adapter "Owns" the IP AddressServer "Owns" the IP Address And then References defined directly between the items: Network Adapter references the Server in the cmdb_ci fieldIP Address references the Network Adapter in the nic field Processing the Payload When the IRE API processes this payload, it does each of those 8 bullet points one after the other, in the order they are in the payload. For clarity we will assume this server is nothing the CMDB already. The IRE will be inserting these. If they are there, and being updated, then when business rules run or not will apply the same. CIs The 3 CIs are inserted first. The following fields will be populated: The attributes defined in the payload item only. The IRE auditing fields - discovery_source, first_discovered, last_discoveredThe platform auditing fields - sys_created_on/sys_created_by, sys_updated_on/sys_updated_by, etc. On Insert Business Rules will run for each of these inserts. Note: the reference fields are not populated yet. You will not be able to dot-walk between these CIs using the reference fields in your Business Rule scripts on insert. Relationships The Relationships are then inserted. These are cmdb_rel_ci records, which have a Parent, Type and Child field. The CIs will already exist by this point, so it is possible to have a business rule that dot-walks to read values from the parent or child CIs. It would be unsafe for Business rules running on insert of the relationship records to be making changes to those CIs, because we have not yet finished with them - see below. By default, Business rules do not run for these inserts. It is possible to enable business rules to run, using system property glide.identification_engine.insert_relation_disable_workflow, however this will slow down the API, and this does add up for example if you are running a discovery schedule against 100k server overnight, leading to millions of API calls to update the CMDB. Originally the API did not run business rules for these inserts. Customer demand caused this option to be added in 2019, but it is still not recommended. More details in: KB0694512 - On insert business rules do not run on cmdb_rel_ci (CI Relationships) table after discovery This insert is done using GlideRecord, and .setWorkflow() is set depending on that property. References The CIs inserted in the first step are then updated with any reference values. These updates are done using a Java DBUpdate, which bypasses the business rule engine, and also auditing and rollback. That means on update Business Rules do not run for that update at all. This also makes it difficult to see that this did happen as a separate update, unless you have session debug enabled for SQL debug. There is no way to enable business rules for this update. By adding the reference after both CIs are inserted means at no time is it a broken reference, waiting for what it references to be inserted. This prevents business rules in insert from seeing any value in the refence fields and attempting to dot-walk. If there were references before the record being referenced was inserted, there is a risk of null queries returning the whole table instead of the single record, causing updates to the wrong records and performance problems from uncontrolled looping. A business rule running on IP insert is not going to be able to dot-walk up via the nic to the CI on that initial insert. Testing this out This can be run from the "Scripts - Background" page, as an admin user, in Global scope. Session Debug, with Business rules, Log and SQL enabled will allow you to see all the database operations, and if/when the Business Rules engine gets involved with these operations. Turning on IRE API debug, by adding the glide.cmdb.logger.source.identification_engine=info,warn,error,debug,debugVerbose property, will allow you to see the various steps of the IRE payload processing inline with the session debug.Note: don't forget to delete that property afterwards, because it spams the logs and eventually affects instance performance. var payload = {"items" : [ {"className" : "cmdb_ci_win_server","values" : {"sys_class_name" : "cmdb_ci_win_server","serial_number" : "KB1284595 Test Server","ip_address" : "10.229.13.28","name" : "CS6476368 TEST2 Server"}},{"className" : "cmdb_ci_ip_address","values" : {"ip_version" : "4","install_status" : "1","netmask" : "255.255.255.0","ip_address" : "10.0.0.1","sys_class_name" : "cmdb_ci_ip_address"}}, {"className" : "cmdb_ci_network_adapter","values" : {"dhcp_enabled" : "False","install_status" : "1","netmask" : "255.255.255.0","mac_address" : "00:aa:bb:cc:dd:ee","name" : "KB1284595 Test NIC","ip_address" : "10.0.0.1","ip_default_gateway" : "10.0.0.254","sys_class_name" : "cmdb_ci_network_adapter"}} ],"relations" : [ {"type" : "Owns::Owned by","child" : 2,"parent" : 0}, {"type" : "Owns::Owned by","child" : 1,"parent" : 2}, {"type" : "Owns::Owned by","child" : 1,"parent" : 0} ],"references" : [ {"referenceField" : "cmdb_ci","referenceDirection" : "childToParent","child" : 2,"parent" : 0}, {"referenceField" : "nic","referenceDirection" : "childToParent","child" : 1,"parent" : 2} ],"mainCiType" : "cmdb_ci_win_server"};var input = JSON.stringify((payload));var output = sn_cmdb.IdentificationEngine.createOrUpdateCIEnhanced('ServiceNow', input, {});gs.info(JSON.stringify(JSON.parse(output), null, 2));