Using Request Interceptors with Embedded Chat
Overview
Request interceptors allow you to customize API requests made by the embedded JavaScript chat widget at runtime. This powerful feature enables you to inject dynamic headers and body parameters based on your application's current state, user context, or tool configuration requirements.
When to Use Request Interceptors
Request interceptors are ideal for scenarios where you need to:
- Authentication & Authorization: Pass dynamic user tokens, session IDs, or custom authentication headers
- Tool Configuration: Provide tool-specific parameters like company IDs or data filters
- Contextual Data: Include user preferences, application state, or environmental information
- Dynamic Content: Add context files or modify memory settings based on user permissions
- Tracking & Analytics: Add request metadata for monitoring and debugging purposes
Basic Implementation
To use request interceptors, add the requestInterceptor function to your widget initialization:
window.WabeeChat.init({
target: '#chat-container',
apiKey: 'YOUR_API_KEY',
agentId: 'YOUR_AGENT_ID',
agentUrl: 'https://your-agent-url.com',
sseUrl: 'https://your-sse-url.com',
fileServiceUrl: 'https://your-file-service-url.com',
// Request interceptor function
requestInterceptor: (config) => {
// Modify config.headers and config.body as needed
return config;
}
});
Configuration Object
The interceptor function receives a configuration object with:
| Property | Type | Description |
|---|---|---|
headers |
Record<string, string> |
HTTP headers (optional) |
body |
Record<string, unknown> |
Request body data (optional) |
message |
string |
User's message |
Customizing Request Headers
Request interceptors allow you to add or modify HTTP headers sent with each request. This is useful for authentication, session management, tracking, and passing custom metadata.
Session Management Example
You can manage chat sessions by setting the session-id header with your own UUID:
// Import a UUID library or use your own UUID generator
import { v4 as uuidv4 } from 'uuid';
// Generate a session ID when user starts chatting
const userSessionId = uuidv4(); // e.g., "550e8400-e29b-41d4-a716-446655440000"
window.WabeeChat.init({
target: '#chat-container',
apiKey: 'YOUR_API_KEY',
agentId: 'YOUR_AGENT_ID',
agentUrl: 'https://your-agent-url.com',
sseUrl: 'https://your-sse-url.com',
fileServiceUrl: 'https://your-file-service-url.com',
requestInterceptor: (config) => {
// Set the session-id header to track conversations
config.headers['session-id'] = userSessionId;
return config;
}
});
This allows you to: - Track conversation continuity across page refreshes - Associate chat sessions with user accounts in your system - Implement custom session management logic - Debug and monitor specific user sessions
Request Tracking Example
Add a unique request ID to each message for debugging and monitoring:
// Simple UUID generator function
function generateRequestId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2);
}
requestInterceptor: (config) => {
// Add a unique request ID for tracking and debugging
config.headers['request-id'] = generateRequestId();
return config;
}
Combining Session and Request Tracking
Use both headers together for comprehensive tracking:
import { v4 as uuidv4 } from 'uuid';
// Generate session ID once when user starts chatting
const sessionId = uuidv4();
// Simple request ID generator
function generateRequestId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2);
}
window.WabeeChat.init({
target: '#chat-container',
apiKey: 'YOUR_API_KEY',
agentId: 'YOUR_AGENT_ID',
agentUrl: 'https://your-agent-url.com',
sseUrl: 'https://your-sse-url.com',
fileServiceUrl: 'https://your-file-service-url.com',
requestInterceptor: (config) => {
// Track the conversation session
config.headers['session-id'] = sessionId;
// Track each individual request
config.headers['request-id'] = generateRequestId();
return config;
}
});
Supported Headers
| Header | Use Case |
|---|---|
session-id |
Track conversation sessions across requests |
request-id |
Trace individual requests for debugging |
Using Data Filter Hints
One of the most powerful uses of request interceptors is to dynamically apply data filter hints that control how your agent's tools access and filter data:
requestInterceptor: (config) => {
const user = getCurrentUser();
const company = getCompany();
// Configure tools with dynamic filters for data access control
config.body.data_filter_hints = [
{
tool_name: "CustomerDataTool",
filter_type: "equals",
filter_key: "company_id",
filter_value: company.id
},
{
tool_name: "CustomerDataTool",
filter_type: "equals",
filter_key: "user_department",
filter_value: user.department
}
];
return config;
}
Available Filter Types
| Filter Type | Description | Example Use Case |
|---|---|---|
equals |
Exact match | company_id = "123" |
gt |
Greater than | date > "2024-01-01" |
lt |
Less than | price < 100 |
gte |
Greater than or equal | score >= 85 |
lte |
Less than or equal | age <= 65 |
like |
Pattern matching | name LIKE "%smith%" |
Role-Based Data Access
Implement different data access levels based on user permissions:
requestInterceptor: (config) => {
const user = getCurrentUser();
const company = getCompany();
// Base filter for company isolation
const baseFilters = [
{
tool_name: "CustomerDataTool",
filter_type: "equals",
filter_key: "company_id",
filter_value: company.id
}
];
// Add role-specific filters
if (user.role === 'admin') {
// Admins see all company data
config.body.data_filter_hints = baseFilters;
} else if (user.role === 'manager') {
// Managers see their department's data
config.body.data_filter_hints = [
...baseFilters,
{
tool_name: "CustomerDataTool",
filter_type: "equals",
filter_key: "department",
filter_value: user.department
}
];
} else {
// Regular users see only their assigned data
config.body.data_filter_hints = [
...baseFilters,
{
tool_name: "CustomerDataTool",
filter_type: "equals",
filter_key: "assigned_user_id",
filter_value: user.id
}
];
}
return config;
}
Additional Configuration Options
Context Files and Memory
requestInterceptor: (config) => {
// Include relevant context files
config.body.context_files = [
"inputs/chat-files/user123/project-requirements.pdf",
"inputs/chat-files/user123/meeting-notes.txt"
];
// Enable memory retention for premium users
const user = getCurrentUser();
config.body.auto_memory_retain = user.plan === 'premium';
return config;
}
Message-Based Logic
Customize behavior based on the user's message content:
requestInterceptor: (config) => {
const message = config.message.toLowerCase();
if (message.includes('customer') || message.includes('client')) {
config.body.context_files = [
"inputs/customer-data/current-customers.csv"
];
config.body.data_filter_hints = [
{
tool_name: "CustomerDatabase",
filter_type: "equals",
filter_key: "status",
filter_value: "active"
}
];
}
return config;
}
Async Operations
Request interceptors support asynchronous operations:
requestInterceptor: async (config) => {
try {
// Fetch dynamic data
const userProfile = await fetchUserProfile();
const permissions = await fetchUserPermissions();
config.body.data_filter_hints = [
{
tool_name: "UserDataTool",
filter_type: "equals",
filter_key: "user_id",
filter_value: userProfile.id
}
];
return config;
} catch (error) {
console.warn('Failed to fetch user data for request interceptor:', error);
return config; // Return original config if async operations fail
}
}
Complete Example
This comprehensive example demonstrates how to use both headers and body parameters together:
import { v4 as uuidv4 } from 'uuid';
// Generate session ID when user starts chatting
const sessionId = uuidv4();
// Simple request ID generator
function generateRequestId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2);
}
window.WabeeChat.init({
target: '#chat-container',
apiKey: 'wabee_api_key_example_123',
agentId: 'agent-uuid-here',
agentUrl: 'https://api.wabee.ai',
sseUrl: 'https://sse.wabee.ai',
fileServiceUrl: 'https://files.wabee.ai',
requestInterceptor: (config) => {
const user = getCurrentUser();
const company = getCompany();
// Add custom headers for session and request tracking
config.headers['session-id'] = sessionId;
config.headers['request-id'] = generateRequestId();
// Configure data filter hints for multi-tenant data access
config.body.data_filter_hints = [
{
tool_name: "BubbleDataTool",
filter_type: "equals",
filter_key: "company_id",
filter_value: company.id
},
{
tool_name: "BubbleDataTool",
filter_type: "equals",
filter_key: "access_level",
filter_value: user.accessLevel
}
];
// Enable memory retention for premium users
config.body.auto_memory_retain = user.plan === 'premium';
// Add context files if user has uploaded relevant documents
const userFiles = getUserContextFiles();
if (userFiles.length > 0) {
config.body.context_files = userFiles;
}
return config;
}
});
Error Handling and Security
Built-in Error Handling
The widget includes automatic error handling: - If the interceptor throws an error, the original request configuration is used - Errors are logged to the console with warning messages - Chat functionality continues working normally
Security Best Practices
- Sensitive Data: Avoid logging sensitive information in the interceptor
- Input Validation: Validate user input before including it in requests
- Token Management: Ensure tokens and API keys are securely stored and regularly refreshed
- Access Control: Implement proper access control checks before setting filter values
requestInterceptor: (config) => {
try {
// Your custom logic here
config.body.data_filter_hints = processDataFilters();
return config;
} catch (error) {
console.warn('Custom interceptor logic failed:', error);
return config; // Return config as-is if errors occur
}
}
Troubleshooting
Common Issues
- Interceptor Not Called: Ensure the function is properly defined in the
initoptions - Headers Not Applied: Verify header names are valid HTTP header names (avoid spaces and special characters)
- Filter Hints Ignored: Check that tool names match exactly and filter types are valid
- Body Parameters Ignored: Ensure body parameter names match the expected API schema
- Authentication Errors: Verify that custom headers don't conflict with existing authentication headers
Debugging
Enable browser developer tools to monitor: - Network requests to see applied headers and body data - Console warnings for interceptor errors - Request/response timing and status codes
function generateRequestId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2);
}
requestInterceptor: (config) => {
console.log('Original config:', config);
// Your modifications
config.headers['request-id'] = generateRequestId();
config.body.data_filter_hints = [
{
tool_name: "DebugTool",
filter_type: "equals",
filter_key: "debug_mode",
filter_value: "enabled"
}
];
console.log('Modified headers:', config.headers);
console.log('Modified body:', config.body);
return config;
}
Next Steps
- Learn more about data filter hints for API integration
- Explore the embedding chat widget tutorial for basic setup
- Review the API documentation for complete endpoint reference