CML Explainability in Salesforce Revenue Cloud: Setup and Usage Guide

When working with CML in Salesforce Revenue Cloud (now Agentforce Revenue Management), it is easy to focus on what your model does and overlook how the engine executes it. And when something goes wrong – a rule does not fire, a default behaves unexpectedly – the constraint solver often feels like a black box. 

For small models, that is fine. But as the model grows – more products, more constraints, more interactions – execution starts to matter. 

The Explainability tool changes that. It records every engine action, every reaction, and every constraint evaluation that happens during a configuration request. 

So you can see not just what the model produces, but how the solver got there.

In this article, we walk through two CML models that produce the same configuration but execute very differently – and use Explainability to show why. Our team has prepared a downloadable practical guide covering how to enable it in your org.

Summary

  • CML Explainability logs every engine action, reaction, and constraint evaluation for a given configuration request – so you can see how the solver reached its result.
  • Two CML models with the same output can execute very differently – 15 constraint satisfy attempts vs 6 in our example.
  • Reaction count alone is not a performance indicator. Constraint satisfy attempts are the metric that actually tracks solver workload.
  • Logs are accessible through the UI, downloadable as JSON, and queryable through the DES Connect API – so the same data feeds manual debugging, automated diagnostics, and CI pipelines.
  • Setup requires a permission set and four Decision Explainability definitions – covered in the downloadable guide.

How CML Explainability works

Explainability reads the constraint engine's logs and splits them into three UI sections based on the type of event. Each section shows a different layer of what happened during the request: 

  1. Engine Actions – high-level phases of execution. Things like validation, attribute assignment, instantiation of a default, evaluation of a relation.
  2. Reactions – individual state changes. A cardinality variable moving from 0..3 to 1..3. A component count being updated. An attribute being locked to a specific value.
  3. Constraint Satisfy Attempts – how many times each constraint was re-evaluated while the solver was propagating changes and looking for a stable state.

With Explainability enabled, every one of these is captured for the request. You can see which actions fired, in what order, how long each one took, which variables they modified, and which constraints triggered which reactions. You can also download the full log as JSON for offline analysis.

That visibility is useful for correctness debugging – figuring out why a product wasn't added, or why a rule didn't fire. But the less obvious payoff is performance.

Why this matters: two models, same result, different cost

Here is a scenario from a real Revenue Cloud implementation. The goal is simple – a bundle that always contains exactly one of three child products.

Approach 1: constraint-based

type CMABundle {

    relation childProducts : ChildProduct[0..3];

    constraint(childProducts[ChildProduct1] == 1);

    constraint(childProducts[ChildProduct2] == 1);

    constraint(childProducts[ChildProduct3] == 1);

}

type ChildProduct;

type ChildProduct1 : ChildProduct;

type ChildProduct2 : ChildProduct;

type ChildProduct3 : ChildProduct;

Engine behavior overview with Explainability tool:

Reads cleanly. Three explicit constraints, one per child product. The engine is told the rules; it figures out the configuration.

Running this with Explainability enabled shows:

  • 1 engine action (AndGoal) with 13 reactions
  • 4 triggered constraints (3 user-defined + 1 internal CardinalityConstraint)
  • 15 total constraint satisfy attempts

Each user-defined constraint is evaluated three times, because updating one cardinality domain triggers the others to re-evaluate, which in turn triggers another round of re-evaluation – the classic propagation cascade. The internal CardinalityConstraint is touched six times for the same reason.

Approach 2: default-based

type CMABundle {

    relation childProducts : ChildProduct[0..3] {

        default ChildProduct1(1);

        default ChildProduct2(1);

        default ChildProduct3(1);

    }

}

Engine behavior overview with Explainability tool:

Same types, same end state. The difference: instead of constraints telling the solver what must be true, defaults tell the solver what to build.

Explainability output for this version:

  • 3 engine actions (InstantiateDefaultPortComponents), 22 reactions in total
  • 1 triggered constraint – the internal CardinalityConstraint
  • 6 total constraint satisfy attempts

More reactions, but fewer constraint evaluations. The default-based model does more bookkeeping – each instantiation is a sequence of small state changes — but avoids solving entirely. The engine builds the configuration directly instead of deriving it.

Comparison of both approaches

Metric Constraint Model (Example 1) Default Model (Example 2)
Engine Actions 1 3
Total Reactions 13 22
Triggered Constraints 4 1
Constraint Satisfy Attempts 15 6
Constraint Solving Required Yes No
Instantiation Strategy After solving Immediate
Propagation Overhead High Low

Why this matters at scale

In a three-product bundle, the gap between 15 and 6 evaluations is not something a user will notice. But the ratio does not shrink when the model grows – it scales with the number of products and constraints. In a real catalog with hundreds of items and thousands of constraints, the same propagation pattern accounts for a significant share of solver time.

This does not mean defaults should replace constraints. Constraints are the right tool when valid configurations genuinely depend on conditions the engine needs to solve for. But when the desired configuration is known upfront, using constraints to describe it forces the solver to derive something that could have been declared directly.

Accessing the logs

With Explainability enabled, logs appear in a new Configuration Logs list inside the Revenue Cloud Operations Console – browsable in the UI, downloadable as JSON, or queryable programmatically through the DES Connect API.

The toggle itself is a one-click switch at request time, but the plumbing behind it is not: Explainability requires a specific permission set and several Decision Explainability definitions in Setup before the toggle becomes available. Once those are in place, every request run with the toggle on produces a full log.

The full setup, in one guide

Enabling Explainability is not a one-click feature flag.

The permission set has to target the right license. The four Decision Explainability definitions in Setup – Application Subtype, Business Process Type, Explainability Action Definition, and Explainability Action Version – each requires specific field values. An incorrect value in any of them will prevent the toggle from becoming available.

Our team has prepared a practical guide covering permission set configuration, the four Decision Explainability definitions with exact field values, API access, and the troubleshooting workflow we use in production.

The guide covers:

  • Permission set configuration (EnableConfigurationLogAccess)
  • All four Decision Explainability definitions with exact field values and screenshots
  • Accessing logs through the Operations Console UI and via the DES Connect API, including the full property reference
  • Troubleshooting workflow: what to check when logs do not appear as expected

Wrapping up

Configuration performance in Revenue Cloud (now Agentforce Revenue Management) has always been a function of two things: the model you write, and the way the solver executes it. Until Explainability, only the first half was visible. Now both are.

For teams debugging rule misfires, that means faster diagnosis. For teams optimizing performance, it means actual data instead of intuition about what the solver is doing. And for teams reviewing each other's CML in code review, it means being able to compare two approaches on something more concrete than readability.

If you have a sandbox with CML models that have been growing for a while, this is worth an afternoon. Enable the toggle, run your most-used configurations, and look at the constraint satisfy attempts. The number will either confirm your model is clean, or tell you exactly where to look first.

FAQ: CML Explainability

Is Explainability meant to run all the time?

No. It is a diagnostic tool you turn on when you need to inspect a specific configuration, then turn off. The logs are detailed by design, so continuous logging is not the intended workflow.

Who needs Explainability enabled?

Developers and admins working with CML. End users do not need it. You assign the EnableConfigurationLogAccess permission to the people who should see the toggle.

The toggle is on but I do not see any logs. Why?

Usually a missing or misconfigured Decision Explainability definition in Setup. All four definitions have to be in place with the correct field values. 

Can I export the logs?

Each log downloads as JSON from the Configuration Logs detail view. The same data is also available through the DES Connect API at /connect/decision-explainer/action-logs.

Do I need a special edition of Revenue Cloud for this?

No. Explainability is part of the Advanced Configurator. What you do need is the EnableConfigurationLogAccess user permission and the four Decision Explainability definitions in Setup — without them the toggle will not appear.

Latest Blog Posts
Ready to accelerate your revenue growth?
CML Explainability Setup Guide

A practical guide from the Veloce team on enabling, accessing, and troubleshooting CML Explainability in Salesforce ARM.