quantum-ai-v3/docs/OPTIMIZED_AGENT_CREATION_GUIDE.md
2025-07-19 08:06:31 +05:30

16 KiB

Optimized Agent Creation Guide

This guide provides comprehensive patterns and best practices for creating agents without UI/UX failures, based on the optimized Data Analyzer and Job Posting Generator implementations.

Quick Start Checklist

Template Architecture

  • Use widget-based layout with CSS custom properties
  • Implement self-contained styles (no external dependencies)
  • Add proper responsive design with flexbox
  • Include accessibility ARIA attributes

Security Implementation

  • Implement HTML sanitization functions
  • Use XSS prevention techniques
  • Validate all form inputs
  • Use safe DOM manipulation

Performance Optimization

  • Add debouncing for form interactions
  • Implement proper event listener management
  • Use efficient DOM queries
  • Add loading states and feedback

Wallet Integration

  • Implement dynamic wallet balance validation
  • Add wallet balance synchronization
  • Include proper error handling
  • Add visual feedback for balance updates

Agent Navigation

  • Implement quick agent access panel
  • Add proper agent linking
  • Include agent discovery features
  • Add smooth transitions and animations

Widget-Based Architecture

Core Layout Structure

<div class="agent-container">
    <div class="agent-grid">
        <!-- Left Column: Main Content -->
        <div class="agent-main">
            <div class="agent-header">...</div>
            <div class="agent-form">...</div>
            <div class="agent-output">...</div>
        </div>
        
        <!-- Right Column: Sidebar Widgets -->
        <div class="agent-sidebar">
            <div class="widget wallet-widget">...</div>
            <div class="widget how-it-works-widget">...</div>
            <div class="widget other-agents-widget">...</div>
        </div>
    </div>
</div>

CSS Custom Properties System

:root {
    --primary: #000000;
    --surface: #ffffff;
    --surface-variant: #f8fafc;
    --background: #f3f4f6;
    --outline: #e4e7eb;
    --outline-variant: #e1e4e7;
    --on-surface: #1a1a1a;
    --on-surface-variant: #6b7280;
    --success: #10b981;
    --error: #ef4444;
    --radius-sm: 8px;
    --radius-md: 12px;
    --radius-lg: 16px;
    --spacing-xs: 4px;
    --spacing-sm: 8px;
    --spacing-md: 16px;
    --spacing-lg: 24px;
    --spacing-xl: 32px;
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
    --shadow-md: 0 4px 8px rgba(0, 0, 0, 0.1);
    --shadow-lg: 0 10px 20px rgba(0, 0, 0, 0.15);
}

Widget Styling Standards

.widget {
    background: var(--surface);
    border: 1px solid var(--outline);
    border-radius: var(--radius-md);
    padding: var(--spacing-lg);
    margin-bottom: var(--spacing-md);
    box-shadow: var(--shadow-sm);
    transition: all 0.2s ease;
}

.widget:hover {
    box-shadow: var(--shadow-md);
}

.widget h3 {
    margin: 0 0 var(--spacing-md) 0;
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--on-surface);
}

Security Implementation

HTML Sanitization Function

function safeSetHTML(element, htmlString) {
    // Create temporary container
    const temp = document.createElement('div');
    temp.innerHTML = htmlString;
    
    // Remove all script tags
    const scripts = temp.querySelectorAll('script');
    scripts.forEach(script => script.remove());
    
    // Remove dangerous attributes
    const allElements = temp.querySelectorAll('*');
    allElements.forEach(el => {
        // Remove event handlers
        const attrs = el.attributes;
        for (let i = attrs.length - 1; i >= 0; i--) {
            const attr = attrs[i];
            if (attr.name.startsWith('on') || 
                attr.name === 'javascript:' || 
                attr.name === 'data-') {
                el.removeAttribute(attr.name);
            }
        }
        
        // Remove dangerous href/src
        if (el.tagName === 'A' && el.href && el.href.startsWith('javascript:')) {
            el.removeAttribute('href');
        }
        if (el.tagName === 'IMG' && el.src && el.src.startsWith('javascript:')) {
            el.removeAttribute('src');
        }
    });
    
    // Set sanitized content
    element.innerHTML = temp.innerHTML;
}

XSS Prevention Pattern

// Always validate and sanitize user input
function sanitizeInput(input) {
    return input
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#x27;');
}

// Use when displaying user content
function displayUserContent(content) {
    const sanitized = sanitizeInput(content);
    const element = document.getElementById('output');
    element.textContent = sanitized; // Use textContent, not innerHTML
}

Wallet Balance Integration

Dynamic Balance Validation

// CRITICAL: Always read balance dynamically from DOM
function validateWalletBalance() {
    const walletBalanceElement = document.getElementById('walletBalance');
    const currentBalance = walletBalanceElement ? 
        parseFloat(walletBalanceElement.textContent) : 0;
    
    if (currentBalance < 4.00) {
        showError('Insufficient wallet balance. Please top up your wallet.');
        return false;
    }
    return true;
}

Balance Synchronization

function updateWalletBalance(newBalance) {
    if (newBalance !== undefined) {
        // Update header balance
        const headerBalance = document.querySelector('a[data-wallet-balance]');
        if (headerBalance) {
            headerBalance.textContent = `💰 ${newBalance.toFixed(2)} AED`;
        }
        
        // Update page balance
        const pageBalance = document.getElementById('walletBalance');
        if (pageBalance) {
            pageBalance.textContent = newBalance.toFixed(2);
        }
    }
}

Performance Optimization

Debounced Form Interactions

function debounce(func, wait) {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
}

// Usage for form validation
const debouncedValidation = debounce(validateForm, 300);
document.getElementById('jobForm').addEventListener('input', debouncedValidation);

Event Listener Management

class AgentManager {
    constructor() {
        this.eventListeners = [];
    }
    
    addEventListeners() {
        // Store references for cleanup
        const submitHandler = this.handleSubmit.bind(this);
        const resetHandler = this.handleReset.bind(this);
        
        document.getElementById('submitBtn').addEventListener('click', submitHandler);
        document.getElementById('resetBtn').addEventListener('click', resetHandler);
        
        // Store for cleanup
        this.eventListeners.push(
            { element: document.getElementById('submitBtn'), event: 'click', handler: submitHandler },
            { element: document.getElementById('resetBtn'), event: 'click', handler: resetHandler }
        );
    }
    
    cleanup() {
        // Remove all event listeners
        this.eventListeners.forEach(({ element, event, handler }) => {
            if (element) {
                element.removeEventListener(event, handler);
            }
        });
        this.eventListeners = [];
    }
}

Accessibility Implementation

ARIA Attributes

<!-- Form with proper ARIA labeling -->
<form id="agentForm" role="main" aria-label="Agent Input Form">
    <div class="form-group">
        <label for="inputField" class="form-label">
            Input Description
            <span class="required" aria-label="required">*</span>
        </label>
        <textarea 
            id="inputField" 
            name="input_text" 
            class="form-control" 
            placeholder="Enter your input here..."
            aria-describedby="inputHelp"
            aria-required="true"
            rows="4">
        </textarea>
        <div id="inputHelp" class="form-text">
            Provide clear, specific information for better results.
        </div>
    </div>
</form>

<!-- Loading state with proper ARIA -->
<div id="loadingState" class="loading-state" 
     aria-live="polite" 
     aria-label="Processing request"
     style="display: none;">
    <div class="spinner" role="status" aria-hidden="true"></div>
    <span class="sr-only">Processing your request...</span>
</div>

Keyboard Navigation

// Ensure proper tab order and keyboard navigation
function enhanceAccessibility() {
    // Add keyboard support for custom elements
    document.querySelectorAll('.custom-button').forEach(button => {
        button.setAttribute('tabindex', '0');
        button.addEventListener('keydown', (e) => {
            if (e.key === 'Enter' || e.key === ' ') {
                e.preventDefault();
                button.click();
            }
        });
    });
    
    // Add focus management
    document.addEventListener('keydown', (e) => {
        if (e.key === 'Escape' && document.querySelector('.modal.active')) {
            closeModal();
        }
    });
}

Quick Agent Access Implementation

Right-Slide Panel

<div class="widget other-agents-widget">
    <h3>🤖 Explore Other Agents</h3>
    <p>Discover more AI agents to boost your productivity</p>
    <button class="btn btn-outline" onclick="showQuickAgentAccess()">
        Quick Agent Access
    </button>
</div>

<!-- Quick Access Panel -->
<div id="quickAgentPanel" class="quick-agent-panel">
    <div class="panel-header">
        <h3>🚀 Quick Agent Access</h3>
        <button class="panel-close" onclick="hideQuickAgentAccess()">&times;</button>
    </div>
    <div class="panel-content">
        <div class="agent-grid">
            <!-- Agent cards populated dynamically -->
        </div>
    </div>
</div>

Panel Styling

.quick-agent-panel {
    position: fixed;
    top: 0;
    right: -400px;
    width: 400px;
    height: 100vh;
    background: var(--surface);
    border-left: 1px solid var(--outline);
    box-shadow: var(--shadow-lg);
    z-index: 1000;
    transition: right 0.3s ease;
    overflow-y: auto;
}

.quick-agent-panel.active {
    right: 0;
}

.panel-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--spacing-lg);
    border-bottom: 1px solid var(--outline);
}

.panel-close {
    background: none;
    border: none;
    font-size: 24px;
    cursor: pointer;
    color: var(--on-surface-variant);
}

Panel JavaScript

function showQuickAgentAccess() {
    const panel = document.getElementById('quickAgentPanel');
    const overlay = document.createElement('div');
    overlay.className = 'panel-overlay';
    overlay.onclick = hideQuickAgentAccess;
    document.body.appendChild(overlay);
    
    panel.classList.add('active');
    document.body.style.overflow = 'hidden';
    
    // Load agents if not already loaded
    if (!panel.dataset.loaded) {
        loadQuickAgents();
        panel.dataset.loaded = 'true';
    }
}

function hideQuickAgentAccess() {
    const panel = document.getElementById('quickAgentPanel');
    const overlay = document.querySelector('.panel-overlay');
    
    panel.classList.remove('active');
    document.body.style.overflow = '';
    
    if (overlay) {
        overlay.remove();
    }
}

function loadQuickAgents() {
    const agents = [
        {
            name: 'Data Analyzer',
            description: 'Analyze and interpret your data files with AI precision',
            url: '/data-analyzer/',
            emoji: '📊'
        },
        {
            name: 'Job Posting Generator',
            description: 'Create professional job postings in minutes',
            url: '/job-posting-generator/',
            emoji: '💼'
        },
        // Add more agents as needed
    ];
    
    const container = document.querySelector('#quickAgentPanel .agent-grid');
    container.innerHTML = agents.map(agent => `
        <div class="agent-card">
            <div class="agent-emoji">${agent.emoji}</div>
            <h4>${agent.name}</h4>
            <p>${agent.description}</p>
            <a href="${agent.url}" class="btn btn-primary btn-sm">
                Try Now
            </a>
        </div>
    `).join('');
}

Form Validation Patterns

Client-Side Validation

function validateForm() {
    const form = document.getElementById('agentForm');
    const inputs = form.querySelectorAll('input, textarea, select');
    let isValid = true;
    
    inputs.forEach(input => {
        const errorElement = document.getElementById(`${input.id}-error`);
        
        // Clear previous errors
        input.classList.remove('is-invalid');
        if (errorElement) {
            errorElement.textContent = '';
        }
        
        // Validate required fields
        if (input.hasAttribute('required') && !input.value.trim()) {
            showFieldError(input, 'This field is required');
            isValid = false;
        }
        
        // Validate specific field types
        if (input.type === 'email' && input.value && !isValidEmail(input.value)) {
            showFieldError(input, 'Please enter a valid email address');
            isValid = false;
        }
        
        if (input.type === 'url' && input.value && !isValidURL(input.value)) {
            showFieldError(input, 'Please enter a valid URL');
            isValid = false;
        }
    });
    
    return isValid;
}

function showFieldError(input, message) {
    input.classList.add('is-invalid');
    const errorElement = document.getElementById(`${input.id}-error`);
    if (errorElement) {
        errorElement.textContent = message;
    }
}

function isValidEmail(email) {
    const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return regex.test(email);
}

function isValidURL(url) {
    try {
        new URL(url);
        return true;
    } catch {
        return false;
    }
}

Error Handling Patterns

User-Friendly Error Display

function showError(message, type = 'error') {
    const errorContainer = document.getElementById('errorContainer');
    const errorElement = document.createElement('div');
    errorElement.className = `alert alert-${type} alert-dismissible`;
    errorElement.innerHTML = `
        <span class="alert-icon">⚠️</span>
        <span class="alert-message">${message}</span>
        <button type="button" class="alert-close" onclick="this.parentElement.remove()">
            &times;
        </button>
    `;
    
    errorContainer.appendChild(errorElement);
    
    // Auto-dismiss after 5 seconds
    setTimeout(() => {
        if (errorElement.parentNode) {
            errorElement.remove();
        }
    }, 5000);
}

function showSuccess(message) {
    showError(message, 'success');
}

Testing Requirements

UI/UX Testing Checklist

  • Test widget responsive behavior on different screen sizes
  • Verify wallet balance updates in real-time
  • Test form validation with various input combinations
  • Verify accessibility with screen reader
  • Test keyboard navigation through all interactive elements
  • Check quick agent access panel functionality
  • Verify error handling and user feedback
  • Test performance with large outputs

Security Testing

  • Test XSS prevention with malicious inputs
  • Verify HTML sanitization functions
  • Test CSRF protection
  • Check for sensitive data exposure
  • Validate input sanitization

Deployment Checklist

Pre-Deployment

  • Run all tests and ensure they pass
  • Check for console errors
  • Verify accessibility compliance
  • Test on multiple browsers
  • Validate HTML and CSS
  • Check for unused CSS/JS
  • Optimize images and assets
  • Test with real user data

Post-Deployment

  • Monitor for JavaScript errors
  • Check wallet balance functionality
  • Verify agent processing works correctly
  • Test performance metrics
  • Monitor user feedback
  • Check analytics for usage patterns

Maintenance Guidelines

Regular Updates

  • Keep dependencies updated
  • Monitor for security vulnerabilities
  • Update accessibility standards
  • Review performance metrics
  • Update documentation

Code Quality

  • Follow consistent coding standards
  • Use proper commenting
  • Implement proper error handling
  • Add comprehensive tests
  • Regular code reviews

This guide ensures that all future agents follow the same optimized patterns, preventing UI/UX failures and maintaining consistency across the platform.