diff --git a/docs/AGENT_SETUP_CHECKLIST.md b/docs/AGENT_SETUP_CHECKLIST.md index 6b9b25d..896e6f1 100644 --- a/docs/AGENT_SETUP_CHECKLIST.md +++ b/docs/AGENT_SETUP_CHECKLIST.md @@ -1,12 +1,25 @@ -# Agent Setup Checklist +# Agent Setup Checklist - Error-Free Creation Guide ## Steps to Complete After Running `create_agent` Command -This checklist covers the **6 essential steps** needed after running the automated `create_agent` command to make your agent fully functional. +This checklist covers the **6 essential steps** needed after running the automated `create_agent` command to make your agent fully functional. **Updated with debugging insights from the successful 5 Whys Agent implementation.** **โœ… The automated system now generates all code files including models, views, processors, and admin interface!** --- +## ๐Ÿš€ **Success Patterns from 5 Whys Agent** + +The 5 Whys Analyzer represents the most robust agent implementation with these key features: +- **Dual-mode processing**: Free chat interactions + paid report generation +- **Session-based architecture**: UUID tracking with persistent chat history +- **Delayed wallet deduction**: Only charge after successful processing +- **Comprehensive error handling**: Graceful failure recovery +- **Smart status tracking**: Proper request lifecycle management + +**Apply these patterns to achieve error-free agent creation.** + +--- + ## Example Command ```bash python manage.py create_agent "PDF Analyzer" "pdf-analyzer" api \ @@ -227,22 +240,29 @@ python manage.py shell -c "from django.urls import reverse; print('Agent URL:', --- -## ๐Ÿ› **Common Issues & Quick Fixes** +## ๐Ÿ› **Common Issues & Quick Fixes** *(Learned from 5 Whys Debugging)* ### **Issue 1: "No module named 'agent_pdf_analyzer'"** +**Root Cause:** App not added to Django settings **Fix:** Make sure you added the app to `INSTALLED_APPS` in settings.py +**Prevention:** Use the automated validation script (coming soon) ### **Issue 2: "TemplateDoesNotExist: detail.html"** +**Root Cause:** Template in wrong location or server cache **Fix:** Ensure template is in correct location within the agent app: ```bash # Template should be at: +agent_[name]/templates/agent_[name]/detail.html + +# NOT just: agent_[name]/templates/detail.html -# NOT in the global templates folder -# Restart Django server after moving templates +# CRITICAL: Restart Django server after moving templates ``` +**5 Whys Learning:** Template organization is crucial for reliability ### **Issue 3: "NoReverseMatch: Reverse for 'wallet' not found"** +**Root Cause:** Missing URL namespaces in templates **Fix:** Check template URLs use proper namespaces: ```html @@ -251,42 +271,100 @@ agent_[name]/templates/detail.html {% url 'core:wallet' %} ``` +**5 Whys Learning:** Always use namespaced URLs for reliability ### **Issue 4: "Agent not found" in marketplace** +**Root Cause:** BaseAgent entry missing or wrong slug **Fix:** Verify BaseAgent was created with correct slug: ```bash python manage.py shell -c "from agent_base.models import BaseAgent; print([a.slug for a in BaseAgent.objects.all()])" ``` -### **Issue 4: Agent page shows 404** +### **Issue 5: Agent page shows 404** +**Root Cause:** URL registration order is wrong **Fix:** Check URL registration order in `netcop_hub/urls.py` - agent URLs must come before core URLs. +**5 Whys Learning:** URL order matters for Django routing -### **Issue 5: API key errors** +### **Issue 6: API key errors** +**Root Cause:** Environment variable name mismatch **Fix:** Verify environment variable name matches processor: ```python # In processor.py api_key_env = 'DOCPARSER_API_KEY' # Must match .env file ``` ---- +### **Issue 7: Wallet deduction errors (5 Whys Pattern)** +**Root Cause:** Deducting balance before processing success +**Fix:** Follow the 5 Whys pattern - only deduct after successful processing: +```python +# โŒ Wrong - deduct before processing +user.deduct_balance(cost, description, agent_slug) +response = process_request() -## ๐Ÿ“ **Quick Checklist Summary** +# โœ… Correct - deduct after success (5 Whys pattern) +response = process_request() +if response.success: + user.deduct_balance(cost, description, agent_slug) +``` -After running `create_agent`, complete these 6 steps: +### **Issue 8: Migration conflicts** +**Root Cause:** Django migrations out of sync with database +**Fix:** Create empty migration to sync state: +```bash +# Create manual sync migration +python manage.py makemigrations [agent_name] --empty +# Edit migration to match your needs +python manage.py migrate +``` +**5 Whys Learning:** Migration conflicts are common - be prepared to sync manually -- [ ] **Settings:** Add agent to `INSTALLED_APPS` -- [ ] **URLs:** Add URL pattern to `netcop_hub/urls.py` -- [ ] **Database:** Run `makemigrations` and `migrate` -- [ ] **Marketplace:** Create `BaseAgent` entry (done automatically) -- [ ] **Environment:** Add API keys to `.env` -- [ ] **Template:** Create and customize `detail.html` template -- [ ] **Test:** Verify agent works end-to-end +### **Issue 9: Session management errors (Advanced Agents)** +**Root Cause:** No persistent session tracking +**Fix:** Implement session-based architecture like 5 Whys: +```python +# Add to your models +session_id = models.CharField(max_length=100, default=uuid.uuid4, db_index=True) +chat_messages = models.JSONField(default=list) +``` -**Total time:** ~10-15 minutes +### **Issue 10: Status tracking problems** +**Root Cause:** Inconsistent request status management +**Fix:** Use proper status lifecycle like 5 Whys: +```python +# Status flow: pending โ†’ processing โ†’ completed/failed +request_obj.status = 'processing' +request_obj.save() +# ... do processing ... +request_obj.status = 'completed' if success else 'failed' +request_obj.save() +``` --- -## ๐Ÿš€ **You're Done!** +## ๐Ÿ“ **Quick Checklist Summary** *(Error-Free Process)* + +After running `create_agent`, complete these **7 critical steps** (updated with 5 Whys learnings): + +- [ ] **Settings:** Add agent to `INSTALLED_APPS` in `netcop_hub/settings.py` +- [ ] **URLs:** Add URL pattern to `netcop_hub/urls.py` **BEFORE core URLs** +- [ ] **Database:** Run `makemigrations` and `migrate` (watch for conflicts) +- [ ] **Marketplace:** Verify `BaseAgent` entry created correctly +- [ ] **Environment:** Add API keys/webhook URLs to `.env` +- [ ] **Template:** Create `agent_[name]/templates/agent_[name]/detail.html` +- [ ] **Validation:** Run complete test flow including wallet integration + +**5 Whys Bonus Validations:** +- [ ] **Template Loading:** Restart Django server after template creation +- [ ] **URL Namespaces:** Use `{% url 'core:wallet' %}` not `{% url 'wallet' %}` +- [ ] **Error Handling:** Implement try-catch blocks in processor +- [ ] **Wallet Logic:** Only deduct balance after successful processing +- [ ] **Status Tracking:** Use pending โ†’ processing โ†’ completed/failed flow + +**Total time:** ~15-20 minutes (includes validation steps) + +--- + +## ๐Ÿš€ **You're Done!** *(Error-Free Agent)* Your agent should now be: โœ… **Visible** in the marketplace @@ -294,9 +372,22 @@ Your agent should now be: โœ… **Functional** with authentication โœ… **Processing** requests successfully โœ… **Integrated** with wallet system +โœ… **Error-resistant** with proper handling +โœ… **Session-aware** (if applicable) +โœ… **Status-tracked** throughout lifecycle + +**Success Validation** (5 Whys Standard): +- Agent processes test request without errors +- Wallet deduction only happens after successful processing +- Templates load correctly with namespaced URLs +- Error states are handled gracefully +- Status updates correctly throughout request lifecycle **Next Steps:** -- Customize the agent's UI/templates -- Add more complex business logic -- Configure additional API integrations -- Monitor usage and performance \ No newline at end of file +- Consider implementing dual-mode processing (free chat + paid reports) +- Add session management for complex interactions +- Enhance error handling with comprehensive try-catch blocks +- Monitor usage patterns and optimize based on 5 Whys learnings +- Document any new patterns for future agents + +**๐ŸŽฏ Remember:** Follow the 5 Whys Agent patterns for maximum reliability! \ No newline at end of file diff --git a/docs/DEVELOPMENT_GUIDE.md b/docs/DEVELOPMENT_GUIDE.md index 5ade896..abdfb2c 100644 --- a/docs/DEVELOPMENT_GUIDE.md +++ b/docs/DEVELOPMENT_GUIDE.md @@ -1,4 +1,4 @@ -# Development Guide +# Development Guide - Enhanced with Agent Testing ## Quick Start @@ -226,4 +226,489 @@ python manage.py shell # Django shell 1. Make script executable: `chmod +x run_dev.sh` 2. Check file permissions: `ls -la` +--- + +## ๐Ÿงช Agent Testing Procedures *(5 Whys Experience)* + +Based on extensive debugging and the successful 5 Whys Analyzer implementation, here are comprehensive testing procedures for error-free agent development. + +### Pre-Development Agent Testing Setup + +```bash +# Agent validation environment setup +python manage.py shell -c " +from agent_base.models import BaseAgent +from django.template.loader import get_template +from django.urls import reverse +import os + +def validate_agent_environment(agent_slug): + print(f'๐Ÿงช Testing environment for {agent_slug}...') + + # Test 1: BaseAgent exists + try: + agent = BaseAgent.objects.get(slug=agent_slug) + print(f'โœ… BaseAgent found: {agent.name}') + except BaseAgent.DoesNotExist: + print(f'โŒ BaseAgent not found for slug: {agent_slug}') + return False + + # Test 2: URL resolution + try: + url = reverse('core:agent_detail', args=[agent_slug]) + print(f'โœ… URL resolved: {url}') + except Exception as e: + print(f'โŒ URL resolution failed: {e}') + return False + + # Test 3: Template loading + try: + template = get_template(f'{agent_slug.replace(\"-\", \"_\")}/detail.html') + print(f'โœ… Template found: {template.origin.name}') + except Exception as e: + print(f'โŒ Template not found: {e}') + return False + + # Test 4: Environment variables (if needed) + env_var = f'N8N_WEBHOOK_{agent_slug.upper().replace(\"-\", \"_\")}' + if os.getenv(env_var): + print(f'โœ… Environment variable found: {env_var}') + else: + print(f'โš ๏ธ Environment variable not set: {env_var}') + + print(f'๐ŸŽฏ Environment validation complete for {agent_slug}') + return True + +# Test your agent +validate_agent_environment('five-whys-analyzer') +" +``` + +### Agent Request Lifecycle Testing + +```bash +# Test complete agent request lifecycle +python manage.py shell -c " +import uuid +from django.contrib.auth import get_user_model +from agent_base.models import BaseAgent +from five_whys_analyzer.models import FiveWhysAnalyzerRequest, FiveWhysAnalyzerResponse +from five_whys_analyzer.processor import FiveWhysAnalyzerProcessor +from decimal import Decimal + +User = get_user_model() + +def test_agent_lifecycle(agent_slug='five-whys-analyzer'): + print(f'๐Ÿงช Testing complete lifecycle for {agent_slug}...') + + # Get test user + user = User.objects.filter(is_superuser=True).first() + if not user: + print('โŒ No superuser found for testing') + return False + + # Test 1: Agent exists and is active + try: + agent = BaseAgent.objects.get(slug=agent_slug, is_active=True) + print(f'โœ… Active agent found: {agent.name} (${agent.price})') + except BaseAgent.DoesNotExist: + print(f'โŒ Active agent not found: {agent_slug}') + return False + + # Test 2: User has sufficient balance + if user.wallet_balance < agent.price: + print(f'โš ๏ธ User balance ({user.wallet_balance}) < agent price ({agent.price})') + print('Adding test balance...') + user.wallet_balance += Decimal('50.00') + user.save() + + # Test 3: Create request object + session_id = str(uuid.uuid4()) + try: + request_obj = FiveWhysAnalyzerRequest.objects.create( + user=user, + agent=agent, + session_id=session_id, + cost=Decimal('8.00'), + problem_statement='Test problem for validation', + status='pending' + ) + print(f'โœ… Request created: {request_obj.id}') + except Exception as e: + print(f'โŒ Request creation failed: {e}') + return False + + # Test 4: Status transitions + try: + request_obj.status = 'processing' + request_obj.save() + print('โœ… Status updated to processing') + + request_obj.status = 'completed' + request_obj.save() + print('โœ… Status updated to completed') + except Exception as e: + print(f'โŒ Status update failed: {e}') + return False + + # Test 5: Response creation + try: + response_obj = FiveWhysAnalyzerResponse.objects.create( + request=request_obj, + success=True, + final_report='Test report generated successfully', + processing_time=2.5 + ) + print(f'โœ… Response created: {response_obj.id}') + except Exception as e: + print(f'โŒ Response creation failed: {e}') + return False + + # Test 6: Cleanup + response_obj.delete() + request_obj.delete() + print('โœ… Test objects cleaned up') + + print(f'๐ŸŽฏ Lifecycle test completed successfully for {agent_slug}') + return True + +# Run the test +test_agent_lifecycle() +" +``` + +### Wallet Integration Testing + +```bash +# Test wallet integration patterns (5 Whys delayed deduction pattern) +python manage.py shell -c " +from django.contrib.auth import get_user_model +from agent_base.models import BaseAgent +from decimal import Decimal + +User = get_user_model() + +def test_wallet_integration(): + print('๐Ÿงช Testing wallet integration patterns...') + + user = User.objects.filter(is_superuser=True).first() + agent = BaseAgent.objects.filter(is_active=True).first() + + if not user or not agent: + print('โŒ Missing test user or agent') + return False + + # Record initial balance + initial_balance = user.wallet_balance + print(f'Initial balance: {initial_balance}') + + # Test 1: Balance check (5 Whys pattern) + if user.wallet_balance >= agent.price: + print('โœ… Sufficient balance for processing') + else: + print('โŒ Insufficient balance') + return False + + # Test 2: Delayed deduction simulation + print('๐Ÿ”„ Simulating processing...') + processing_success = True # Simulate success + + if processing_success: + # Only deduct after success (5 Whys pattern) + user.deduct_balance( + agent.price, + f'Test deduction for {agent.name}', + agent.slug + ) + print(f'โœ… Balance deducted after success: {user.wallet_balance}') + + # Verify deduction + expected_balance = initial_balance - agent.price + if user.wallet_balance == expected_balance: + print('โœ… Wallet deduction verified correct') + else: + print(f'โŒ Wallet deduction incorrect: expected {expected_balance}, got {user.wallet_balance}') + return False + else: + print('โœ… No deduction for failed processing (correct behavior)') + + # Test 3: Restore balance for other tests + user.wallet_balance = initial_balance + user.save() + print(f'๐Ÿ”„ Balance restored to: {user.wallet_balance}') + + print('๐ŸŽฏ Wallet integration test completed successfully') + return True + +test_wallet_integration() +" +``` + +### Template and URL Testing + +```bash +# Test template loading and URL routing (common 5 Whys issues) +python manage.py shell -c " +from django.template.loader import get_template +from django.urls import reverse +from django.test import RequestFactory +from django.contrib.auth import get_user_model + +User = get_user_model() + +def test_template_and_urls(): + print('๐Ÿงช Testing templates and URLs...') + + # Test template loading for all agents + agents = ['weather_reporter', 'five_whys_analyzer'] + + for agent in agents: + try: + template = get_template(f'{agent}/detail.html') + print(f'โœ… Template loaded for {agent}: {template.origin.name}') + except Exception as e: + print(f'โŒ Template failed for {agent}: {e}') + + # Test URL resolution + url_tests = [ + ('core:homepage', []), + ('core:marketplace', []), + ('core:wallet', []), + ('core:agent_detail', ['weather-reporter']), + ('core:agent_detail', ['five-whys-analyzer']), + ] + + for url_name, args in url_tests: + try: + url = reverse(url_name, args=args) + print(f'โœ… URL resolved {url_name}: {url}') + except Exception as e: + print(f'โŒ URL failed {url_name}: {e}') + + print('๐ŸŽฏ Template and URL testing completed') + +test_template_and_urls() +" +``` + +### Error Handling Testing + +```bash +# Test error handling patterns (5 Whys comprehensive error handling) +python manage.py shell -c " +from five_whys_analyzer.processor import FiveWhysAnalyzerProcessor +from agent_base.models import BaseAgent +from django.contrib.auth import get_user_model +import uuid + +User = get_user_model() + +def test_error_handling(): + print('๐Ÿงช Testing error handling patterns...') + + processor = FiveWhysAnalyzerProcessor() + user = User.objects.filter(is_superuser=True).first() + + # Test 1: Missing session_id + try: + result = processor.handle_chat_message( + user=user, + message='Test message' + # No session_id - should auto-generate + ) + print('โœ… Missing session_id handled gracefully') + except Exception as e: + print(f'โŒ Missing session_id caused error: {e}') + + # Test 2: Missing user + try: + result = processor.handle_chat_message( + session_id=str(uuid.uuid4()), + message='Test message' + # No user - should raise clear error + ) + print('โŒ Missing user should have raised error') + except Exception as e: + print(f'โœ… Missing user properly handled: {type(e).__name__}') + + # Test 3: Invalid message type + try: + result = processor.process_request( + user=user, + message_type='invalid_type' + ) + print('โŒ Invalid message type should have raised error') + except ValueError as e: + print(f'โœ… Invalid message type properly handled: {e}') + except Exception as e: + print(f'โŒ Unexpected error type: {e}') + + print('๐ŸŽฏ Error handling testing completed') + +test_error_handling() +" +``` + +### Performance and Index Testing + +```bash +# Test database performance and indexes (5 Whys optimization patterns) +python manage.py shell -c " +from django.db import connection +from five_whys_analyzer.models import FiveWhysAnalyzerRequest +from django.contrib.auth import get_user_model +import uuid +import time + +User = get_user_model() + +def test_performance(): + print('๐Ÿงช Testing database performance...') + + user = User.objects.first() + if not user: + print('โŒ No user found for testing') + return + + # Test 1: Session lookup performance + session_id = str(uuid.uuid4()) + + start_time = time.time() + try: + request = FiveWhysAnalyzerRequest.objects.filter( + user=user, + session_id=session_id, + chat_active=True + ).first() + end_time = time.time() + print(f'โœ… Session lookup completed in {(end_time - start_time)*1000:.2f}ms') + except Exception as e: + print(f'โŒ Session lookup failed: {e}') + + # Test 2: Index usage check + with connection.cursor() as cursor: + cursor.execute('EXPLAIN QUERY PLAN SELECT * FROM five_whys_analyzer_requests WHERE session_id = ?', [session_id]) + plan = cursor.fetchall() + + # Check if index is being used + plan_text = str(plan).lower() + if 'index' in plan_text: + print('โœ… Database index being used for session_id queries') + else: + print('โš ๏ธ No index detected for session_id queries') + + print('๐ŸŽฏ Performance testing completed') + +test_performance() +" +``` + +### Agent Integration Testing Commands + +```bash +# Complete agent validation script +python manage.py shell -c " +def run_complete_agent_test(agent_slug): + print(f'๐Ÿš€ Running complete agent test for {agent_slug}') + print('='*50) + + tests = [ + ('Environment', lambda: validate_agent_environment(agent_slug)), + ('Lifecycle', lambda: test_agent_lifecycle(agent_slug)), + ('Wallet', lambda: test_wallet_integration()), + ('Templates & URLs', lambda: test_template_and_urls()), + ('Error Handling', lambda: test_error_handling()), + ('Performance', lambda: test_performance()), + ] + + results = [] + for test_name, test_func in tests: + print(f'\\n๐Ÿงช Running {test_name} test...') + try: + result = test_func() + results.append((test_name, result)) + if result: + print(f'โœ… {test_name} test PASSED') + else: + print(f'โŒ {test_name} test FAILED') + except Exception as e: + print(f'โŒ {test_name} test ERROR: {e}') + results.append((test_name, False)) + + print(f'\\n๐ŸŽฏ Test Summary for {agent_slug}:') + print('='*30) + passed = sum(1 for _, result in results if result) + total = len(results) + + for test_name, result in results: + status = 'โœ… PASS' if result else 'โŒ FAIL' + print(f'{test_name}: {status}') + + print(f'\\nOverall: {passed}/{total} tests passed') + if passed == total: + print('๐ŸŽ‰ All tests passed! Agent is ready for production.') + else: + print('โš ๏ธ Some tests failed. Please review and fix issues.') + +# Run for 5 Whys Analyzer +run_complete_agent_test('five-whys-analyzer') +" +``` + +### 5 Whys Debugging Workflow + +When issues arise during agent development, follow this debugging workflow learned from 5 Whys experience: + +```bash +# 1. Basic validation +python manage.py check +python manage.py showmigrations [agent_name] + +# 2. Template validation +python manage.py shell -c " +from django.template.loader import get_template +template = get_template('[agent_name]/detail.html') +print('Template found:', template.origin.name) +" + +# 3. URL validation +python manage.py shell -c " +from django.urls import reverse +url = reverse('core:agent_detail', args=['[agent-slug]']) +print('URL resolved:', url) +" + +# 4. Model validation +python manage.py shell -c " +from [agent_name].models import * +from agent_base.models import BaseAgent +agent = BaseAgent.objects.get(slug='[agent-slug]') +print('Agent found:', agent.name) +" + +# 5. Processor validation +python manage.py shell -c " +from [agent_name].processor import [AgentName]Processor +processor = [AgentName]Processor() +print('Processor initialized successfully') +" +``` + +### Production Readiness Checklist + +Based on 5 Whys success patterns, verify these before deploying: + +- [ ] **Template Loading**: Templates load without server restart +- [ ] **URL Routing**: All URLs resolve correctly with namespaces +- [ ] **Database**: Migrations applied, indexes created +- [ ] **Wallet Integration**: Delayed deduction pattern implemented +- [ ] **Error Handling**: Comprehensive try-catch blocks +- [ ] **Session Management**: UUID-based sessions (if applicable) +- [ ] **Status Tracking**: Request lifecycle properly managed +- [ ] **Environment Variables**: All required variables validated +- [ ] **Performance**: Database queries optimized with indexes +- [ ] **Testing**: Complete test suite passes + +**๐ŸŽฏ Following these testing procedures ensures the same level of reliability achieved with the 5 Whys Analyzer.** + Happy coding! ๐ŸŽ‰ \ No newline at end of file diff --git a/docs/ERROR_PREVENTION_GUIDE.md b/docs/ERROR_PREVENTION_GUIDE.md new file mode 100644 index 0000000..c4bd04f --- /dev/null +++ b/docs/ERROR_PREVENTION_GUIDE.md @@ -0,0 +1,803 @@ +# Error Prevention Guide for Agent Creation + +## ๐ŸŽฏ Based on 5 Whys Analyzer Debugging Experience + +This guide documents all the common errors encountered during agent development and their proven solutions, based on extensive debugging work that led to the successful 5 Whys Analyzer implementation. + +--- + +## ๐Ÿ“‹ Table of Contents + +1. [Template Loading Errors](#template-loading-errors) +2. [URL Routing Issues](#url-routing-issues) +3. [Database Migration Conflicts](#database-migration-conflicts) +4. [Wallet Integration Problems](#wallet-integration-problems) +5. [Session Management Issues](#session-management-issues) +6. [Status Tracking Problems](#status-tracking-problems) +7. [Error Handling Failures](#error-handling-failures) +8. [Environment Variable Issues](#environment-variable-issues) +9. [N8N Webhook Problems](#n8n-webhook-problems) +10. [Performance and Index Issues](#performance-and-index-issues) + +--- + +## 1. Template Loading Errors + +### โŒ Common Error +``` +TemplateDoesNotExist: detail.html +django.template.loader.TemplateDoesNotExist: detail.html +``` + +### ๐Ÿ” Root Cause Analysis +- Template in wrong directory structure +- Django server cache holding old template paths +- Missing app in INSTALLED_APPS +- Incorrect template naming convention + +### โœ… 5 Whys Learned Solution + +**Correct Template Structure:** +```bash +# โœ… Correct - 5 Whys pattern +agent_five_whys_analyzer/ +โ””โ”€โ”€ templates/ + โ””โ”€โ”€ five_whys_analyzer/ + โ””โ”€โ”€ detail.html + +# โŒ Wrong - causes TemplateDoesNotExist +agent_five_whys_analyzer/ +โ””โ”€โ”€ templates/ + โ””โ”€โ”€ detail.html # Missing app subdirectory +``` + +**Template Path Validation Script:** +```bash +# Test template loading before starting server +python manage.py shell -c " +from django.template.loader import get_template +try: + template = get_template('five_whys_analyzer/detail.html') + print('โœ… Template found:', template.origin.name) +except Exception as e: + print('โŒ Template error:', e) +" +``` + +**Critical Fix Steps:** +1. Create proper directory structure +2. Move template to correct location +3. **RESTART Django server** (cache issue) +4. Verify template loading with shell command + +### ๐Ÿ›ก๏ธ Prevention Strategy +```bash +# Template creation checklist +mkdir -p [agent_name]/templates/[agent_name]/ +cp existing_working_template.html [agent_name]/templates/[agent_name]/detail.html +# Always restart server after template changes +``` + +--- + +## 2. URL Routing Issues + +### โŒ Common Errors +``` +NoReverseMatch: Reverse for 'wallet' not found +django.urls.exceptions.NoReverseMatch at /agents/five-whys-analyzer/ +``` + +### ๐Ÿ” Root Cause Analysis +- Missing URL namespaces in templates +- Incorrect URL registration order +- Agent URLs placed after catch-all core URLs + +### โœ… 5 Whys Learned Solution + +**Correct URL Namespacing in Templates:** +```html + +Wallet +Home + + +Wallet +Home +Login +``` + +**Correct URL Registration Order:** +```python +# netcop_hub/urls.py - CRITICAL ORDER +urlpatterns = [ + path('admin/', admin.site.urls), + path('auth/', include('authentication.urls')), + + # โœ… Agent URLs MUST come before core URLs + path('agents/weather-reporter/', include('weather_reporter.urls')), + path('agents/five-whys-analyzer/', include('five_whys_analyzer.urls')), + + # โŒ Core URLs with catch-all pattern must be LAST + path('', include('core.urls')), # This catches everything - put LAST +] +``` + +**URL Testing Commands:** +```bash +# Test URL resolution +python manage.py shell -c " +from django.urls import reverse +try: + url = reverse('core:agent_detail', args=['five-whys-analyzer']) + print('โœ… URL resolved:', url) +except Exception as e: + print('โŒ URL error:', e) +" +``` + +### ๐Ÿ›ก๏ธ Prevention Strategy +- Always use namespaced URLs in templates +- Register agent URLs before core URLs +- Test URL resolution after each agent creation + +--- + +## 3. Database Migration Conflicts + +### โŒ Common Errors +``` +django.db.utils.ProgrammingError: relation "five_whys_analyzer_requests" already exists +django.db.migrations.exceptions.InconsistentMigrationHistory +``` + +### ๐Ÿ” Root Cause Analysis +- Django migration state out of sync with actual database +- Manually created tables conflicting with migrations +- Migration dependencies missing or circular + +### โœ… 5 Whys Learned Solution + +**Manual Migration Sync Fix:** +```bash +# 1. Check current migration state +python manage.py showmigrations five_whys_analyzer + +# 2. Create empty migration to sync state +python manage.py makemigrations five_whys_analyzer --empty --name fix_migration_sync + +# 3. Edit the migration file to match current state +# migrations/000X_fix_migration_sync.py +from django.db import migrations + +class Migration(migrations.Migration): + dependencies = [ + ('five_whys_analyzer', '0001_initial'), + ] + operations = [ + # Empty operations - just sync Django state + ] + +# 4. Apply migration +python manage.py migrate five_whys_analyzer +``` + +**Conflict Resolution Pattern:** +```bash +# If migration conflicts persist +python manage.py migrate five_whys_analyzer --fake-initial +python manage.py migrate five_whys_analyzer +``` + +### ๐Ÿ›ก๏ธ Prevention Strategy +- Always run `makemigrations` immediately after model changes +- Test migrations on clean database before production +- Keep migration files in version control + +--- + +## 4. Wallet Integration Problems + +### โŒ Common Errors +``` +AttributeError: 'User' object has no attribute 'deduct_balance' +decimal.InvalidOperation: [] +Wallet balance incorrectly deducted for failed requests +``` + +### ๐Ÿ” Root Cause Analysis +- Deducting balance before processing completion +- Incorrect decimal handling for currency +- Missing wallet methods in User model + +### โœ… 5 Whys Learned Solution + +**Delayed Deduction Pattern (Critical):** +```python +# โŒ Wrong - deduct before processing +def process_view(request): + # Bad: deduct immediately + request.user.deduct_balance(agent.price, description, agent_slug) + result = process_request() # What if this fails? + return result + +# โœ… Correct - 5 Whys pattern (deduct after success) +def process_report_response(self, response_data, request_obj): + try: + # Process first + final_report = response_data.get('output', '') + success = bool(final_report) and response_data.get('success', True) + + if success: + # Save successful response + response_obj.final_report = final_report + response_obj.save() + + # ONLY deduct after confirmed success + request_obj.user.deduct_balance( + request_obj.cost, + f"5 Whys Analysis Agent - Final Report", + 'five-whys-analyzer' + ) + request_obj.status = 'completed' + else: + request_obj.status = 'failed' + # No wallet deduction for failures + + request_obj.save() + return response_obj + + except Exception as e: + request_obj.status = 'failed' + request_obj.save() + # No wallet deduction for exceptions + raise Exception(f"Failed to process: {e}") +``` + +**Decimal Handling:** +```python +# โœ… Correct decimal usage +from decimal import Decimal + +# Always use Decimal for currency +agent.price = Decimal('8.00') +request_obj.cost = Decimal('8.00') + +# Check balance properly +if request.user.wallet_balance >= agent.price: + # Proceed +``` + +### ๐Ÿ›ก๏ธ Prevention Strategy +- Never deduct balance before processing completion +- Always use Decimal for currency calculations +- Implement balance checks before processing +- Test wallet integration with both success and failure scenarios + +--- + +## 5. Session Management Issues + +### โŒ Common Errors +``` +KeyError: 'session_id' +Multiple chat sessions created for same user +Session state lost between requests +``` + +### ๐Ÿ” Root Cause Analysis +- Missing session ID handling +- No persistent session storage +- Poor session lifecycle management + +### โœ… 5 Whys Learned Solution + +**Session-Based Model Pattern:** +```python +# 5 Whys session management pattern +class AgentRequest(BaseAgentRequest): + # Session management + session_id = models.CharField(max_length=100, default=uuid.uuid4, db_index=True) + + # Session state tracking + chat_messages = models.JSONField(default=list) + chat_active = models.BooleanField(default=True) + report_generated = models.BooleanField(default=False) + + class Meta: + indexes = [ + models.Index(fields=['session_id']), + models.Index(fields=['user', 'chat_active']), + ] +``` + +**Session Retrieval Pattern:** +```python +# Safe session handling +def handle_chat_message(self, **kwargs): + user = kwargs.get('user') + session_id = kwargs.get('session_id', str(uuid.uuid4())) + + # Get or create session + request_obj, created = AgentRequest.objects.get_or_create( + user=user, + session_id=session_id, + chat_active=True, + defaults={ + 'agent': agent, + 'cost': 0, # No cost for chat + 'status': 'pending' + } + ) + + # Add message to history + chat_messages = request_obj.chat_messages + chat_messages.append({ + 'role': 'user', + 'message': user_message, + 'timestamp': timezone.now().isoformat() + }) + request_obj.chat_messages = chat_messages + request_obj.save() +``` + +### ๐Ÿ›ก๏ธ Prevention Strategy +- Always use UUID for session IDs +- Index session_id field for performance +- Implement session cleanup for old sessions +- Test session persistence across requests + +--- + +## 6. Status Tracking Problems + +### โŒ Common Errors +``` +Requests stuck in 'processing' status +Status not updated after completion +Inconsistent status across request lifecycle +``` + +### ๐Ÿ” Root Cause Analysis +- Missing status updates in error paths +- No status transitions defined +- Exception handling bypassing status updates + +### โœ… 5 Whys Learned Solution + +**Status Lifecycle Pattern:** +```python +# 5 Whys status tracking pattern +def process_response(self, response_data, request_obj): + try: + # Always update status to processing + request_obj.status = 'processing' + request_obj.save() + + # Process the request + success = self.extract_and_validate_response(response_data) + + # Update status based on result + if success: + request_obj.status = 'completed' + # Handle successful response + else: + request_obj.status = 'failed' + # Handle failed response + + except Exception as e: + # Always handle errors with status update + request_obj.status = 'failed' + request_obj.save() + raise + finally: + # Always set processed timestamp + request_obj.processed_at = timezone.now() + request_obj.save() +``` + +**Status Validation:** +```python +# Status transition validation +VALID_STATUS_TRANSITIONS = { + 'pending': ['processing', 'failed'], + 'processing': ['completed', 'failed'], + 'completed': [], # Terminal state + 'failed': [], # Terminal state +} + +def update_status(self, request_obj, new_status): + current_status = request_obj.status + if new_status not in VALID_STATUS_TRANSITIONS.get(current_status, []): + raise ValueError(f"Invalid status transition: {current_status} -> {new_status}") + request_obj.status = new_status + request_obj.save() +``` + +### ๐Ÿ›ก๏ธ Prevention Strategy +- Define clear status lifecycle +- Always update status in exception handlers +- Use try-finally blocks for cleanup +- Monitor requests stuck in processing status + +--- + +## 7. Error Handling Failures + +### โŒ Common Errors +``` +Unhandled exceptions breaking request flow +Users see raw Django error pages +No error logging for debugging +``` + +### ๐Ÿ” Root Cause Analysis +- Missing try-catch blocks +- No graceful error recovery +- Poor error messaging to users + +### โœ… 5 Whys Learned Solution + +**Comprehensive Error Handling Pattern:** +```python +# 5 Whys error handling pattern +def process_request(self, **kwargs): + request_obj = None + try: + # Create request object + request_obj = self.create_request_object(**kwargs) + + # Process the request + response_data = self.make_api_call(**kwargs) + + # Handle response + return self.process_response(response_data, request_obj) + + except ValidationError as e: + # User input error - don't log as system error + self.handle_user_error(request_obj, f"Invalid input: {e}") + raise Exception(f"Please check your input: {e}") + + except requests.RequestException as e: + # External API error - log and retry + self.log_api_error(e, request_obj) + self.handle_api_error(request_obj, "External service temporarily unavailable") + raise Exception("Service temporarily unavailable. Please try again later.") + + except Exception as e: + # Unknown error - log everything for debugging + self.log_system_error(e, request_obj, **kwargs) + self.handle_system_error(request_obj, "An unexpected error occurred") + raise Exception("An unexpected error occurred. Please contact support.") + +def handle_user_error(self, request_obj, message): + if request_obj: + request_obj.status = 'failed' + request_obj.save() + # Don't log user errors as system issues + +def handle_api_error(self, request_obj, message): + if request_obj: + request_obj.status = 'failed' + request_obj.save() + # Log API errors for monitoring + print(f"API Error: {message}") + +def handle_system_error(self, request_obj, message): + if request_obj: + request_obj.status = 'failed' + request_obj.save() + # Log system errors with full context + print(f"SYSTEM ERROR: {message}") + +def log_system_error(self, error, request_obj, **kwargs): + """Log system errors with full context for debugging""" + error_context = { + 'error': str(error), + 'request_id': str(request_obj.id) if request_obj else 'None', + 'user_id': kwargs.get('user', {}).get('id', 'None'), + 'agent_slug': self.agent_slug, + 'kwargs': kwargs + } + print(f"SYSTEM ERROR CONTEXT: {error_context}") +``` + +**User-Friendly Error Messages:** +```python +# Map internal errors to user-friendly messages +ERROR_MESSAGES = { + 'insufficient_balance': "Insufficient wallet balance. Please top up your wallet.", + 'file_too_large': "File size exceeds limit. Please upload a smaller file.", + 'invalid_format': "Unsupported file format. Please upload a valid file.", + 'api_timeout': "Request timed out. Please try again.", + 'service_unavailable': "Service temporarily unavailable. Please try again later.", + 'unknown_error': "An unexpected error occurred. Please contact support." +} + +def get_user_friendly_error(self, error_code): + return ERROR_MESSAGES.get(error_code, ERROR_MESSAGES['unknown_error']) +``` + +### ๐Ÿ›ก๏ธ Prevention Strategy +- Wrap all external calls in try-catch blocks +- Provide user-friendly error messages +- Log errors with sufficient context for debugging +- Test error scenarios during development + +--- + +## 8. Environment Variable Issues + +### โŒ Common Errors +``` +KeyError: 'N8N_WEBHOOK_5_WHYS' +API authentication failures +Webhook URLs not found +``` + +### ๐Ÿ” Root Cause Analysis +- Environment variables not loaded +- Variable name mismatches +- Missing .env file in production + +### โœ… 5 Whys Learned Solution + +**Environment Variable Pattern:** +```python +# Safe environment variable loading +import os +from django.conf import settings + +class AgentProcessor: + def __init__(self): + # Safe environment variable access + self.webhook_url = self.get_env_var('N8N_WEBHOOK_5_WHYS') + self.api_key = self.get_env_var('EXTERNAL_API_KEY') + + def get_env_var(self, var_name, default=None): + """Safely get environment variable with validation""" + value = os.getenv(var_name, default) + if not value and default is None: + raise Exception(f"Required environment variable '{var_name}' not found") + return value + + def validate_configuration(self): + """Validate all required environment variables""" + required_vars = [ + 'N8N_WEBHOOK_5_WHYS', + 'DATABASE_URL', + 'SECRET_KEY' + ] + + missing_vars = [] + for var in required_vars: + if not os.getenv(var): + missing_vars.append(var) + + if missing_vars: + raise Exception(f"Missing required environment variables: {missing_vars}") +``` + +**Environment Variable Validation Command:** +```bash +# Create validation script +python manage.py shell -c " +import os +required_vars = ['N8N_WEBHOOK_5_WHYS', 'OPENWEATHER_API_KEY', 'DATABASE_URL'] +missing = [var for var in required_vars if not os.getenv(var)] +if missing: + print('โŒ Missing variables:', missing) +else: + print('โœ… All required variables present') +" +``` + +### ๐Ÿ›ก๏ธ Prevention Strategy +- Create environment variable validation script +- Use safe access patterns with defaults +- Document all required variables +- Test with missing variables to ensure graceful failure + +--- + +## 9. N8N Webhook Problems + +### โŒ Common Errors +``` +Connection refused to N8N webhook +Webhook timeout errors +Invalid webhook response format +``` + +### ๐Ÿ” Root Cause Analysis +- N8N workflow not active +- Network connectivity issues +- Response format mismatches + +### โœ… 5 Whys Learned Solution + +**Webhook Validation Pattern:** +```python +# 5 Whys webhook handling pattern +class WebhookProcessor(StandardWebhookProcessor): + def make_request(self, payload): + """Make webhook request with comprehensive error handling""" + try: + # Validate webhook URL + if not self.webhook_url: + raise Exception("Webhook URL not configured") + + # Test connectivity first + self.test_webhook_connectivity() + + # Make request with timeout + response = requests.post( + self.webhook_url, + json=payload, + timeout=30, # 30 second timeout + headers={'Content-Type': 'application/json'} + ) + + # Validate response + if response.status_code != 200: + raise Exception(f"Webhook returned status {response.status_code}: {response.text}") + + # Validate response format + try: + response_data = response.json() + except ValueError: + raise Exception("Webhook returned invalid JSON") + + return response_data + + except requests.ConnectionError: + raise Exception("Cannot connect to N8N webhook. Check N8N service status.") + except requests.Timeout: + raise Exception("Webhook request timed out. Try again later.") + except Exception as e: + raise Exception(f"Webhook error: {e}") + + def test_webhook_connectivity(self): + """Test webhook connectivity before making actual request""" + try: + test_response = requests.get( + self.webhook_url.replace('/webhook/', '/ping/'), + timeout=5 + ) + return True + except: + # Webhook connectivity test failed - continue anyway + return False +``` + +**Webhook Response Validation:** +```python +def validate_webhook_response(self, response_data): + """Validate webhook response format""" + required_fields = ['output', 'success'] + + if not isinstance(response_data, dict): + raise Exception("Webhook response must be JSON object") + + missing_fields = [field for field in required_fields if field not in response_data] + if missing_fields: + raise Exception(f"Webhook response missing fields: {missing_fields}") + + return True +``` + +### ๐Ÿ›ก๏ธ Prevention Strategy +- Always test webhook connectivity +- Implement proper timeout handling +- Validate webhook response format +- Have fallback mechanisms for webhook failures + +--- + +## 10. Performance and Index Issues + +### โŒ Common Errors +``` +Slow database queries +Missing indexes on frequently queried fields +Session lookup timeouts +``` + +### ๐Ÿ” Root Cause Analysis +- Missing database indexes +- Inefficient query patterns +- No query optimization + +### โœ… 5 Whys Learned Solution + +**Database Index Pattern:** +```python +# 5 Whys performance optimization +class AgentRequest(BaseAgentRequest): + session_id = models.CharField(max_length=100, default=uuid.uuid4, db_index=True) + + class Meta: + indexes = [ + # Session-based queries + models.Index(fields=['session_id']), + models.Index(fields=['user', 'chat_active']), + + # Status and time-based queries + models.Index(fields=['status', 'created_at']), + models.Index(fields=['user', 'status']), + + # Agent-specific queries + models.Index(fields=['agent', 'created_at']), + ] +``` + +**Query Optimization Pattern:** +```python +# Efficient query patterns +def get_user_active_session(self, user, agent_slug): + """Optimized session lookup""" + return AgentRequest.objects.select_related('agent', 'user').filter( + user=user, + agent__slug=agent_slug, + chat_active=True + ).first() + +def get_recent_requests(self, user, limit=10): + """Optimized recent requests lookup""" + return AgentRequest.objects.select_related('agent').filter( + user=user + ).order_by('-created_at')[:limit] +``` + +### ๐Ÿ›ก๏ธ Prevention Strategy +- Add indexes for all frequently queried fields +- Use select_related for foreign key queries +- Monitor slow queries in production +- Test with realistic data volumes + +--- + +## ๐Ÿ›ก๏ธ Overall Prevention Strategy + +### Pre-Development Checklist +- [ ] Study 5 Whys Analyzer patterns before starting +- [ ] Plan session management if needed +- [ ] Design delayed wallet deduction flow +- [ ] Plan comprehensive error handling + +### During Development Checklist +- [ ] Use proper template directory structure +- [ ] Always use namespaced URLs +- [ ] Implement delayed wallet deduction +- [ ] Add comprehensive error handling +- [ ] Create proper database indexes + +### Post-Development Checklist +- [ ] Test all error scenarios +- [ ] Validate template loading +- [ ] Test URL routing +- [ ] Verify wallet integration +- [ ] Test session management +- [ ] Validate environment variables + +### Production Deployment Checklist +- [ ] Run migration validation +- [ ] Test webhook connectivity +- [ ] Verify environment variables +- [ ] Monitor error rates +- [ ] Check performance metrics + +--- + +## ๐ŸŽฏ Key Takeaways from 5 Whys Debugging + +1. **Template Organization is Critical**: Always use proper directory structure +2. **URL Namespaces Prevent Errors**: Always use namespaced URLs +3. **Delayed Wallet Deduction**: Never deduct before processing success +4. **Session Management**: Use UUID-based sessions for complex agents +5. **Status Tracking**: Implement proper lifecycle management +6. **Error Handling**: Wrap everything in try-catch blocks +7. **Environment Variables**: Validate all required variables +8. **Performance**: Add indexes for frequently queried fields + +**Following these patterns from the 5 Whys success ensures error-free agent creation.** \ No newline at end of file diff --git a/docs/MANUAL_AGENT_CREATION_GUIDE.md b/docs/MANUAL_AGENT_CREATION_GUIDE.md index 3b35073..431ce6d 100644 --- a/docs/MANUAL_AGENT_CREATION_GUIDE.md +++ b/docs/MANUAL_AGENT_CREATION_GUIDE.md @@ -1,6 +1,6 @@ -# Complete Manual Agent Creation Guide +# Complete Manual Agent Creation Guide - Error-Free Edition -This guide provides step-by-step instructions for manually creating AI agents in the NetCop Hub platform. +This guide provides step-by-step instructions for manually creating AI agents in the NetCop Hub platform. **Updated with proven patterns from the successful 5 Whys Analyzer implementation.** ## Table of Contents 1. [Overview](#overview) @@ -20,15 +20,28 @@ This guide provides step-by-step instructions for manually creating AI agents in ### Agent Types - **API Agents**: Direct integration with external APIs (e.g., OpenWeather, Stripe) -- **Webhook Agents**: Integration with N8N workflows or custom webhooks +- **Webhook Agents**: Integration with N8N workflows or custom webhooks *(Recommended)* +- **Dual-Mode Agents**: Free interactions + paid reports *(5 Whys Pattern)* -### Architecture +### Architecture *(5 Whys Success Patterns)* Each agent is a separate Django app that extends the base agent framework: - `BaseAgent`: Marketplace catalog entry - `BaseAgentRequest`/`BaseAgentResponse`: Request/response tracking - `BaseAgentProcessor`: Processing logic (API or webhook) - `BaseAgentView`: Form handling and authentication +### ๐Ÿš€ **5 Whys Analyzer Success Patterns** +The most robust agent implementation includes these key patterns: + +**Core Success Features:** +- **Session-based architecture**: UUID tracking with persistent state +- **Dual-mode processing**: Free chat interactions + paid report generation +- **Delayed wallet deduction**: Only charge after successful processing +- **Comprehensive error handling**: Try-catch blocks throughout lifecycle +- **Smart status tracking**: pending โ†’ processing โ†’ completed/failed + +**Apply these patterns for maximum reliability and user satisfaction.** + ## Prerequisites 1. Django project setup and running @@ -36,6 +49,199 @@ Each agent is a separate Django app that extends the base agent framework: 3. Authentication system configured 4. Wallet system for payments +--- + +## ๐ŸŽฏ **5 Whys Analyzer - Proven Implementation Patterns** + +Before diving into the step-by-step guide, study these proven patterns from the successful 5 Whys Analyzer implementation. **Following these patterns ensures error-free agent creation.** + +### Session-Based Models *(Recommended for Complex Agents)* + +```python +# Key model patterns from 5 Whys success +class FiveWhysAnalyzerRequest(BaseAgentRequest): + # Session management + session_id = models.CharField(max_length=100, default=uuid.uuid4, db_index=True) + + # Chat interaction tracking + chat_messages = models.JSONField(default=list) + + # Mode tracking + report_generated = models.BooleanField(default=False) + chat_active = models.BooleanField(default=True) + + # Specific request data + problem_statement = models.TextField(blank=True) + analysis_depth = models.CharField(max_length=20, choices=[...]) +``` + +### Delayed Wallet Deduction Pattern *(Critical for Reliability)* + +```python +# โŒ Wrong - deduct before processing +user.deduct_balance(cost, description, agent_slug) +response = process_request() + +# โœ… Correct - 5 Whys pattern (deduct after success) +def process_report_response(self, response_data, request_obj): + try: + # Process the request first + final_report = response_data.get('output', '') + success = bool(final_report) and response_data.get('success', True) + + if success: + # Save response data + response_obj.final_report = final_report + response_obj.save() + + # ONLY deduct wallet balance after successful processing + request_obj.user.deduct_balance( + request_obj.cost, + f"5 Whys Analysis Agent - Final Report", + 'five-whys-analyzer' + ) + request_obj.status = 'completed' + else: + request_obj.status = 'failed' + + request_obj.save() + return response_obj + except Exception as e: + request_obj.status = 'failed' + request_obj.save() + raise Exception(f"Failed to process: {e}") +``` + +### Dual-Mode Processing Pattern *(Free + Paid Interactions)* + +```python +# 5 Whys processor pattern - handle both free chat and paid reports +def process_request(self, **kwargs): + message_type = kwargs.get('message_type', 'chat') + + if message_type == 'chat': + return self.handle_chat_message(**kwargs) # Free + elif message_type == 'generate_report': + return self.handle_report_generation(**kwargs) # Paid + else: + raise ValueError(f"Unknown message type: {message_type}") + +def handle_chat_message(self, **kwargs): + # No wallet deduction for chat + request_obj.cost = 0 + # Process free interaction + return self.process_chat_response(response_data, request_obj) + +def handle_report_generation(self, **kwargs): + # Set cost for report generation + request_obj.cost = 8.0 + # Process paid interaction (wallet deducted only after success) + return self.process_report_response(response_data, request_obj) +``` + +### Comprehensive Error Handling Pattern + +```python +# 5 Whys error handling pattern +def process_response(self, response_data, request_obj): + try: + request_obj.status = 'processing' + request_obj.save() + + # Extract and validate response + result = response_data.get('output', '') + success = bool(result) and response_data.get('success', True) + + # Create response object + response_obj, created = ModelResponse.objects.get_or_create( + request=request_obj, + defaults={'success': success, 'processing_time': response_data.get('processing_time', 0)} + ) + + if success: + response_obj.result_data = result + response_obj.save() + + # Only deduct balance after confirmed success + request_obj.user.deduct_balance( + request_obj.cost, + f"Agent processing - {request_obj.agent.name}", + request_obj.agent.slug + ) + request_obj.status = 'completed' + else: + request_obj.status = 'failed' + response_obj.error_message = "Processing failed" + response_obj.save() + + request_obj.processed_at = timezone.now() + request_obj.save() + + return response_obj + + except Exception as e: + # Always handle errors gracefully + request_obj.status = 'failed' + request_obj.save() + + # Log the error for debugging + print(f"Agent {self.agent_slug} error: {e}") + raise Exception(f"Failed to process response: {e}") +``` + +### Status Tracking Pattern *(Request Lifecycle Management)* + +```python +# 5 Whys status flow pattern +# 1. Initial state +request_obj.status = 'pending' + +# 2. Start processing +request_obj.status = 'processing' +request_obj.save() + +# 3. Complete or fail +try: + # ... do processing ... + request_obj.status = 'completed' +except Exception: + request_obj.status = 'failed' +finally: + request_obj.processed_at = timezone.now() + request_obj.save() +``` + +### Template URL Namespace Pattern *(Prevents 404 Errors)* + +```html + +Wallet + + +Wallet +Home +Login +``` + +### Database Index Pattern *(Performance Optimization)* + +```python +# 5 Whys database optimization patterns +class AgentRequest(BaseAgentRequest): + session_id = models.CharField(max_length=100, default=uuid.uuid4, db_index=True) + + class Meta: + indexes = [ + models.Index(fields=['session_id']), + models.Index(fields=['user', 'chat_active']), + models.Index(fields=['status', 'created_at']), + ] +``` + +**๐ŸŽฏ Key Takeaway:** The 5 Whys Analyzer's success comes from these robust patterns. Apply them to your agents for maximum reliability and user satisfaction. + +--- + ## Step 1: Create Django App ### 1.1 Create the App @@ -304,12 +510,9 @@ class PdfAnalyzerProcessView(View): language=language, ) - # Deduct from wallet - request.user.deduct_balance( - agent.price, - f"PDF Analyzer request for {pdf_file.name}", - 'pdf-analyzer' - ) + # โš ๏ธ WARNING: This violates 5 Whys pattern! + # Better to deduct ONLY after successful processing + # Consider implementing delayed deduction pattern for reliability # Process request processor = PdfAnalyzerProcessor()