You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Twilio Node.js API实现机器人外呼TTS转接座席?

Got it, let's walk through how to add the agent transfer logic to your existing Twilio Node.js outbound TTS call flow. You mentioned you're already using a wait-free conference for the outbound call, so we'll build directly on that foundation.

Solution: Adding Agent Transfer to Your Twilio Outbound TTS Bot

Core Flow Recap

We’ll extend your current setup to:

  1. Keep the customer in the wait-free conference while the bot plays TTS appointment details
  2. Prompt the customer to press a key if they want to speak with an agent
  3. Route the customer to an agent (direct number or call center queue) when they confirm

Step 1: Update Outbound Call Initiation

First, make sure your initial call creation points to a TwiML endpoint that handles both the conference join and bot interaction. Here’s the Node.js SDK code for initiating the call:

const twilio = require('twilio');
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

// Launch outbound call and send customer to your TwiML handler
client.calls.create({
  to: '+1234567890', // Customer's phone number
  from: '+1098765432', // Your Twilio phone number
  url: 'https://your-server.com/handle-conference-call', // Your TwiML endpoint
  method: 'POST'
})
.then(call => console.log(`Call started with SID: ${call.sid}`))
.catch(err => console.error('Call initiation failed:', err));

Step 2: Build the TwiML Handler for Bot & Transfer Logic

We’ll use an Express server here (works similarly in Twilio Functions) to handle the conference, TTS prompt, keypress gathering, and agent transfer.

const express = require('express');
const VoiceResponse = require('twilio').twiml.VoiceResponse;
const app = express();
app.use(express.urlencoded({ extended: true }));

// Endpoint to join customer to conference and play bot message
app.post('/handle-conference-call', (req, res) => {
  const twiml = new VoiceResponse();

  // Join customer to a wait-free conference (no hold delay)
  const conference = twiml.conference({
    beep: false,
    startConferenceOnEnter: true,
    endConferenceOnExit: true,
    waitUrl: 'http://twimlets.com/holdmusic?Bucket=com.twilio.music.silence' // No pre-bot audio
  });
  conference.sid('YOUR_CONFERENCE_SID'); // Let Twilio auto-generate if you don't need a fixed SID

  // Play TTS appointment details and ask for transfer confirmation
  const gather = twiml.gather({
    numDigits: 1,
    action: '/handle-transfer-choice',
    method: 'POST',
    timeout: 10
  });
  gather.say({ voice: 'Polly.Joanna' }, 
    'Hello, this is your appointment reminder for your visit on October 15th at 2 PM. Would you like to speak with an agent to reschedule or ask questions? Press 1 to connect to an agent now.'
  );

  // If no input, repeat the prompt once then hang up
  twiml.redirect('/handle-conference-call');

  res.type('text/xml');
  res.send(twiml.toString());
});

// Handle customer's keypress choice
app.post('/handle-transfer-choice', (req, res) => {
  const twiml = new VoiceResponse();
  const selectedDigit = req.body.Digits;

  if (selectedDigit === '1') {
    // Option 1: Transfer to a direct agent phone number
    twiml.dial({ callerId: '+1098765432' }, '+1112223333'); // Replace with agent's number

    // Option 2: Transfer to a Twilio TaskRouter queue (for call centers)
    // const queue = twiml.enqueue({
    //   workflowSid: 'YOUR_TASKROUTER_WORKFLOW_SID'
    // });
    // queue.task('{"task_type": "customer_appointment_inquiry"}');
  } else {
    twiml.say({ voice: 'Polly.Joanna' }, 'Thank you for your time. Have a wonderful day!');
    twiml.hangup();
  }

  res.type('text/xml');
  res.send(twiml.toString());
});

app.listen(3000, () => console.log('Call handler server running on port 3000'));

Key Implementation Tips

  • Conference Cleanup: The endConferenceOnExit parameter ensures the conference closes automatically when the customer is transferred or hangs up, preventing lingering empty conferences.
  • Input Fallback: Adjust the timeout value in gather to control how long the bot waits for a keypress. Add a max retry count if you want to avoid looping indefinitely.
  • Transfer Flexibility: Choose direct dial for small teams, or TaskRouter if you need advanced routing (e.g., skill-based agent assignment, queue hold music).

内容的提问来源于stack exchange,提问作者Srini Narayanan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:18:37