Your First Chatbot¶
Build your first complete chatbot using lex-helper with detailed explanations of each component. This comprehensive tutorial will teach you best practices for structuring, testing, and deploying a production-ready chatbot.
What You'll Build¶
By the end of this tutorial, you'll have created a Personal Assistant Bot that can:
- ✅ Handle multiple intents (greetings, weather, reminders, help)
- ✅ Manage complex session state and user preferences
- ✅ Provide error handling and fallback responses
- ✅ Support different response channels (SMS, web, voice)
- ✅ Include comprehensive testing
- ✅ Follow production-ready patterns
Estimated time: 30-45 minutes
Learning Objectives¶
By completing this tutorial, you'll understand:
- Project Structure - How to organize a lex-helper project for maintainability
- Intent Patterns - Common patterns for handling different types of intents
- Session Management - Advanced session attribute usage and persistence
- Error Handling - Graceful error handling and user experience
- Testing Strategies - How to test your chatbot logic
- Channel Awareness - Adapting responses for different channels
Prerequisites¶
- ✅ Completed Quick Start Guide
- ✅ Basic understanding of Amazon Lex concepts (intents, slots, fulfillment)
- ✅ Familiarity with Python classes and type hints
Project Setup¶
1. Create Project Structure¶
Let's create a well-organized project structure:
mkdir personal-assistant-bot
cd personal-assistant-bot
# Create directory structure
mkdir intents utils tests
touch handler.py session_attributes.py
touch intents/__init__.py utils/__init__.py tests/__init__.py
# Create configuration files
touch requirements.txt .env
Your structure should look like:
personal-assistant-bot/
├── intents/
│ └── __init__.py
├── utils/
│ └── __init__.py
├── tests/
│ └── __init__.py
├── handler.py
├── session_attributes.py
├── requirements.txt
└── .env
2. Define Requirements¶
Install dependencies:
Step 1: Advanced Session Attributes¶
Create comprehensive session attributes that demonstrate real-world usage:
# session_attributes.py
from datetime import datetime
from typing import List, Optional
from pydantic import ConfigDict, Field
from lex_helper import SessionAttributes
class UserPreferences(SessionAttributes):
"""User preferences sub-model."""
preferred_name: str = Field(default="", description="User's preferred name")
timezone: str = Field(default="UTC", description="User's timezone")
notification_enabled: bool = Field(default=True, description="Whether notifications are enabled")
class PersonalAssistantSessionAttributes(SessionAttributes):
"""
Comprehensive session attributes for a personal assistant bot.
This demonstrates advanced session management patterns including:
- Nested models for organization
- Different data types (strings, integers, booleans, lists, dates)
- Default values and validation
- Clear documentation
"""
model_config = ConfigDict(extra="allow")
# User Information
user_preferences: UserPreferences = Field(
default_factory=UserPreferences,
description="User's personal preferences"
)
# Conversation State
current_flow: str = Field(
default="",
description="Current conversation flow (e.g., 'weather_inquiry', 'reminder_setup')"
)
last_intent: str = Field(
default="",
description="The last successfully handled intent"
)
conversation_count: int = Field(
default=0,
description="Number of interactions in this session"
)
# Context and Memory
mentioned_topics: List[str] = Field(
default_factory=list,
description="Topics mentioned in this conversation"
)
pending_reminders: List[str] = Field(
default_factory=list,
description="Reminders waiting to be set"
)
# Error Handling
consecutive_errors: int = Field(
default=0,
description="Number of consecutive errors for fallback logic"
)
last_error_intent: str = Field(
default="",
description="Intent that last caused an error"
)
# Timestamps
session_start_time: Optional[str] = Field(
default=None,
description="When this session started (ISO format)"
)
last_activity_time: Optional[str] = Field(
default=None,
description="Last activity timestamp (ISO format)"
)
def update_activity(self) -> None:
"""Update the last activity timestamp."""
self.last_activity_time = datetime.utcnow().isoformat()
if not self.session_start_time:
self.session_start_time = self.last_activity_time
def add_topic(self, topic: str) -> None:
"""Add a topic to the mentioned topics list."""
if topic and topic not in self.mentioned_topics:
self.mentioned_topics.append(topic)
def reset_error_count(self) -> None:
"""Reset the consecutive error count."""
self.consecutive_errors = 0
self.last_error_intent = ""
def increment_error_count(self, intent_name: str) -> None:
"""Increment the error count for an intent."""
self.consecutive_errors += 1
self.last_error_intent = intent_name
Step 2: Utility Functions¶
Create utility functions to support your intents:
# utils/helpers.py
from typing import Optional
from datetime import datetime
import re
def extract_name_from_input(user_input: str) -> Optional[str]:
"""
Extract a name from user input using common patterns.
Examples:
- "My name is John" -> "John"
- "I'm Sarah" -> "Sarah"
- "Call me Mike" -> "Mike"
"""
patterns = [
r"my name is (\w+)",
r"i'm (\w+)",
r"call me (\w+)",
r"i am (\w+)",
]
user_input_lower = user_input.lower()
for pattern in patterns:
match = re.search(pattern, user_input_lower)
if match:
return match.group(1).title()
return None
def format_time_greeting() -> str:
"""Return a time-appropriate greeting."""
hour = datetime.now().hour
if 5 <= hour < 12:
return "Good morning"
elif 12 <= hour < 17:
return "Good afternoon"
elif 17 <= hour < 22:
return "Good evening"
else:
return "Good night"
def is_business_hours() -> bool:
"""Check if it's currently business hours (9 AM - 5 PM)."""
hour = datetime.now().hour
return 9 <= hour < 17
def format_list_response(items: list, conjunction: str = "and") -> str:
"""
Format a list into a natural language string.
Examples:
- ["apple"] -> "apple"
- ["apple", "banana"] -> "apple and banana"
- ["apple", "banana", "cherry"] -> "apple, banana, and cherry"
"""
if not items:
return ""
elif len(items) == 1:
return str(items[0])
elif len(items) == 2:
return f"{items[0]} {conjunction} {items[1]}"
else:
return f"{', '.join(items[:-1])}, {conjunction} {items[-1]}"
Step 3: Intent Handlers¶
Now let's create comprehensive intent handlers that demonstrate different patterns:
Welcome Intent¶
# intents/welcome_intent.py
from lex_helper import LexRequest, LexResponse, LexPlainText, dialog
from session_attributes import PersonalAssistantSessionAttributes
from utils.helpers import format_time_greeting, extract_name_from_input
def handler(lex_request: LexRequest[PersonalAssistantSessionAttributes]) -> LexResponse[PersonalAssistantSessionAttributes]:
"""
Handle welcome/greeting intents.
This intent demonstrates:
- Session state initialization
- Personalized responses based on session history
- Context-aware greetings
"""
session_attrs = lex_request.sessionState.sessionAttributes
session_attrs.update_activity()
session_attrs.conversation_count += 1
session_attrs.current_flow = "greeting"
session_attrs.last_intent = "WelcomeIntent"
session_attrs.add_topic("greeting")
# Try to extract name from user input
user_input = lex_request.inputTranscript or ""
extracted_name = extract_name_from_input(user_input)
if extracted_name and not session_attrs.user_preferences.preferred_name:
session_attrs.user_preferences.preferred_name = extracted_name
# Create personalized greeting
time_greeting = format_time_greeting()
if session_attrs.user_preferences.preferred_name:
if session_attrs.conversation_count == 1:
message = f"{time_greeting}, {session_attrs.user_preferences.preferred_name}! Welcome back to your personal assistant."
else:
message = f"Hello again, {session_attrs.user_preferences.preferred_name}!"
else:
message = f"{time_greeting}! I'm your personal assistant. What's your name?"
# Add helpful context
if session_attrs.conversation_count == 1:
message += " I can help you with weather, reminders, and general questions. What would you like to do?"
return dialog.close(
messages=[LexPlainText(content=message)],
lex_request=lex_request,
fulfillment_state="Fulfilled"
)
Weather Intent¶
# intents/weather_intent.py
from lex_helper import LexRequest, LexResponse, LexPlainText, dialog
from session_attributes import PersonalAssistantSessionAttributes
def handler(lex_request: LexRequest[PersonalAssistantSessionAttributes]) -> LexResponse[PersonalAssistantSessionAttributes]:
"""
Handle weather inquiry intents.
This intent demonstrates:
- Slot validation and elicitation
- Multi-turn conversations
- Error handling for missing information
"""
session_attrs = lex_request.sessionState.sessionAttributes
session_attrs.update_activity()
session_attrs.current_flow = "weather_inquiry"
session_attrs.last_intent = "WeatherIntent"
session_attrs.add_topic("weather")
# Get the city slot
city_slot = dialog.get_slot("City", lex_request.sessionState.intent)
if not city_slot or not city_slot.value:
# Elicit the city if not provided
return dialog.elicit_slot(
slot_to_elicit="City",
messages=[LexPlainText(content="Which city would you like to know the weather for?")],
lex_request=lex_request
)
city = city_slot.value.interpretedValue
# In a real implementation, you would call a weather API here
# For this tutorial, we'll simulate a response
weather_response = f"The weather in {city} is currently sunny with a temperature of 72°F. Perfect day to go outside!"
# Add personalized touch
if session_attrs.user_preferences.preferred_name:
weather_response = f"Here you go, {session_attrs.user_preferences.preferred_name}! " + weather_response
return dialog.close(
messages=[LexPlainText(content=weather_response)],
lex_request=lex_request,
fulfillment_state="Fulfilled"
)
Reminder Intent¶
# intents/reminder_intent.py
from lex_helper import LexRequest, LexResponse, LexPlainText, dialog
from session_attributes import PersonalAssistantSessionAttributes
def handler(lex_request: LexRequest[PersonalAssistantSessionAttributes]) -> LexResponse[PersonalAssistantSessionAttributes]:
"""
Handle reminder creation intents.
This intent demonstrates:
- Complex slot management
- Session state persistence
- Multi-step workflows
"""
session_attrs = lex_request.sessionState.sessionAttributes
session_attrs.update_activity()
session_attrs.current_flow = "reminder_setup"
session_attrs.last_intent = "ReminderIntent"
session_attrs.add_topic("reminders")
# Get required slots
reminder_text_slot = dialog.get_slot("ReminderText", lex_request.sessionState.intent)
reminder_time_slot = dialog.get_slot("ReminderTime", lex_request.sessionState.intent)
# Elicit reminder text if missing
if not reminder_text_slot or not reminder_text_slot.value:
return dialog.elicit_slot(
slot_to_elicit="ReminderText",
messages=[LexPlainText(content="What would you like me to remind you about?")],
lex_request=lex_request
)
# Elicit reminder time if missing
if not reminder_time_slot or not reminder_time_slot.value:
return dialog.elicit_slot(
slot_to_elicit="ReminderTime",
messages=[LexPlainText(content="When would you like to be reminded?")],
lex_request=lex_request
)
reminder_text = reminder_text_slot.value.interpretedValue
reminder_time = reminder_time_slot.value.interpretedValue
# Store the reminder (in a real app, you'd save to a database)
reminder = f"{reminder_text} at {reminder_time}"
session_attrs.pending_reminders.append(reminder)
# Create confirmation message
message = f"Perfect! I've set a reminder for '{reminder_text}' at {reminder_time}."
if session_attrs.user_preferences.preferred_name:
message += f" I'll make sure to remind you, {session_attrs.user_preferences.preferred_name}!"
return dialog.close(
messages=[LexPlainText(content=message)],
lex_request=lex_request,
fulfillment_state="Fulfilled"
)
Help Intent¶
# intents/help_intent.py
from lex_helper import LexRequest, LexResponse, LexPlainText, dialog
from session_attributes import PersonalAssistantSessionAttributes
from utils.helpers import format_list_response
def handler(lex_request: LexRequest[PersonalAssistantSessionAttributes]) -> LexResponse[PersonalAssistantSessionAttributes]:
"""
Handle help requests.
This intent demonstrates:
- Context-aware help based on conversation history
- Dynamic response generation
- User guidance and onboarding
"""
session_attrs = lex_request.sessionState.sessionAttributes
session_attrs.update_activity()
session_attrs.current_flow = "help"
session_attrs.last_intent = "HelpIntent"
session_attrs.add_topic("help")
# Base capabilities
capabilities = [
"check the weather for any city",
"set reminders for you",
"have conversations and answer questions",
"remember your preferences"
]
# Create personalized help message
if session_attrs.user_preferences.preferred_name:
greeting = f"Hi {session_attrs.user_preferences.preferred_name}! "
else:
greeting = "Hi there! "
message = greeting + f"I can help you {format_list_response(capabilities)}."
# Add context-specific help
if session_attrs.mentioned_topics:
message += f"\n\nWe've talked about {format_list_response(session_attrs.mentioned_topics)} so far."
if session_attrs.pending_reminders:
reminder_count = len(session_attrs.pending_reminders)
message += f"\n\nYou have {reminder_count} pending reminder{'s' if reminder_count != 1 else ''}."
message += "\n\nWhat would you like to do?"
return dialog.close(
messages=[LexPlainText(content=message)],
lex_request=lex_request,
fulfillment_state="Fulfilled"
)
Fallback Intent¶
# intents/fallback_intent.py
from lex_helper import LexRequest, LexResponse, LexPlainText, dialog
from session_attributes import PersonalAssistantSessionAttributes
def handler(lex_request: LexRequest[PersonalAssistantSessionAttributes]) -> LexResponse[PersonalAssistantSessionAttributes]:
"""
Handle fallback when no intent matches or errors occur.
This intent demonstrates:
- Error tracking and recovery
- Escalating help based on error frequency
- Graceful degradation of user experience
"""
session_attrs = lex_request.sessionState.sessionAttributes
session_attrs.update_activity()
session_attrs.increment_error_count("FallbackIntent")
session_attrs.current_flow = "fallback"
session_attrs.last_intent = "FallbackIntent"
# Escalate help based on consecutive errors
if session_attrs.consecutive_errors == 1:
message = "I'm not sure I understood that. Could you try rephrasing your request?"
elif session_attrs.consecutive_errors == 2:
message = "I'm still having trouble understanding. I can help with weather, reminders, or general questions. What would you like to do?"
elif session_attrs.consecutive_errors >= 3:
message = "I apologize for the confusion. Let me help you get back on track. Here's what I can do:\n\n"
message += "• Say 'weather in [city]' to get weather information\n"
message += "• Say 'remind me to [task] at [time]' to set reminders\n"
message += "• Say 'help' for more options\n\n"
message += "What would you like to try?"
# Reset error count after providing comprehensive help
session_attrs.reset_error_count()
else:
message = "I didn't catch that. Could you please try again?"
return dialog.close(
messages=[LexPlainText(content=message)],
lex_request=lex_request,
fulfillment_state="Failed"
)
Step 4: Enhanced Main Handler¶
Create a robust main handler with error handling:
# handler.py
import logging
from typing import Any
from lex_helper import Config, LexHelper
from session_attributes import PersonalAssistantSessionAttributes
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def lambda_handler(event: dict[str, Any], context: Any) -> dict[str, Any]:
"""
Enhanced Lambda handler with comprehensive error handling and logging.
This handler demonstrates:
- Proper logging for debugging and monitoring
- Error handling and recovery
- Configuration management
- Performance considerations
"""
try:
# Log the incoming request (be careful with sensitive data in production)
logger.info(f"Processing request for intent: {event.get('sessionState', {}).get('intent', {}).get('name', 'Unknown')}")
# Configure lex-helper
config = Config(
session_attributes=PersonalAssistantSessionAttributes(),
package_name="intents"
)
# Initialize lex-helper
lex_helper = LexHelper(config=config)
# Process the request
response = lex_helper.handler(event, context)
# Log successful processing
logger.info("Request processed successfully")
return response
except Exception as e:
# Log the error
logger.error(f"Error processing request: {str(e)}", exc_info=True)
# Return a graceful error response
return {
"sessionState": {
"dialogAction": {
"type": "Close"
},
"intent": {
"name": event.get('sessionState', {}).get('intent', {}).get('name', 'Unknown'),
"state": "Failed"
}
},
"messages": [
{
"contentType": "PlainText",
"content": "I apologize, but I'm experiencing technical difficulties. Please try again in a moment."
}
]
}
Step 5: Testing Your Chatbot¶
Create comprehensive tests to ensure your chatbot works correctly:
# tests/test_intents.py
import pytest
from unittest.mock import Mock
from lex_helper import LexRequest
from session_attributes import PersonalAssistantSessionAttributes
# Import your intent handlers
from intents.welcome_intent import handler as welcome_handler
from intents.weather_intent import handler as weather_handler
from intents.help_intent import handler as help_handler
class TestWelcomeIntent:
"""Test the welcome intent handler."""
def test_first_time_user(self):
"""Test welcome for a new user."""
# Create mock request
session_attrs = PersonalAssistantSessionAttributes()
lex_request = Mock(spec=LexRequest)
lex_request.sessionState.sessionAttributes = session_attrs
lex_request.inputTranscript = "Hello"
# Call handler
response = welcome_handler(lex_request)
# Verify response
assert response.sessionState.dialogAction.type == "Close"
assert "Good" in response.messages[0].content # Should include time-based greeting
assert session_attrs.conversation_count == 1
assert session_attrs.last_intent == "WelcomeIntent"
def test_returning_user_with_name(self):
"""Test welcome for a returning user with a known name."""
# Create mock request with existing session
session_attrs = PersonalAssistantSessionAttributes()
session_attrs.user_preferences.preferred_name = "Alice"
session_attrs.conversation_count = 0 # Will be incremented to 1
lex_request = Mock(spec=LexRequest)
lex_request.sessionState.sessionAttributes = session_attrs
lex_request.inputTranscript = "Hi there"
# Call handler
response = welcome_handler(lex_request)
# Verify personalized response
assert "Alice" in response.messages[0].content
assert session_attrs.conversation_count == 1
class TestWeatherIntent:
"""Test the weather intent handler."""
def test_weather_with_city(self):
"""Test weather request with city provided."""
# Create mock request with city slot
session_attrs = PersonalAssistantSessionAttributes()
lex_request = Mock(spec=LexRequest)
lex_request.sessionState.sessionAttributes = session_attrs
lex_request.sessionState.intent = Mock()
# Mock the city slot
city_slot = Mock()
city_slot.value.interpretedValue = "Seattle"
# Mock dialog.get_slot to return our city
import intents.weather_intent
original_get_slot = intents.weather_intent.dialog.get_slot
intents.weather_intent.dialog.get_slot = Mock(return_value=city_slot)
try:
# Call handler
response = weather_handler(lex_request)
# Verify response
assert response.sessionState.dialogAction.type == "Close"
assert "Seattle" in response.messages[0].content
assert session_attrs.current_flow == "weather_inquiry"
finally:
# Restore original function
intents.weather_intent.dialog.get_slot = original_get_slot
def test_weather_without_city(self):
"""Test weather request without city - should elicit slot."""
# Create mock request without city slot
session_attrs = PersonalAssistantSessionAttributes()
lex_request = Mock(spec=LexRequest)
lex_request.sessionState.sessionAttributes = session_attrs
lex_request.sessionState.intent = Mock()
# Mock dialog.get_slot to return None (no city provided)
import intents.weather_intent
original_get_slot = intents.weather_intent.dialog.get_slot
intents.weather_intent.dialog.get_slot = Mock(return_value=None)
try:
# Call handler
response = weather_handler(lex_request)
# Verify it elicits the city slot
assert response.sessionState.dialogAction.type == "ElicitSlot"
assert response.sessionState.dialogAction.slotToElicit == "City"
finally:
# Restore original function
intents.weather_intent.dialog.get_slot = original_get_slot
class TestHelpIntent:
"""Test the help intent handler."""
def test_help_with_conversation_history(self):
"""Test help with existing conversation context."""
# Create session with history
session_attrs = PersonalAssistantSessionAttributes()
session_attrs.user_preferences.preferred_name = "Bob"
session_attrs.mentioned_topics = ["weather", "reminders"]
session_attrs.pending_reminders = ["Buy groceries at 5 PM"]
lex_request = Mock(spec=LexRequest)
lex_request.sessionState.sessionAttributes = session_attrs
lex_request.inputTranscript = "help"
# Call handler
response = help_handler(lex_request)
# Verify contextual help
assert "Bob" in response.messages[0].content
assert "weather" in response.messages[0].content
assert "1 pending reminder" in response.messages[0].content
# Run tests
if __name__ == "__main__":
pytest.main([__file__, "-v"])
Run your tests:
Step 6: Local Testing Script¶
Create a script to test your bot locally:
# test_bot_locally.py
import json
from handler import lambda_handler
def create_test_event(intent_name: str, input_text: str, slots: dict = None) -> dict:
"""Create a test Lex event."""
event = {
"sessionState": {
"intent": {
"name": intent_name,
"state": "ReadyForFulfillment",
"slots": slots or {}
},
"sessionAttributes": {}
},
"inputTranscript": input_text,
"bot": {
"name": "PersonalAssistantBot",
"version": "1.0"
}
}
return event
def test_conversation_flow():
"""Test a complete conversation flow."""
print("🤖 Testing Personal Assistant Bot\n")
# Test 1: Welcome
print("Test 1: Welcome Intent")
event = create_test_event("WelcomeIntent", "Hello")
response = lambda_handler(event, None)
print(f"Bot: {response['messages'][0]['content']}\n")
# Test 2: Weather (without city)
print("Test 2: Weather Intent (no city)")
event = create_test_event("WeatherIntent", "What's the weather?")
response = lambda_handler(event, None)
print(f"Bot: {response['messages'][0]['content']}\n")
# Test 3: Weather (with city)
print("Test 3: Weather Intent (with city)")
event = create_test_event("WeatherIntent", "Weather in New York", {
"City": {
"value": {
"interpretedValue": "New York"
}
}
})
response = lambda_handler(event, None)
print(f"Bot: {response['messages'][0]['content']}\n")
# Test 4: Help
print("Test 4: Help Intent")
event = create_test_event("HelpIntent", "help")
response = lambda_handler(event, None)
print(f"Bot: {response['messages'][0]['content']}\n")
# Test 5: Fallback
print("Test 5: Fallback Intent")
event = create_test_event("FallbackIntent", "asdfghjkl")
response = lambda_handler(event, None)
print(f"Bot: {response['messages'][0]['content']}\n")
if __name__ == "__main__":
test_conversation_flow()
Run the local test:
Key Concepts Explained¶
1. Session State Management¶
# Session attributes persist across the conversation
session_attrs.user_preferences.preferred_name = "Alice"
session_attrs.conversation_count += 1
session_attrs.add_topic("weather")
2. Intent Organization¶
Each intent handler follows a consistent pattern: - Update session state - Validate and process slots - Generate appropriate response - Handle errors gracefully
3. Error Handling Strategy¶
# Track consecutive errors for escalating help
session_attrs.increment_error_count("FallbackIntent")
# Provide increasingly helpful responses
if session_attrs.consecutive_errors >= 3:
# Provide comprehensive help and reset counter
pass # Implementation details
4. Type Safety Benefits¶
# Type-safe access to session attributes
user_name: str = session_attrs.user_preferences.preferred_name
count: int = session_attrs.conversation_count
# IDE autocomplete and error detection
# session_attrs.user_preferences. # <- IDE shows available fields
Production Considerations¶
1. Environment Configuration¶
# .env file for local development
AWS_REGION=us-east-1
LOG_LEVEL=INFO
WEATHER_API_KEY=your_api_key_here
2. Logging and Monitoring¶
import logging
logger = logging.getLogger(__name__)
# Log important events
logger.info(f"Processing {intent_name} for user {user_id}")
logger.error(f"Error in {intent_name}: {str(e)}")
3. Security Best Practices¶
- Never log sensitive user data
- Use IAM roles instead of hardcoded credentials
- Validate all user inputs
- Implement rate limiting
4. Performance Optimization¶
- Keep Lambda functions warm
- Minimize cold start time
- Use connection pooling for databases
- Cache frequently accessed data
Next Steps¶
Congratulations! You've built a comprehensive chatbot with lex-helper. Here's what to explore next:
Immediate Enhancements¶
- Message Management - Add internationalization
- Channel Formatting - Optimize for different channels
- Smart Disambiguation - Handle ambiguous input
Advanced Features¶
- Bedrock Integration - Add AI-powered responses
- Testing Strategies - Comprehensive testing approaches
- Production Deployment - Deploy to AWS
Real-World Examples¶
- Airline Bot Tutorial - Complex multi-turn conversations
- Advanced Patterns - Production-ready patterns
- AWS Integrations - Connect with other AWS services
Troubleshooting¶
Common Issues¶
Issue: Intent handler not found
Issue: Session attributes not persisting
# Ensure you're modifying the existing object, not creating new ones
session_attrs = lex_request.sessionState.sessionAttributes # ✅
session_attrs.user_name = "Alice" # ✅
# Don't create new instances
session_attrs = PersonalAssistantSessionAttributes() # ❌
Issue: Slots not being elicited properly
# Make sure slot names match exactly between Lex console and code
dialog.elicit_slot(
slot_to_elicit="City", # Must match Lex console exactly
messages=[LexPlainText(content="Which city?")],
lex_request=lex_request
)
Getting Help¶
- Advanced Troubleshooting - Detailed debugging guide
- Troubleshooting Guide - Get help with common issues
- GitHub Issues - Report bugs or request features
Ready to explore advanced features? Check out the Core Concepts Guide →