My usual workaround is to bypassing the REST API entirely for internal logic reuse, as the executeFlow endpoint is strictly designed for initiating new interaction lifecycles, not procedural subroutines.
Is it possible to invoke a shared Common Module flow directly from an Architect Data Action without triggering a full transfer, effectively mimicking a Twilio Studio sub-flow execution?
The core misunderstanding here is treating Architect flows as stateless API endpoints. They are stateful execution contexts. When you hit /api/v2/flows/{flowId}/execute, you are telling the platform to spawn a new thread. If that flow is already associated with the current interaction context (which it is, if you are trying to “reuse” it within the same call), the platform rightly returns a 409 Conflict to prevent infinite loops or context corruption.
In the Web Messaging SDK, we handle similar state management by maintaining a single WebSocket connection and managing session tokens manually. You cannot “call” a flow; you must route to it.
The correct pattern is to use a Flow Transfer action within Architect, specifically a “Transfer to Flow” step, rather than a Data Action calling a REST endpoint. If you absolutely must trigger this from code (e.g., via a custom integration or external webhook), you cannot use executeFlow. Instead, you must update the interaction’s disposition or attributes to trigger a routing rule that moves the interaction into the target flow.
However, for true “sub-flow” behavior, you should refactor your Common Module into a set of Reusable Data Actions or use Architect’s built-in “Include” pattern (if available in your specific Architect version via drag-and-drop sub-flows). If you are stuck with the current architecture, consider using a Queue Transfer or Skill-based Routing to move the interaction to a secondary flow that contains your common logic, then transfer back. This is verbose, but it respects the platform’s state model.
Here is why the REST approach fails:
// This will fail if the interaction is already bound to a flow context
POST /api/v2/flows/{flowId}/execute
{
"reason": "subroutine_call" // Invalid semantic for this endpoint
}
Stop trying to force procedural programming paradigms onto a stateful routing engine. Refactor the common logic into a separate flow and use standard transfer mechanisms.