|
|
""" |
|
|
Module: api.routes.agents |
|
|
Description: Direct agent endpoints for specialized AI agents |
|
|
Author: Anderson H. Silva |
|
|
Date: 2025-09-25 |
|
|
License: Proprietary - All rights reserved |
|
|
""" |
|
|
|
|
|
from typing import Dict, Any, Optional |
|
|
from fastapi import APIRouter, HTTPException, Depends, BackgroundTasks |
|
|
from pydantic import BaseModel, Field |
|
|
|
|
|
from src.core import get_logger |
|
|
from src.api.middleware.authentication import get_current_user |
|
|
from src.api.auth import User |
|
|
from src.infrastructure.rate_limiter import RateLimitTier |
|
|
|
|
|
|
|
|
async def get_rate_limit_tier() -> RateLimitTier: |
|
|
"""Get rate limit tier for current user.""" |
|
|
return RateLimitTier.BASIC |
|
|
from src.agents import ZumbiAgent, AnitaAgent, TiradentesAgent, BonifacioAgent, AgentContext |
|
|
from src.infrastructure.observability.metrics import track_time, count_calls |
|
|
|
|
|
|
|
|
logger = get_logger(__name__) |
|
|
router = APIRouter() |
|
|
|
|
|
|
|
|
class AgentRequest(BaseModel): |
|
|
"""Base request model for agent operations.""" |
|
|
query: str = Field(..., description="Query or input for the agent") |
|
|
context: Dict[str, Any] = Field(default_factory=dict, description="Additional context") |
|
|
options: Dict[str, Any] = Field(default_factory=dict, description="Agent-specific options") |
|
|
|
|
|
|
|
|
class AgentResponse(BaseModel): |
|
|
"""Base response model for agent operations.""" |
|
|
agent: str = Field(..., description="Agent name") |
|
|
result: Dict[str, Any] = Field(..., description="Agent processing result") |
|
|
metadata: Dict[str, Any] = Field(default_factory=dict, description="Processing metadata") |
|
|
success: bool = Field(default=True, description="Operation success status") |
|
|
message: Optional[str] = Field(None, description="Optional status message") |
|
|
|
|
|
|
|
|
@router.post("/zumbi", response_model=AgentResponse) |
|
|
@track_time("agent_zumbi_process") |
|
|
@count_calls("agent_zumbi_requests") |
|
|
async def process_zumbi_request( |
|
|
request: AgentRequest, |
|
|
background_tasks: BackgroundTasks, |
|
|
current_user: User = Depends(get_current_user), |
|
|
rate_limit_tier: RateLimitTier = Depends(get_rate_limit_tier) |
|
|
): |
|
|
""" |
|
|
Process request with Zumbi dos Palmares agent. |
|
|
|
|
|
Zumbi specializes in anomaly detection and investigation: |
|
|
- Price anomalies and overpricing |
|
|
- Vendor concentration and cartels |
|
|
- Temporal pattern irregularities |
|
|
- Contract duplication |
|
|
- Payment irregularities |
|
|
""" |
|
|
try: |
|
|
|
|
|
context = AgentContext( |
|
|
user_id=current_user.id if current_user else "anonymous", |
|
|
session_id=str(request.context.get("session_id", "default")), |
|
|
request_id=str(request.context.get("request_id", "unknown")), |
|
|
metadata={ |
|
|
"rate_limit_tier": rate_limit_tier.value, |
|
|
**request.context |
|
|
} |
|
|
) |
|
|
|
|
|
|
|
|
zumbi = ZumbiAgent() |
|
|
|
|
|
|
|
|
result = await zumbi.process( |
|
|
message=request.query, |
|
|
context=context, |
|
|
**request.options |
|
|
) |
|
|
|
|
|
return AgentResponse( |
|
|
agent="zumbi_dos_palmares", |
|
|
result=result.data if hasattr(result, 'data') else {"analysis": str(result)}, |
|
|
metadata={ |
|
|
"processing_time": result.metadata.get("processing_time", 0) if hasattr(result, 'metadata') else 0, |
|
|
"anomalies_detected": result.metadata.get("anomalies_detected", 0) if hasattr(result, 'metadata') else 0, |
|
|
}, |
|
|
success=True, |
|
|
message="Anomaly detection completed successfully" |
|
|
) |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Zumbi agent error: {str(e)}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Zumbi agent processing failed: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.post("/anita", response_model=AgentResponse) |
|
|
@track_time("agent_anita_process") |
|
|
@count_calls("agent_anita_requests") |
|
|
async def process_anita_request( |
|
|
request: AgentRequest, |
|
|
background_tasks: BackgroundTasks, |
|
|
current_user: User = Depends(get_current_user), |
|
|
rate_limit_tier: RateLimitTier = Depends(get_rate_limit_tier) |
|
|
): |
|
|
""" |
|
|
Process request with Anita Garibaldi agent. |
|
|
|
|
|
Anita specializes in pattern analysis and correlation: |
|
|
- Spending trends and patterns |
|
|
- Organizational behavior analysis |
|
|
- Vendor relationship mapping |
|
|
- Seasonal pattern detection |
|
|
- Efficiency metrics calculation |
|
|
""" |
|
|
try: |
|
|
|
|
|
context = AgentContext( |
|
|
user_id=current_user.id if current_user else "anonymous", |
|
|
session_id=str(request.context.get("session_id", "default")), |
|
|
request_id=str(request.context.get("request_id", "unknown")), |
|
|
metadata={ |
|
|
"rate_limit_tier": rate_limit_tier.value, |
|
|
**request.context |
|
|
} |
|
|
) |
|
|
|
|
|
|
|
|
anita = AnitaAgent() |
|
|
|
|
|
|
|
|
result = await anita.process( |
|
|
message=request.query, |
|
|
context=context, |
|
|
**request.options |
|
|
) |
|
|
|
|
|
return AgentResponse( |
|
|
agent="anita_garibaldi", |
|
|
result=result.data if hasattr(result, 'data') else {"analysis": str(result)}, |
|
|
metadata={ |
|
|
"processing_time": result.metadata.get("processing_time", 0) if hasattr(result, 'metadata') else 0, |
|
|
"patterns_found": result.metadata.get("patterns_found", 0) if hasattr(result, 'metadata') else 0, |
|
|
}, |
|
|
success=True, |
|
|
message="Pattern analysis completed successfully" |
|
|
) |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Anita agent error: {str(e)}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Anita agent processing failed: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.post("/tiradentes", response_model=AgentResponse) |
|
|
@track_time("agent_tiradentes_process") |
|
|
@count_calls("agent_tiradentes_requests") |
|
|
async def process_tiradentes_request( |
|
|
request: AgentRequest, |
|
|
background_tasks: BackgroundTasks, |
|
|
current_user: User = Depends(get_current_user), |
|
|
rate_limit_tier: RateLimitTier = Depends(get_rate_limit_tier) |
|
|
): |
|
|
""" |
|
|
Process request with Tiradentes agent. |
|
|
|
|
|
Tiradentes specializes in report generation: |
|
|
- Executive summaries |
|
|
- Detailed investigation reports |
|
|
- Multi-format output (JSON, Markdown, HTML) |
|
|
- Natural language explanations |
|
|
- Actionable recommendations |
|
|
""" |
|
|
try: |
|
|
|
|
|
context = AgentContext( |
|
|
user_id=current_user.id if current_user else "anonymous", |
|
|
session_id=str(request.context.get("session_id", "default")), |
|
|
request_id=str(request.context.get("request_id", "unknown")), |
|
|
metadata={ |
|
|
"rate_limit_tier": rate_limit_tier.value, |
|
|
**request.context |
|
|
} |
|
|
) |
|
|
|
|
|
|
|
|
tiradentes = TiradentesAgent() |
|
|
|
|
|
|
|
|
result = await tiradentes.process( |
|
|
message=request.query, |
|
|
context=context, |
|
|
**request.options |
|
|
) |
|
|
|
|
|
return AgentResponse( |
|
|
agent="tiradentes", |
|
|
result=result.data if hasattr(result, 'data') else {"report": str(result)}, |
|
|
metadata={ |
|
|
"processing_time": result.metadata.get("processing_time", 0) if hasattr(result, 'metadata') else 0, |
|
|
"report_format": request.options.get("format", "markdown"), |
|
|
}, |
|
|
success=True, |
|
|
message="Report generation completed successfully" |
|
|
) |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Tiradentes agent error: {str(e)}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Tiradentes agent processing failed: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.post("/bonifacio", response_model=AgentResponse) |
|
|
@track_time("agent_bonifacio_process") |
|
|
@count_calls("agent_bonifacio_requests") |
|
|
async def process_bonifacio_request( |
|
|
request: AgentRequest, |
|
|
background_tasks: BackgroundTasks, |
|
|
current_user: User = Depends(get_current_user), |
|
|
rate_limit_tier: RateLimitTier = Depends(get_rate_limit_tier) |
|
|
): |
|
|
""" |
|
|
Process request with José Bonifácio agent. |
|
|
|
|
|
Bonifácio specializes in legal and compliance analysis: |
|
|
- Legal framework verification |
|
|
- Compliance assessment |
|
|
- Regulatory requirement checking |
|
|
- Constitutional alignment analysis |
|
|
- Legal risk identification |
|
|
- Jurisprudence application |
|
|
""" |
|
|
try: |
|
|
|
|
|
context = AgentContext( |
|
|
user_id=current_user.id if current_user else "anonymous", |
|
|
session_id=str(request.context.get("session_id", "default")), |
|
|
request_id=str(request.context.get("request_id", "unknown")), |
|
|
metadata={ |
|
|
"rate_limit_tier": rate_limit_tier.value, |
|
|
**request.context |
|
|
} |
|
|
) |
|
|
|
|
|
|
|
|
bonifacio = BonifacioAgent() |
|
|
|
|
|
|
|
|
result = await bonifacio.process( |
|
|
message=request.query, |
|
|
context=context, |
|
|
**request.options |
|
|
) |
|
|
|
|
|
return AgentResponse( |
|
|
agent="jose_bonifacio", |
|
|
result=result.data if hasattr(result, 'data') else {"analysis": str(result)}, |
|
|
metadata={ |
|
|
"processing_time": result.metadata.get("processing_time", 0) if hasattr(result, 'metadata') else 0, |
|
|
"compliance_issues": result.metadata.get("compliance_issues", 0) if hasattr(result, 'metadata') else 0, |
|
|
"legal_risks": result.metadata.get("legal_risks", []) if hasattr(result, 'metadata') else [], |
|
|
}, |
|
|
success=True, |
|
|
message="Legal and compliance analysis completed successfully" |
|
|
) |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Bonifacio agent error: {str(e)}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Bonifacio agent processing failed: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.post("/maria-quiteria", response_model=AgentResponse) |
|
|
@track_time("agent_maria_quiteria_process") |
|
|
@count_calls("agent_maria_quiteria_requests") |
|
|
async def process_maria_quiteria_request( |
|
|
request: AgentRequest, |
|
|
background_tasks: BackgroundTasks, |
|
|
current_user: User = Depends(get_current_user), |
|
|
rate_limit_tier: RateLimitTier = Depends(get_rate_limit_tier) |
|
|
): |
|
|
""" |
|
|
Process request with Maria Quitéria agent. |
|
|
|
|
|
Maria Quitéria specializes in security auditing and system protection: |
|
|
- Security threat detection |
|
|
- Vulnerability assessment |
|
|
- Compliance verification (LGPD, ISO27001, etc.) |
|
|
- Intrusion detection |
|
|
- Digital forensics |
|
|
- Risk assessment |
|
|
- Security monitoring |
|
|
""" |
|
|
try: |
|
|
|
|
|
context = AgentContext( |
|
|
user_id=current_user.id if current_user else "anonymous", |
|
|
session_id=str(uuid4()), |
|
|
investigation_id=request.metadata.get("investigation_id", str(uuid4())) |
|
|
) |
|
|
|
|
|
|
|
|
from src.agents import MariaQuiteriaAgent |
|
|
maria_quiteria = MariaQuiteriaAgent() |
|
|
|
|
|
|
|
|
result = await maria_quiteria.process( |
|
|
message=request.query, |
|
|
context=context, |
|
|
**request.options |
|
|
) |
|
|
|
|
|
return AgentResponse( |
|
|
agent="maria_quiteria", |
|
|
result=result.data if hasattr(result, 'data') else {"analysis": str(result)}, |
|
|
metadata={ |
|
|
"processing_time": result.metadata.get("processing_time", 0) if hasattr(result, 'metadata') else 0, |
|
|
"threats_detected": result.metadata.get("threats_detected", 0) if hasattr(result, 'metadata') else 0, |
|
|
"security_score": result.metadata.get("security_score", 0) if hasattr(result, 'metadata') else 0, |
|
|
}, |
|
|
success=True, |
|
|
message="Security audit completed successfully" |
|
|
) |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Maria Quiteria agent error: {str(e)}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Maria Quiteria agent processing failed: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.get("/status") |
|
|
async def get_agents_status( |
|
|
current_user: User = Depends(get_current_user) |
|
|
): |
|
|
"""Get status of all available agents.""" |
|
|
agents = { |
|
|
"zumbi_dos_palmares": { |
|
|
"name": "Zumbi dos Palmares", |
|
|
"role": "Anomaly Detection Specialist", |
|
|
"status": "active", |
|
|
"capabilities": [ |
|
|
"Price anomaly detection", |
|
|
"Vendor concentration analysis", |
|
|
"Temporal pattern recognition", |
|
|
"Contract duplication detection", |
|
|
"Payment irregularity identification" |
|
|
] |
|
|
}, |
|
|
"anita_garibaldi": { |
|
|
"name": "Anita Garibaldi", |
|
|
"role": "Pattern Analysis Specialist", |
|
|
"status": "active", |
|
|
"capabilities": [ |
|
|
"Spending trend analysis", |
|
|
"Organizational behavior mapping", |
|
|
"Vendor relationship analysis", |
|
|
"Seasonal pattern detection", |
|
|
"Efficiency metrics calculation" |
|
|
] |
|
|
}, |
|
|
"tiradentes": { |
|
|
"name": "Tiradentes", |
|
|
"role": "Report Generation Specialist", |
|
|
"status": "active", |
|
|
"capabilities": [ |
|
|
"Executive summary generation", |
|
|
"Detailed investigation reports", |
|
|
"Multi-format output", |
|
|
"Natural language explanations", |
|
|
"Actionable recommendations" |
|
|
] |
|
|
}, |
|
|
"jose_bonifacio": { |
|
|
"name": "José Bonifácio", |
|
|
"role": "Legal & Compliance Specialist", |
|
|
"status": "active", |
|
|
"capabilities": [ |
|
|
"Legal framework verification", |
|
|
"Compliance assessment", |
|
|
"Regulatory requirement checking", |
|
|
"Constitutional alignment analysis", |
|
|
"Legal risk identification" |
|
|
] |
|
|
}, |
|
|
"maria_quiteria": { |
|
|
"name": "Maria Quitéria", |
|
|
"role": "Security Auditor & System Guardian", |
|
|
"status": "active", |
|
|
"capabilities": [ |
|
|
"Security threat detection", |
|
|
"Vulnerability assessment", |
|
|
"Compliance verification (LGPD, ISO27001)", |
|
|
"Intrusion detection", |
|
|
"Digital forensics", |
|
|
"Risk assessment" |
|
|
] |
|
|
} |
|
|
} |
|
|
|
|
|
return { |
|
|
"agents": agents, |
|
|
"total_active": sum(1 for a in agents.values() if a["status"] == "active"), |
|
|
"timestamp": "2025-09-25T14:30:00Z" |
|
|
} |
|
|
|
|
|
|
|
|
@router.get("/") |
|
|
async def list_agents(): |
|
|
"""List all available agents with their endpoints.""" |
|
|
return { |
|
|
"message": "Cidadão.AI Agent System", |
|
|
"version": "2.0.0", |
|
|
"agents": [ |
|
|
{ |
|
|
"name": "Zumbi dos Palmares", |
|
|
"endpoint": "/api/v1/agents/zumbi", |
|
|
"description": "Anomaly detection and investigation specialist" |
|
|
}, |
|
|
{ |
|
|
"name": "Anita Garibaldi", |
|
|
"endpoint": "/api/v1/agents/anita", |
|
|
"description": "Pattern analysis and correlation specialist" |
|
|
}, |
|
|
{ |
|
|
"name": "Tiradentes", |
|
|
"endpoint": "/api/v1/agents/tiradentes", |
|
|
"description": "Report generation and natural language specialist" |
|
|
}, |
|
|
{ |
|
|
"name": "José Bonifácio", |
|
|
"endpoint": "/api/v1/agents/bonifacio", |
|
|
"description": "Legal and compliance analysis specialist" |
|
|
}, |
|
|
{ |
|
|
"name": "Maria Quitéria", |
|
|
"endpoint": "/api/v1/agents/maria-quiteria", |
|
|
"description": "Security auditing and system protection specialist" |
|
|
} |
|
|
] |
|
|
} |