The branch-decision contract: from CDP to flows
A customer browses your store, adds an item to their cart, and checks out. The CDP records three events —Product Viewed, Add to Cart, Order Completed — on the same append-only stream. A flow reads the Order Completed event, evaluates whether the order total exceeds $100, and
branches: yes sends a loyalty discount, no sends a standard
confirmation. The audit log records both the fact and the branch the
flow took.
That chain — a CDP fact driving a flow branch, with an audit
verdict recording the outcome — is the branch-decision contract. This
page defines the envelope that carries that hand-off, walks through one
end-to-end example, and documents the three guard-rails that prevent the
two halves from reading different versions of the same truth.
What a branch-decision event is
A branch-decision event is not a separate event type or a new API resource. It is the intersection of three existing primitives:- The CDP fact — a behavioral event (
trackcall), a segment membership change, a score crossing a threshold, or a tracking-plan signal. The CDP event model defines the envelope it arrives in and how it binds to a contact. - The flow condition node — the point in a flow
execution where a
conditionnode evaluates a predicate (segment.repeat_buyers = true,order.total > 100,intent = 'refund') and picks a handle (yes/no, an intent name, a sentiment bucket). The execution enters the routed arm. - The audit verdict — the row the audit log writes when the branch is taken, recording which predicate was evaluated, which handle was chosen, and at what time. The audit ledger model owns the schema.
What the two subgroups actually cover
The Concepts tree divides the question cleanly. Whichever subgroup you landed on tells you which half you own:- CDP & Intelligence covers the capture side — CDP events, identity resolution, segments, scoring, and the rendered analytics surface. Its output is a fact a flow can read.
- AI & Automation covers the action side — flows, runs (executions), and follow-up steps. Its output is a branch and a recorded step trace — not a new CDP fact.
The two flagship pages, one paragraph each
- CDP & Intelligence’s flagship is the Analytics pipeline: raw events feed into rollup groupings, which feed into statistics, which feed into the charts a customer reads — all on the same append-only event stream the CDP event model defines.
- AI & Automation’s flagship is the Flow execution model: a flow definition becomes a run through the trigger catalog and node semantics, advancing node by node through handles until a webhook hand-off or a terminal state closes it.
The build-your-first-branch contract
When a flow condition node evaluates a CDP fact and picks a branch, the execution writes one step in the execution trace. The canonical shape of that step is:predicate— the expression the condition node evaluated, in the same syntax you authored in the flow builder.resolved_value— the result of resolving the predicate against the execution context at that moment. This is the value the CDP fact produced when the branch read it.selected_handle— the outgoing edge the flow took. For a binary condition,yesorno; for an AI classifier, the intent name; for an A/B split, the variant label.context_snapshot— the subset of execution context the predicate read, captured so the audit log can reconstruct what the branch saw without replaying the whole run.timestamp— the moment the branch was evaluated. This is the wall-clock time on the flow executor, not the CDP event’soriginalTimestamp.
steps[] array and is
addressable by step_id. The audit log reads the same row; nothing in
the chain invents a separate branch-event type.
Worked example: a loyalty-discount branch
A repeat-buyer segment drives a flow that sends a loyalty discount to high-value orders. Here is the end-to-end chain:1. The CDP leg — the fact is recorded
Atrack call lands on the CDP event model
ingest surface:
repeat_buyers = true
(unmodified since Q2 2026; the segment gate is tenant-owned, per the
compliance tenant-owned model).
2. The flow leg — the branch is taken
A published flow with a webhook trigger and acondition node fires:
condition node
(condition_loyalty), it resolves:
yes arm routes to a sendEmail action that dispatches a 15% loyalty
discount template. The per-resume execution budget (300 s, per the
flow-execution model) applies from the
moment the condition node is reached.
3. The audit leg — the verdict is written
The audit log records a branch-verdict row:execution_id and by condition_node, so
you can ask two questions: “what did this run decide?” and “what did this
condition node decide across all runs?” The verdict field carries the
same terminal status the execution carries — if the execution timeouts,
the audit verdict is timeout, not completed.
Three guard-rails
Three constraints prevent the CDP fact and the flow branch from reading different versions of the truth. Each one answers a specific “why did my branch pick the wrong handle?” question.1. The no-ACK window (~30 minutes for SMPP)
A branch that reads asent-leg delivery receipt inside the carrier’s
no-DLR grace window is reading a pending fact, not a final fact.
For SMPP channels, the grace window is 30 minutes — a sent status
that has not yet received a delivered or failed DLR is in-flight,
not terminal. If your flow condition reads message.status = 'sent' and
branches within that window, the audit row records the verdict as
pending_dlr, not completed.
The timer contract is defined in the DLR model: two
planes. To avoid the most common audit
muddle, configure your condition node to gate on the delivery receipt
parent (dlr_anchor) rather than the carrier status field, and set a
minimum age (at least 30 minutes) on the receipt before branching.
2. Ownership — only one side decides
A branch on the same fact must have exactly one owner. When a flow’scondition node and a CDP audience rule both claim to decide a routing
outcome, the two decisions race — and the audit log records whichever one
fired last, not whichever one was correct.
The contract resolves this: the flow owns the branch decision. A CDP
segment or score supplies the input (a true/false, a numeric
value, a trait), and the flow’s condition node consumes it. A CDP rule
should never write a branch outcome that a flow could also write — if
both systems need the same decision, route the CDP rule into a flow
trigger, so the flow remains the single owner of the selected_handle.
3. The execution timeout (300 seconds)
Every flow run has a per-resume execution budget of 300 seconds (defined in the flow-execution model). A run that exceeds this budget finalises astimeout — a hard failure
verdict, not completed, and not an in-flight run that “caught up.”
A branch that follows a timed-out run without treating the verdict as a
terminal failure is the second way an audit row can read a wrong
conclusion. When your flow condition reads the outcome of a prior run,
check the prior run’s status before consuming its selected_handle:
timeout means the branch never actually completed, and the handle is
not a valid input.
The return path: what the audit log reads back
After the branch is taken and the flow completes (or times out), two read surfaces surface the same verdict:- The execution trace (
GET /api/v1/flows/:flow_id/executions/:id) includes the condition step with itsselected_handleandcontext_snapshot. This is the flow executor’s own record — the action-side view. - The audit log (
GET /api/v1/audit?execution_id=exec_branch01) records the same branch verdict, cross-referenced by execution ID. This is the system-of-record view — the one group-by-kind charts and aggregate reads consume.
steps[] array. There is no cross-subgroup exchange that
can diverge — the flow writes the branch step, and the audit log reads
the same step. A group-by-condition-node chart that queries the audit log
and a run-level trace that queries the execution API return the same
selected_handle for the same execution_id.
Related
- CDP event model — the append-only event stream that produces the facts a branch reads.
- Flow execution model — the run advancing the condition node and routing through handles.
- Analytics pipeline — the conversation → statistics → inference chain the aggregate read rides.
- DLR model: two planes — the timer contract that defines the no-ACK caveat’s grace window.
- Audit ledger model — the schema that records the branch verdict.