Another approach suggested to me and I'm currently experimenting with is to have a master routing workspace and possibly multiple application workspaces. In the first instance the user's input goes to the master which has high level intents that work out which application workspace to route to. The application workspaces have intents that break into more detail.
The subtlety is to then send all subsequent input to both the selected app workspace and the master router in parallel. The potential advantage of this over the sequential approach described previously is that the master workspace can wrestle control rather than having to have it surrendered by off-topic or low confidence. This means as well as allowing off-topic to be centralised you can get dynamic routing to other workspaces using the same intents in the master as the initial routing.
I've done this by having the orchestration layer manage the session as an array of contexts like this
{
currentWs: xxxx,
contexts: {
ws_idn: {}, // basically an array of conversation contexts,
.... // keyed on workspace_id's
}
}
Input gets sent to the master workspace and whichever workspace is marked as current by the master (along with the relevant context object for that workspace). You can seamlessly switch back and forth between multiple chatbot applications without losing context in any of them.