Add autonomous compliance agent that fetches web documents (cookie banners, privacy policies), classifies them via Qwen/Ollama, assesses DSGVO compliance, assigns to the responsible role, and sends notification emails. Components: - ZeroClaw SOP (6-step workflow: fetch, classify, assess, summarize, assign, notify) - Backend: /api/compliance/agent/analyze (combined endpoint) - Backend: /api/compliance/agent/notify (standalone email) - Frontend: /sdk/agent page (Manager UI with URL input + results) - Helper scripts + E2E test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
78 lines
2.3 KiB
Python
78 lines
2.3 KiB
Python
"""
|
|
Agent Notification Routes — endpoint for the ZeroClaw compliance agent
|
|
to send notification emails via SMTP.
|
|
|
|
POST /api/compliance/agent/notify
|
|
"""
|
|
|
|
import logging
|
|
from datetime import datetime, timezone
|
|
|
|
from fastapi import APIRouter
|
|
from pydantic import BaseModel, EmailStr
|
|
|
|
from compliance.services.smtp_sender import send_email
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(prefix="/compliance/agent", tags=["agent"])
|
|
|
|
|
|
class NotifyRequest(BaseModel):
|
|
recipient: EmailStr
|
|
subject: str
|
|
body_html: str
|
|
role: str
|
|
escalation_id: str | None = None
|
|
|
|
|
|
class NotifyResponse(BaseModel):
|
|
status: str
|
|
recipient: str
|
|
subject: str
|
|
role: str
|
|
sent_at: str
|
|
error: str | None = None
|
|
|
|
|
|
@router.post("/notify", response_model=NotifyResponse)
|
|
async def send_agent_notification(req: NotifyRequest):
|
|
"""Send a compliance notification email on behalf of the agent."""
|
|
result = send_email(
|
|
recipient=req.recipient,
|
|
subject=req.subject,
|
|
body_html=_build_email_body(req),
|
|
)
|
|
|
|
return NotifyResponse(
|
|
status=result["status"],
|
|
recipient=req.recipient,
|
|
subject=req.subject,
|
|
role=req.role,
|
|
sent_at=datetime.now(timezone.utc).isoformat(),
|
|
error=result.get("error"),
|
|
)
|
|
|
|
|
|
def _build_email_body(req: NotifyRequest) -> str:
|
|
"""Wrap the agent's HTML body with a standard email frame."""
|
|
return f"""
|
|
<div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; max-width: 600px; margin: 0 auto;">
|
|
<div style="background: #1a1a2e; color: white; padding: 16px 24px; border-radius: 8px 8px 0 0;">
|
|
<h2 style="margin: 0; font-size: 18px;">BreakPilot Compliance Agent</h2>
|
|
</div>
|
|
<div style="padding: 24px; border: 1px solid #e2e8f0; border-top: none;">
|
|
<p style="color: #64748b; font-size: 13px; margin-top: 0;">
|
|
Zugewiesen an: <strong>{req.role}</strong>
|
|
{f' | Eskalation: {req.escalation_id}' if req.escalation_id else ''}
|
|
</p>
|
|
{req.body_html}
|
|
</div>
|
|
<div style="background: #f8fafc; padding: 12px 24px; border: 1px solid #e2e8f0; border-top: none; border-radius: 0 0 8px 8px;">
|
|
<p style="color: #94a3b8; font-size: 11px; margin: 0;">
|
|
Automatisch generiert vom BreakPilot Compliance Agent (ZeroClaw + Qwen)
|
|
</p>
|
|
</div>
|
|
</div>
|
|
"""
|