Overview
The chat interface is the primary user interaction point in Workshop Cloud Chat. It provides a real-time conversational experience powered by Amazon Bedrock agents, with support for session management, theme customization, and technical diagnostics.
Session Management Automatic session ID generation with persistent conversation context
Theme Toggle Light and dark mode support with smooth transitions
Debug Mode Technical diagnostics for troubleshooting API responses
Message History Persistent message storage with role-based styling
Chat Configuration
The chat interface requires configuration of AWS credentials and Bedrock agent parameters. Configuration is managed through a modal dialog and stored in browser localStorage.
Required Configuration
Access Key ID (required): Your AWS access key
Secret Access Key (required): Your AWS secret key
Session Token (optional): For temporary credentials
Region (required): AWS region where your agent is deployed (e.g., us-east-1)
Agent ID (required): Unique identifier for your Bedrock agent
Agent Alias ID (required): Alias ID for the agent version
Session ID (optional): Auto-generated if not provided
Configuration Storage
All configuration is persisted in localStorage under the key workshop-cloud-chat-config-v1:
const STORAGE_KEY = 'workshop-cloud-chat-config-v1' ;
const state = {
messages: [],
aws: {
accessKeyId: '' ,
secretAccessKey: '' ,
sessionToken: ''
},
bedrock: {
region: '' ,
agentId: '' ,
agentAliasId: '' ,
sessionId: ''
},
// ... other state
};
User Interface
The header displays the application title and provides quick access to configuration:
< header class = "chat-header" >
< div class = "chat-brand" >
< h1 class = "chat-title" > Asistente Bedrock · Chat con Agente (Amazon Bedrock) </ h1 >
</ div >
< button class = "ghost icon-btn" id = "openChatConfig"
aria-label = "Configurar chat y credenciales" >
⚙
</ button >
</ header >
Message Display
Messages are displayed in a scrollable container with role-based styling:
User messages appear on the right with a purple gradient background, while assistant messages appear on the left with a light blue background.
const renderMessages = () => {
el . messages . innerHTML = '' ;
if ( state . messages . length === 0 ) {
// Show empty state
const note = document . createElement ( 'p' );
note . className = 'empty-chat-note' ;
note . textContent = 'Aún no hay mensajes. Escribe tu primera consulta para iniciar el chat.' ;
el . messages . appendChild ( note );
return ;
}
state . messages . forEach (( msg ) => {
const isUser = msg . role === 'user' ;
const roleClass = isUser ? 'user' : 'assistant' ;
// Create message bubble with emoji and text
const emoji = document . createElement ( 'span' );
emoji . textContent = isUser ? '👤' : '🤖' ;
const text = document . createElement ( 'span' );
text . textContent = msg . content ;
// ... styling and DOM manipulation
});
};
Theme Toggle
The application supports light and dark themes with CSS custom properties:
:root {
color-scheme : light ;
--bg : #f4f2ff ;
--surface : #ffffff ;
--primary : #8453d2 ;
/* ... other light theme variables */
}
body [ data-theme = 'dark' ] {
color-scheme : dark ;
--bg : #121524 ;
--surface : #1a1f33 ;
--primary : #9b73f0 ;
/* ... other dark theme variables */
}
Theme selection is managed through a toggle switch:
const applyTheme = () => {
const theme = state . ui . theme === 'dark' ? 'dark' : 'light' ;
document . body . setAttribute ( 'data-theme' , theme );
el . toggleTheme . checked = theme === 'dark' ;
};
Chat API Integration
Sending Messages
Messages are sent to the /api/chat endpoint with full configuration:
// From src/pages/api/chat.ts
export const POST : APIRoute = async ({ request }) => {
const body = await request . json () as ChatRequest ;
// Validate required parameters
if ( ! body . region || ! body . agentId || ! body . agentAliasId ||
! body . accessKeyId || ! body . secretAccessKey ) {
return new Response ( JSON . stringify ({
error: 'Faltan parámetros de configuración del agente Bedrock.'
}), { status: 400 });
}
// Initialize Bedrock client
const client = new BedrockAgentRuntimeClient ({
region: body . region ,
credentials: {
accessKeyId: body . accessKeyId ,
secretAccessKey: body . secretAccessKey ,
sessionToken: body . sessionToken || undefined
}
});
// Extract latest user message
const latestUserMessage = [ ... ( body . messages || [])]
. reverse ()
. find (( item ) => item ?. role === 'user' && item ?. content ?. trim ());
// Generate session ID if not provided
const sessionId = body . sessionId ?. trim () || crypto . randomUUID ();
// Invoke agent
const command = new InvokeAgentCommand ({
agentId: body . agentId ,
agentAliasId: body . agentAliasId ,
sessionId ,
inputText: latestUserMessage . content
});
const response = await client . send ( command );
// ... process streaming response
};
Response Processing
The API processes streaming responses from Bedrock:
const decoder = new TextDecoder ();
let reply = '' ;
if ( response . completion ) {
for await ( const chunkEvent of response . completion ) {
const bytes = chunkEvent . chunk ?. bytes ;
if ( bytes ) {
reply += decoder . decode ( bytes , { stream: true });
}
}
reply += decoder . decode ();
}
const normalizedReply = reply . replace ( / \u0000 / g , '' ). trim ();
return new Response ( JSON . stringify ({
reply: normalizedReply || 'No se recibió texto del agente.' ,
sessionId
}), { status: 200 });
Session Management
Automatic Session Rotation
Sessions are automatically rotated on page load to prevent context mixing:
const rotateChatSessionOnPageLoad = () => {
const hasBedrockConfig = Boolean (
state . bedrock . region &&
state . bedrock . agentId &&
state . bedrock . agentAliasId
);
if ( ! hasBedrockConfig ) return ;
state . bedrock . sessionId = crypto . randomUUID ();
saveConfig ();
};
Session rotation ensures each page load starts a fresh conversation, preventing message history from leaking between sessions.
Debug Mode
Technical Diagnostics
Debug mode displays the raw API response for troubleshooting:
< label class = "chat-debug-toggle" for = "toggleChatDebug" >
< input type = "checkbox" id = "toggleChatDebug" />
Mostrar diagnóstico técnico
</ label >
< details class = "chat-debug" >
< summary >< strong > Diagnóstico de respuesta </ strong ></ summary >
< pre id = "chatDebugPayload" > Sin solicitudes aún. </ pre >
</ details >
Debug visibility is controlled via state:
const applyDebugVisibility = () => {
const debugEnabled = Boolean ( state . ui . chatDebug );
el . toggleChatDebug . checked = debugEnabled ;
el . chatDebugPanel . hidden = ! debugEnabled ;
};
Debug Payload Display
The debug panel shows the complete request/response cycle:
// When debug mode is enabled, store the raw response
el . chatDebugPayload . textContent = JSON . stringify ({
request: {
agentId: state . bedrock . agentId ,
sessionId: state . bedrock . sessionId ,
message: userMessage
},
response: apiResponse
}, null , 2 );
The textarea supports keyboard shortcuts and auto-sizing:
< textarea id = "messageInput"
placeholder = "Escribe tu mensaje..." ></ textarea >
< div class = "row" style = "margin-top:8px;" >
< button class = "primary" id = "sendMessage" > Enviar </ button >
</ div >
Section Availability
The chat section is disabled until properly configured:
const updateSectionAvailability = () => {
const chatReady = isBedrockConfigured ();
el . chatSection . classList . toggle ( 'section-disabled' , ! chatReady );
el . messageInput . disabled = ! chatReady ;
el . sendMessage . disabled = ! chatReady ;
el . chatSectionHint . textContent = chatReady
? 'La sección de chat está habilitada.'
: 'Configura chat y credenciales para habilitar esta sección.' ;
};
const isBedrockConfigured = () =>
Boolean (
state . bedrock . region &&
state . bedrock . agentId &&
state . bedrock . agentAliasId &&
isAwsConfigured ()
);
Message Types
The chat interface uses a simple message type structure:
type ChatMessage = {
role : 'user' | 'assistant' ;
content : string ;
};
type ChatRequest = {
region : string ;
agentId : string ;
agentAliasId : string ;
sessionId ?: string ;
accessKeyId : string ;
secretAccessKey : string ;
sessionToken ?: string ;
messages : ChatMessage [];
};
Best Practices
Session IDs Always use unique session IDs for different users or conversation contexts
Error Handling Implement proper error handling for network failures and API errors
Debug Mode Use debug mode during development to troubleshoot API responses
Credentials Never commit AWS credentials to version control