Hey everyone,
We’re trying to implement some branching logic in a CXone Studio flow using ASSIGN and IF actions, but the trace context seems to get lost when the flow hits a conditional branch that doesn’t match.
Here’s the setup: we have a Data Action that calls an internal service, and we’re trying to propagate the OTel trace context via custom headers. The issue is that when the IF action evaluates to false, the subsequent actions don’t seem to pick up the correct context, leading to orphaned spans in Jaeger.
Here’s a snippet of our Studio flow:
{
"assignments": [
{
"name": "traceContext",
"type": "string",
"value": "{{GetRESTProxy('traceContext')}}"
}
],
"conditions": [
{
"name": "isHighPriority",
"type": "boolean",
"value": "{{IF(GetRESTProxy('priority') == 'high', true, false)}}"
}
],
"actions": [
{
"name": "highPriorityAction",
"type": "REST",
"condition": "isHighPriority",
"headers": {
"X-Trace-Id": "{{traceContext}}"
}
},
{
"name": "defaultAction",
"type": "REST",
"condition": "!isHighPriority",
"headers": {
"X-Trace-Id": "{{traceContext}}"
}
}
]
}
The problem is that when isHighPriority is false, the defaultAction doesn’t seem to carry the X-Trace-Id header correctly, resulting in a broken trace. We’ve verified that the GetRESTProxy('traceContext') call works fine in other parts of the flow.
Has anyone run into this issue before? Any ideas on how to ensure the trace context is properly propagated across conditional branches in CXone Studio?
Thanks,
Cr
Docs state: “OpenTelemetry context propagation requires the traceparent header to be explicitly passed through each hop in the request chain.” You’re hitting the wall because CXone Studio’s IF action doesn’t automatically carry forward custom headers into the false branch unless you explicitly map them in the output configuration.
The trace context lives in the traceparent header. If your Data Action sets it, the next action needs to read it. But the IF action is a gate. It evaluates a condition. It doesn’t pass headers through by default. You have to tell it to.
Check your IF action settings. Under “Outputs” or “Variables”, make sure you’re exposing the traceparent variable to both branches. Or better yet, use a Set Variable action right after the IF to re-assign the header for the downstream Data Action.
Here’s how you force the context through in a Studio flow using a Set Variable action as a bridge:
- Data Action 1: Calls your service. Ensure the response includes the
traceparent header in the response body or headers.
- IF Action: Checks your logic.
- Set Variable Action (in both branches):
- Variable Name:
otel_traceparent
- Value:
{{dataAction1Response.headers.traceparent}}
- Data Action 2: Uses
{{otel_traceparent}} in its header configuration.
If you skip step 3, the context dies. The docs are clear on this: “Context must be explicitly propagated across service boundaries.” Studio is the boundary. You have to build the bridge.
{
"name": "Propagate Trace Context",
"type": "SetVariable",
"configuration": {
"variables": [
{
"name": "otel_traceparent",
"value": "{{previousDataActionResponse.headers.traceparent}}"
}
]
}
}
Make sure your downstream service is actually reading traceparent. If it’s expecting x-trace-id or something else, you’re still going to break. Check the header name.