Can someone please guide me about twilio sms and voice integration with Dialogflow cx?

103 Views Asked by At

i'm searching for guideness about twilio voice and sms and the integration of these with dialogflow cx, i'm just learning about it and I think the information and documentation I've found is not enough and it's kind of confusiong to me.

I've already have a Twilio number connected to a webhook which I created from GCP run and build, but I don't know if I'm ignoring an important step, i'd be very grateful if someone can help me.

I've researching and found a repository where they explain the integration with twilio but focusing in whatsapp, this is my code:

imports...

const sessionClient = new SessionsClient({
  apiEndpoint: `${process.env.LOCATION}-dialogflow.googleapis.com`,
});

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

const listener = app.listen(process.env.PORT || 8081, () => {
  console.log('Your Dialogflow integration server is listening on port ' +
  listener.address().port);
});

const twilioToDetectIntent = (twilioReq) => {
    const sessionId = twilioReq.body.To;
    const sessionPath = sessionClient.projectLocationAgentSessionPath (
        process.env.PROJECT_ID,
        process.env.LOCATION,
        process.env.AGENT_ID,
        sessionId
    );

    const message = twilioReq.body.Body;
    const languageCode = process.env.LANGUAGE_CODE;
    const request = {
        session: sessionPath,
        queryInput:
            {
                text: {
                    text: message
                },
                languageCode
            }
        };
    
    return request;
};

const detectIntentToTwilio = (dialogflowResponse) => {
  let reply = "";
  
  for (let responseMessage of dialogflowResponse.queryResult.responseMessages) {
      if (responseMessage.hasOwnProperty('text')) {
          reply += responseMessage.text.text;
      }
  }

  const twiml = new  MessagingResponse();
  twiml.message(reply);
  return twiml;
};

const getResponseMessage = async (req) => {
  const dialogflowRequest = twilioToDetectIntent(req);
  const [dialogflowResponse] = await sessionClient.detectIntent(dialogflowRequest);
  const twiml = detectIntentToTwilio(dialogflowResponse);
  return twiml.toString();
};

//voice
const sendToDialogflowVoice = async (speechResult, callSid) => {
  const sessionPath = sessionClient.projectLocationAgentSessionPath(
    process.env.PROJECT_ID,
    process.env.LOCATION,
    process.env.AGENT_ID,
    callSid
  );

  const request = {
    session: sessionPath,
    queryInput: {
      audio: {
        config: {
          languageCode: process.env.LANGUAGE_CODE,
        },
        audio: speechResult, // El mensaje de voz
      },
    },
  };

  try {
    const [response] = await sessionClient.detectIntent(request);
    const messageFromDialogflow = response.queryResult.responseMessages[0].text.text;
    return messageFromDialogflow;
  } catch (error) {
    console.error('Something ocurred', error);
    return 'error from Dialogflow.';
  }
};

app.post('/sms', async (req, res) => {
  const message = await getResponseMessage(req);
    console.log("MESSAGE: " + message);
    res.send(message);
});

app.post('/voice', async (req, res) => {
  const speechResult = req.body.SpeechResult;
  const callSid = req.body.CallSid;
  const dialogflowResponse = await sendToDialogflowVoice(speechResult, callSid);

  const twiml = new MessagingResponse();
  twiml.message(dialogflowResponse);

  res.setHeader('Content-Type', 'text/xml');
  res.send(twiml.toString());
});

process.on('SIGTERM', () => {
  listener.close(async ()=> {
    console.log('Closing server.');
    process.exit(0);
  });
});

exports...
1

There are 1 best solutions below

0
On

You can integrate with Voice using One click Integration but would have to add this "virtualagent-ccai-prod@dialogflow-prod-env.iam.gserviceaccount.com" in your project via IAM.

Link to One Click Integration of Voice Agent with Twilio:

For Integrating with SMS you would have to build via Twilio Studio.

Step#1: Create Session for incoming First Message.

Step#2: Pass the Session and First incoming Message to Dialogflow API.

Step#3: Send the Dialogflow API response via Send and Wait Widget to wait for user response this will work in a loop. You will also to add a way to handle end session and so on.

Just Import this into Twilio Studio adjust according to your Needs. Let me know if further help is needed : )

    {
  "description": "Dialogflow CX Sample",
  "states": [
    {
      "name": "Trigger",
      "type": "trigger",
      "transitions": [
        {
          "next": "SetUtteranceVariable",
          "event": "incomingMessage"
        },
        {
          "event": "incomingCall"
        },
        {
          "event": "incomingConversationMessage"
        },
        {
          "event": "incomingRequest"
        },
        {
          "event": "incomingParent"
        }
      ],
      "properties": {
        "offset": {
          "x": -70,
          "y": -860
        }
      }
    },
    {
      "name": "SetUtteranceVariable",
      "type": "set-variables",
      "transitions": [
        {
          "next": "http_get_session",
          "event": "next"
        }
      ],
      "properties": {
        "variables": [
          {
            "value": "{{trigger.message.Body}}",
            "key": "utterance"
          },
          {
            "value": "{{trigger.message.From}}",
            "key": "From"
          },
          {
            "value": "{{trigger.call.To}}",
            "key": "To"
          }
        ],
        "offset": {
          "x": -30,
          "y": -620
        }
      }
    },
    {
      "name": "ResetUtteranceVariable",
      "type": "set-variables",
      "transitions": [
        {
          "next": "Dialogflow",
          "event": "next"
        }
      ],
      "properties": {
        "variables": [
          {
            "value": "{{widgets.SendDialogflowAnswerAndWaitForReply.inbound.Body}}",
            "key": "utterance"
          }
        ],
        "offset": {
          "x": 110,
          "y": -200
        }
      }
    },
    {
      "name": "send_message_virtual_agent_error",
      "type": "send-message",
      "transitions": [
        {
          "event": "sent"
        },
        {
          "event": "failed"
        }
      ],
      "properties": {
        "offset": {
          "x": 1430,
          "y": 240
        },
        "service": "{{trigger.message.InstanceSid}}",
        "channel": "{{trigger.message.ChannelSid}}",
        "from": "{{flow.channel.address}}",
        "to": "{{contact.channel.address}}",
        "body": "Sorry, couldn't connect to our backend systems. Call us at {{trigger.call.To}}  or visit our website at Dynamic Value."
      }
    },
    {
      "name": "http_get_session",
      "type": "make-http-request",
      "transitions": [
        {
          "next": "Dialogflow",
          "event": "success"
        },
        {
          "next": "send_message_session_error",
          "event": "failed"
        }
      ],
      "properties": {
        "offset": {
          "x": 890,
          "y": -560
        },
        "method": "POST",
        "content_type": "application/json;charset=utf-8",
        "body": "{\"from\":\"{{trigger.message.From}}\",\"to\":\"{{trigger.message.To}}\",\"fulfillmentInfo\":\"Twilio\"}",
        "url": "https://us-east1-airia-voximplant.cloudfunctions.net/get-session"
      }
    },
    {
      "name": "send_message_session_error",
      "type": "send-message",
      "transitions": [
        {
          "event": "sent"
        },
        {
          "event": "failed"
        }
      ],
      "properties": {
        "offset": {
          "x": 1490,
          "y": -250
        },
        "service": "{{trigger.message.InstanceSid}}",
        "channel": "{{trigger.message.ChannelSid}}",
        "from": "{{flow.channel.address}}",
        "to": "{{contact.channel.address}}",
        "body": "Sorry, we are not able to create a session for you on the call. please send a message to {{trigger.call.To}}  or reach our website dynamic value."
      }
    },
    {
      "name": "Dialogflow",
      "type": "make-http-request",
      "transitions": [
        {
          "next": "SendDialogflowAnswerAndWaitForReply",
          "event": "success"
        },
        {
          "next": "send_message_virtual_agent_error",
          "event": "failed"
        }
      ],
      "properties": {
        "offset": {
          "x": 840,
          "y": -220
        },
        "method": "POST",
        "content_type": "application/json;charset=utf-8",
        "body": "{\"utterance\":\"{{flow.variables.utterance}}\",\"caller_session\":\"{{widgets.http_get_session.parsed.caller_session}}\",\"caller_id\":\"{{widgets.http_get_session.parsed.caller_id}}\",\"called_number\":\"{{widgets.http_get_session.parsed.called_number}}\",\"phonenumber_type\":\"{{widgets.http_get_session.parsed.phonenumber_type}}\"}",
        "url": "https://us-east1-airia-voximplant.cloudfunctions.net/cx-api"
      }
    },
    {
      "name": "SendDialogflowAnswerAndWaitForReply",
      "type": "send-and-wait-for-reply",
      "transitions": [
        {
          "next": "ResetUtteranceVariable",
          "event": "incomingMessage"
        },
        {
          "event": "timeout"
        },
        {
          "event": "deliveryFailure"
        }
      ],
      "properties": {
        "offset": {
          "x": 800,
          "y": 220
        },
        "service": "{{trigger.message.InstanceSid}}",
        "channel": "{{trigger.message.ChannelSid}}",
        "from": "{{flow.channel.address}}",
        "body": "{{widgets.Dialogflow.parsed. \nresponse_message}}",
        "timeout": "3600"
      }
    }
  ],
  "initial_state": "Trigger",
  "flags": {
    "allow_concurrent_calls": true
  }
}