Appearance
User Input Timeout Event
Sent when no user speech is detected within the configured timeout period after the assistant finishes speaking.
Event Structure
json
{
"type": "user_input_timeout",
"session": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"account_id": "account-123",
"phone_number": "+1234567890",
"direction": "inbound",
"from_phone_number": "+9876543210",
"to_phone_number": "+1234567890"
}
}When Triggered
This event is sent when:
- A
speakaction includes auser_input_timeout_secondsfield - The assistant finishes speaking (
assistant_speech_endedevent fires) - The specified timeout period elapses without any user speech detected
Response
You can respond with any action:
json
{
"type": "speak",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"text": "I didn't hear anything. Let me repeat the question."
}Use Cases
Retry Question
javascript
app.post('/webhook', (req, res) => {
const event = req.body;
if (event.type === 'user_input_timeout') {
return res.json({
type: 'speak',
session_id: event.session.id,
text: 'Are you still there? Please say yes or no.',
user_input_timeout_seconds: 5
});
}
});Escalate to Human
javascript
app.post('/webhook', (req, res) => {
const event = req.body;
if (event.type === 'user_input_timeout') {
return res.json({
type: 'speak',
session_id: event.session.id,
text: 'Let me transfer you to a human agent.',
// Follow with transfer action
});
}
});Hangup After Multiple Timeouts
javascript
const timeoutCounts = new Map();
app.post('/webhook', (req, res) => {
const event = req.body;
if (event.type === 'user_input_timeout') {
const sessionId = event.session.id;
const count = (timeoutCounts.get(sessionId) || 0) + 1;
timeoutCounts.set(sessionId, count);
if (count >= 3) {
return res.json({
type: 'hangup',
session_id: sessionId
});
}
return res.json({
type: 'speak',
session_id: sessionId,
text: `I didn't hear anything. Please respond. Attempt ${count} of 3.`,
user_input_timeout_seconds: 5
});
}
});Configuration
The timeout is configured in the speak action:
json
{
"type": "speak",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"text": "What is your account number?",
"user_input_timeout_seconds": 5
}See Speak Action for details.
Behavior
- Timer starts: When
assistant_speech_endedevent fires - Timer cleared: When any user speech is detected (STT events)
- Event sent: When timeout period elapses without speech
- New speak action: Clears any existing timeout and sets a new one (if specified)
Examples
Python
python
@app.route('/webhook', methods=['POST'])
def webhook():
event = request.json
if event['type'] == 'user_input_timeout':
return jsonify({
'type': 'speak',
'session_id': event['session']['id'],
'text': 'I didn\'t hear you. Please try again.'
})Go
go
if event["type"] == "user_input_timeout" {
action := map[string]interface{}{
"type": "speak",
"session_id": session["id"],
"text": "I didn't hear you. Please try again.",
}
json.NewEncoder(w).Encode(action)
}Ruby
ruby
post '/webhook' do
event = JSON.parse(request.body.read)
if event['type'] == 'user_input_timeout'
content_type :json
{
type: 'speak',
session_id: event['session']['id'],
text: 'I didn\'t hear you. Please try again.'
}.to_json
end
endBest Practices
- Set reasonable timeouts - 5-10 seconds is typical for most interactions
- Provide feedback - Let users know why they're being prompted again
- Limit retries - After 2-3 timeouts, consider escalating or hanging up
- Use context - Different questions may need different timeout durations
- Handle gracefully - Don't frustrate users with immediate hangups
Related
- Speak Action - Configure timeout
- Assistant Speech Ended - When timer starts
- User Speak - Clears timeout