quantum-ai/docs/development/agent-creation.md
Claude 87397aceb5 🤖 Add specialized subagents and auto-documentation system
- Create 5 specialized subagents for improved development workflow:
  - django-expert: Django development specialist
  - agent-architect: AI agent development specialist
  - django-debugger: Django debugging specialist
  - security-auditor: Security review specialist
  - template-optimizer: Frontend optimization specialist

- Implement comprehensive auto-documentation system:
  - Slash command integration (/update-docs)
  - Git hooks for automatic updates
  - Manual trigger scripts
  - Documentation automation tools

- Update project documentation:
  - Enhanced agent creation guide with recent improvements
  - Toast messaging standardization documented
  - Dynamic pricing implementation patterns
  - Subagents usage guide

🎯 Key Benefits:
- 10x faster agent development with specialized assistance
- Automated security reviews and Django best practices
- Consistent template architecture and optimization
- Comprehensive documentation maintenance

Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-27 17:47:37 +05:30

757 lines
22 KiB
Markdown

# Agent Creation Guide using Template Prototype
This guide provides step-by-step instructions for creating new Django agents using the `agent_template_prototype.html` template system.
## Overview
The NetCop Hub uses a standardized template prototype (`agent_template_prototype.html`) that provides:
- Complete CSS framework with custom properties
- JavaScript utilities for common functions
- Consistent UI components (wallet card, processing status, quick access panel)
- Responsive design and accessibility features
- Toast notifications and status management
## Quick Start
### 1. Create Django Agent Structure
```bash
# Use the built-in Django command
python manage.py create_agent
# Or create manually:
mkdir your_agent_name
cd your_agent_name
touch __init__.py models.py views.py processor.py urls.py admin.py
mkdir templates
mkdir templates/your_agent_name
```
### 2. Required Files Checklist
- `__init__.py` - Empty Python package file
- `models.py` - Request model with base fields + agent-specific fields
- `processor.py` - Inherits from BaseAgentProcessor
- `views.py` - Detail view with form handling and status polling
- `urls.py` - URL patterns for detail and status endpoints
- `admin.py` - Django admin configuration
- `templates/your_agent_name/detail.html` - Converted template from prototype
## Template Conversion Process
### Step 1: Copy Base Structure from Prototype
Start with the `agent_template_prototype.html` and convert to Django template format:
```html
{% extends 'base.html' %}
{% load static %}
{% block title %}Your Agent Name - NetCop Hub{% endblock %}
{% block content %}
<div class="agent-container">
<!-- Copy CSS from prototype within <style> tags -->
<style>
/* All CSS from agent_template_prototype.html lines 8-632 */
</style>
<!-- Copy HTML structure -->
<!-- Agent Header -->
<div class="agent-header">
<div>
<h1 class="agent-title">Your Agent Name</h1>
<p class="agent-subtitle">Description of what your agent does</p>
</div>
<div class="header-controls">
{% include 'components/wallet_card.html' %}
</div>
</div>
<!-- Main agent content -->
<!-- ... -->
</div>
<!-- Copy JavaScript from prototype -->
<script>
/* All JavaScript from agent_template_prototype.html lines 808-967 */
</script>
{% endblock %}
```
### Step 2: Replace Placeholder Sections
Replace the placeholder sections with your agent-specific content:
**Agent Grid Section (lines 704-714 in prototype):**
```html
<div class="agent-grid">
<div class="agent-widget widget-large">
<div class="widget-header">
<h3 class="widget-title">
<span class="widget-icon">🎯</span>
Your Agent Form
</h3>
</div>
<div class="widget-content">
{% if user.is_authenticated %}
<form method="post" id="agentForm">
{% csrf_token %}
<!-- Your form fields here -->
</form>
{% else %}
<p>Please <a href="{% url 'authentication:login' %}">login</a> to use this agent.</p>
{% endif %}
</div>
</div>
<!-- How It Works Widget (keep as-is from prototype) -->
<div class="agent-widget widget-small">
<!-- Copy from prototype lines 716-744 -->
</div>
</div>
```
**Results Section (lines 763-774 in prototype):**
```html
<div class="agent-grid">
<div class="agent-widget widget-wide" id="resultsSection" style="display: none;">
<div class="widget-header">
<h3 class="widget-title">
<span class="widget-icon">📊</span>
Results
</h3>
</div>
<div class="widget-content">
<div id="resultsContent">
<!-- Agent-specific results display -->
</div>
<div style="display: flex; gap: var(--spacing-md); margin-top: var(--spacing-lg);">
<button onclick="copyToClipboard(document.getElementById('resultsContent').textContent)">
📋 Copy Results
</button>
<button onclick="downloadAsFile(document.getElementById('resultsContent').textContent, 'agent_results.txt')">
💾 Download
</button>
</div>
</div>
</div>
</div>
```
## Django Implementation Patterns
### Models Structure
Follow this pattern for all agent models:
```python
from django.db import models
from django.contrib.auth import get_user_model
import uuid
User = get_user_model()
class YourAgentRequest(models.Model):
"""Your Agent request model"""
# Base request fields (required for all agents)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
status = models.CharField(max_length=20, choices=[
('pending', 'Pending'),
('processing', 'Processing'),
('completed', 'Completed'),
('failed', 'Failed'),
], default='pending')
cost = models.DecimalField(max_digits=10, decimal_places=2, default=3.00)
created_at = models.DateTimeField(auto_now_add=True)
processed_at = models.DateTimeField(null=True, blank=True)
# Agent-specific fields
your_field = models.CharField(max_length=200, help_text="Field description")
# ... more fields
# Result fields
result_content = models.TextField(blank=True, help_text="Generated results")
class Meta:
verbose_name = "Your Agent Request"
verbose_name_plural = "Your Agent Requests"
ordering = ['-created_at']
def __str__(self):
return f"Your Agent - {self.your_field}"
```
### Views Pattern
```python
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from .models import YourAgentRequest
from .processor import YourAgentProcessor
@login_required
def your_agent_detail(request):
if request.method == 'POST':
# Form validation
if not request.POST.get('required_field'):
return JsonResponse({'error': 'Required field is missing'}, status=400)
# Check wallet balance
if request.user.wallet_balance < 3.00:
return JsonResponse({'error': 'Insufficient balance'}, status=400)
# Create request
agent_request = YourAgentRequest.objects.create(
user=request.user,
your_field=request.POST.get('your_field'),
# ... other fields
)
# Process with agent
processor = YourAgentProcessor()
processor.process_request(agent_request)
return JsonResponse({'success': True, 'request_id': str(agent_request.id)})
return render(request, 'your_agent/detail.html', {
'agent_cost': 3.00
})
@require_http_methods(["GET"])
def your_agent_status(request, request_id):
try:
agent_request = YourAgentRequest.objects.get(id=request_id, user=request.user)
return JsonResponse({
'status': agent_request.status,
'result': agent_request.result_content if agent_request.status == 'completed' else None
})
except YourAgentRequest.DoesNotExist:
return JsonResponse({'error': 'Request not found'}, status=404)
```
### Processor Pattern
```python
from agent_base.processors import BaseAgentProcessor
class YourAgentProcessor(BaseAgentProcessor):
def get_cost(self):
return 3.00
def prepare_webhook_data(self, request_obj):
return {
'your_field': request_obj.your_field,
# ... other fields
}
def process_webhook_response(self, request_obj, response_data):
if response_data.get('success'):
request_obj.result_content = response_data.get('result', '')
request_obj.status = 'completed'
else:
request_obj.status = 'failed'
request_obj.save()
```
## Form Integration with Template
### HTML Form Structure
```html
<form method="post" id="agentForm">
{% csrf_token %}
<div style="display: flex; flex-direction: column; gap: var(--spacing-md);">
<div>
<label for="your_field">Your Field:</label>
<input type="text" id="your_field" name="your_field" required>
</div>
<!-- More form fields -->
<button type="submit"
style="padding: var(--spacing-md); background: var(--primary); color: white; border: none; border-radius: var(--radius-md); cursor: pointer;">
Process Request ({{ agent_cost }} AED)
</button>
</div>
</form>
```
### JavaScript Form Handling
Add this to your template's JavaScript section:
```javascript
// Form submission handling
document.getElementById('agentForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
// Show processing status
showProcessing();
fetch('', {
method: 'POST',
body: formData,
headers: {
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
pollStatus(data.request_id);
} else {
hideProcessing();
showToast(data.error || 'Request failed', 'error');
}
})
.catch(error => {
hideProcessing();
showToast('Network error occurred', 'error');
});
});
// Status polling
function pollStatus(requestId) {
const poll = setInterval(() => {
fetch(`status/${requestId}/`)
.then(response => response.json())
.then(data => {
if (data.status === 'completed') {
clearInterval(poll);
hideProcessing();
displayResults(data.result);
} else if (data.status === 'failed') {
clearInterval(poll);
hideProcessing();
showToast('Processing failed', 'error');
}
});
}, 2000);
}
// Display results
function displayResults(result) {
document.getElementById('resultsContent').textContent = result;
document.getElementById('resultsSection').style.display = 'block';
showToast('Results ready!', 'success');
}
```
## Toast Messaging Standards
### Standardized Toast Messages
All agents must follow these standardized toast message patterns for consistency:
#### Success Messages
```javascript
// Agent completion - use specific agent action
AgentUtils.showToast('✅ Data analysis completed successfully!', 'success');
AgentUtils.showToast('✅ Weather report completed successfully!', 'success');
AgentUtils.showToast('✅ Email completed successfully!', 'success');
```
#### Clipboard Operations
```javascript
// Always use this exact message for clipboard operations
navigator.clipboard.writeText(text).then(() => {
AgentUtils.showToast('📋 Copied to clipboard!', 'success');
}).catch(() => {
AgentUtils.showToast('❌ Failed to copy to clipboard', 'error');
});
```
#### Error Messages
```javascript
// Use ❌ emoji prefix for all error messages
AgentUtils.showToast('❌ Network error occurred', 'error');
AgentUtils.showToast('❌ Insufficient wallet balance', 'error');
AgentUtils.showToast('❌ Processing failed', 'error');
```
#### No Toast Scenarios
Do NOT show toast messages for:
- **Download operations** - File download is confirmation enough
- **Reset operations** - Visual feedback is sufficient
- **Form validation** - Use inline error messages instead
### Toast Function Naming
Each agent should maintain its own utils object with a `showToast` method:
```javascript
// Data Analyzer
const DataAnalyzerUtils = {
showToast(message, type = 'info') { /* standard implementation */ }
};
// Social Ads Generator
const SocialAdsUtils = {
showToast(message, type = 'info') { /* standard implementation */ }
};
// Weather Reporter
const WeatherUtils = {
showToast(message, type = 'info') { /* standard implementation */ }
};
```
## Dynamic Pricing Implementation
### Template Variables
All pricing must use dynamic template variables instead of hardcoded values:
#### Button Text
```html
<!-- CORRECT -->
<button type="submit" class="btn btn-primary btn-full">
🚀 Analyze Data ({{ agent.price }} AED)
</button>
<!-- INCORRECT -->
<button type="submit" class="btn btn-primary btn-full">
🚀 Analyze Data (5.00 AED)
</button>
```
#### Balance Validation
```html
<!-- CORRECT -->
{% if user.wallet_balance >= agent.price %}
<button>Process Request</button>
{% else %}
<div class="alert alert-error">
Insufficient balance! You need {{ agent.price }} AED.
</div>
{% endif %}
<!-- INCORRECT -->
{% if user.wallet_balance >= 5.00 %}
```
#### JavaScript Price Checks
```javascript
// CORRECT - Use template variable
document.body.setAttribute('data-agent-price', '{{ agent.price }}');
const agentPrice = parseFloat(document.body.getAttribute('data-agent-price'));
if (walletBalance < agentPrice) {
showToast('Insufficient wallet balance', 'error');
}
// INCORRECT - Hardcoded value
if (walletBalance < 5.00) {
```
### Agent Context Required
Ensure your view passes the agent context:
```python
# views.py
from agent_base.models import BaseAgent
def your_agent_detail(request):
try:
agent = BaseAgent.objects.get(slug='your-agent-slug')
except BaseAgent.DoesNotExist:
# Handle missing agent
pass
context = {
'agent': agent, # Required for {{ agent.price }}
# other context...
}
return render(request, 'your_agent/detail.html', context)
```
## Best Practices for Agent Modifications
### Preserving Existing Functionality
When updating agents, follow these critical guidelines:
#### DO NOT Break Result Display Logic
```javascript
// CORRECT - Preserve agent-specific utils and function names
const DataAnalyzerUtils = {
displayResults(result) { /* existing logic */ }
};
// INCORRECT - Don't change to generic names
const AgentUtils = {
displayResults(result) { /* breaks existing calls */ }
};
```
#### Each Agent Has Unique Display Patterns
Different agents handle results differently:
- **Data Analyzer**: Formatted HTML output with sections
- **Weather Reporter**: Text-based reports with immediate API response
- **Social Ads**: Multiple ad variants with copy/download options
- **Email Writer**: Rich text formatting with email structure
**Never standardize result display logic across agents.**
#### Safe Modification Approach
1. **Test Before Changes**: Always verify current functionality works
2. **Isolated Updates**: Change only what's explicitly requested
3. **Preserve Names**: Keep existing function and object names
4. **Incremental Testing**: Test after each small change
### Common Pitfalls to Avoid
#### Over-Standardization
```javascript
// WRONG - Don't rename existing functions
// Before: DataAnalyzerUtils.displayResults()
// After: AgentUtils.displayResults() // BREAKS FUNCTIONALITY
// CORRECT - Keep existing structure, update content only
// Before: showToast('Data copied!', 'success');
// After: showToast('📋 Copied to clipboard!', 'success');
```
#### Breaking Function Calls
```javascript
// WRONG - Changing function names breaks templates
SocialAdsUtils.displayResults() AgentUtils.displayResults()
// CORRECT - Preserve all function names and calling patterns
SocialAdsUtils.displayResults() SocialAdsUtils.displayResults()
```
#### Git Recovery When Things Break
If agent functionality breaks:
```bash
# Check what changed
git status
git diff
# Reset to last working commit
git log --oneline -10
git reset --hard <commit-hash>
# Verify functionality restored
python manage.py runserver
# Test affected agents manually
```
## URL Configuration
### App URLs (`your_agent/urls.py`)
```python
from django.urls import path
from . import views
app_name = 'your_agent'
urlpatterns = [
path('', views.your_agent_detail, name='detail'),
path('status/<uuid:request_id>/', views.your_agent_status, name='status'),
]
```
### Main URLs (add to `netcop_hub/urls.py`)
```python
path('agents/your-agent-slug/', include('your_agent.urls')),
```
### Settings (add to `INSTALLED_APPS`)
```python
INSTALLED_APPS = [
# ... existing apps
'your_agent',
]
```
## Database and Marketplace Integration
### 1. Create and Apply Migrations
```bash
python manage.py makemigrations your_agent
python manage.py migrate
```
### 2. Add to Marketplace Catalog
```bash
python manage.py shell
```
```python
from agent_base.models import BaseAgent
BaseAgent.objects.create(
name="Your Agent Name",
slug="your-agent-slug",
description="Description of what your agent does...",
category="content", # or appropriate category
price=3.00,
icon="🎯", # appropriate emoji
agent_type="webhook"
)
```
## Common Components Reference
### Available CSS Components
- **Layout**: `.agent-container`, `.agent-header`, `.agent-grid`
- **Widgets**: `.agent-widget`, `.widget-header`, `.widget-title`, `.widget-content`
- **Sizes**: `.widget-large`, `.widget-small`, `.widget-wide`
- **Wallet**: `.wallet-card` (use `{% include 'components/wallet_card.html' %}`)
- **Status**: `.processing-status`, `.status-icon`, `.status-title`
- **Utilities**: `.info-list`, `.placeholder-section`
### Available JavaScript Functions
- `showToast(message, type)` - Display notifications
- `showProcessing()` / `hideProcessing()` - Processing status
- `copyToClipboard(text, message)` - Copy functionality
- `downloadAsFile(text, filename, message)` - Download functionality
- `toggleQuickAgents()` - Quick access panel
- `updateWalletBalance(balance)` - Update wallet display
## Testing and Verification
### 1. Django Check
```bash
python manage.py check
```
### 2. URL Resolution Test
```bash
python manage.py shell
```
```python
from django.urls import reverse
print(reverse('your_agent:detail'))
```
### 3. Agent Marketplace Test
Visit `/marketplace/` to verify your agent appears in the catalog.
## Best Practices
1. **Always inherit CSS and JavaScript** from the prototype - don't modify the template utilities
2. **Use consistent naming** - follow the existing patterns for models, views, and URLs
3. **Preserve accessibility** - keep ARIA attributes and keyboard navigation
4. **Test responsive design** - verify mobile functionality
5. **Follow security practices** - use CSRF tokens, validate inputs, check permissions
6. **Maintain consistent pricing** - use decimal values with 2 places
7. **Handle errors gracefully** - provide meaningful error messages via toast notifications
8. **Preserve existing functionality** - Never break result display logic when making updates
9. **Test after each change** - Verify functionality works before proceeding to next modification
10. **Use git for safety** - Commit working states and reset if changes break functionality
## Testing Procedures for Agent Modifications
### Pre-Modification Testing
```bash
# 1. Test current functionality
python manage.py runserver
# Visit agent page and test full workflow
# 2. Create git checkpoint
git add .
git commit -m "Working state before modifications"
```
### During Modification Testing
```bash
# Test after each significant change
python manage.py runserver
# Test the specific functionality you modified
# If something breaks:
git status
git diff
# Identify the breaking change and fix or revert
```
### Post-Modification Testing
```bash
# 1. Full agent workflow test
# - Form submission
# - Processing status display
# - Results display
# - Copy/download functionality
# 2. Cross-agent functionality test
# - Quick agents panel
# - Navigation between agents
# - Wallet balance updates
# 3. Browser console check
# - No JavaScript errors
# - No broken network requests
```
## Troubleshooting
### Common Issues
1. **CSS not loading**: Ensure all CSS from prototype is copied within `<style>` tags
2. **JavaScript errors**: Check that all utility functions are included
3. **Form submission fails**: Verify CSRF token and POST data validation
4. **Agent not in marketplace**: Check BaseAgent database entry and migrations
5. **Template not found**: Verify template directory structure matches app name
### Debug Commands
```bash
# Check database
python manage.py check_db
# Shell debugging
python manage.py shell
# View agent catalog
python manage.py shell
>>> from agent_base.models import BaseAgent
>>> BaseAgent.objects.all()
```
This guide ensures consistent, maintainable agent creation using the proven template prototype system.
## Recent Improvements (July 2025)
### ✅ Toast Messaging Standardization
All agents now use consistent toast messages:
- **Success**: `✅ [Action] completed successfully!`
- **Clipboard**: `📋 Copied to clipboard!`
- **Errors**: `❌ [Error description]`
- **Removed**: Download and reset toast notifications (visual feedback sufficient)
### ✅ Dynamic Pricing Implementation
All agents now use `{{ agent.price }}` template variables instead of hardcoded prices:
- Button text: `Process Request ({{ agent.price }} AED)`
- Balance validation: `{% if user.wallet_balance >= agent.price %}`
- JavaScript checks: `data-agent-price="{{ agent.price }}"`
### ✅ Enhanced Agent Template Architecture
- Improved component-based template structure
- Standardized CSS and JavaScript utilities
- Better security with XSS prevention
- Consistent wallet balance integration
These improvements ensure all agents maintain consistent user experience while syncing with Railway database pricing changes.