diff --git a/backend/app/agents/brand_agent.py b/backend/app/agents/brand_agent.py index 0827e05..df32eb0 100755 --- a/backend/app/agents/brand_agent.py +++ b/backend/app/agents/brand_agent.py @@ -71,6 +71,9 @@ Your response MUST include: images: List[Tuple[bytes, str]], previous_review: Optional[PreviousReviewContext] = None, brand: str = "Barclaycard", + channel: Optional[str] = None, + sub_channel: Optional[str] = None, + proof_type: Optional[str] = None, ) -> SubReview: """ Analyze the proof for brand guideline adherence. @@ -79,6 +82,9 @@ Your response MUST include: images: List of (file_data, mime_type) tuples representing the proof previous_review: Optional context from previous version for revision-aware analysis brand: Brand to analyze against ('Barclays' or 'Barclaycard') + channel: Target channel (e.g. "Social", "Digital") + sub_channel: Target sub-channel (e.g. "Meta", "Google") + proof_type: Proof format type (e.g. "In-feed 1x1", "Banner") Returns: SubReview with brand compliance assessment @@ -99,6 +105,14 @@ Here is the {brand} brand specification to use for your analysis: {revision_context} --- +**PROOF METADATA** +- Channel: {channel or "Not specified"} +- Sub-Channel: {sub_channel or "Not specified"} +- Proof Type: {proof_type or "Not specified"} + +Use this metadata to focus your analysis on the specific brand requirements for this channel and format. +--- + Analyze the uploaded proof against the {brand} brand specification above, checking for: 1. **Logo Usage**: Is the {brand} logo used correctly? Check minimum size, clear space, placement, and that it hasn't been altered. Verify correct logo colors per guidelines. diff --git a/backend/app/agents/channel_best_practices_agent.py b/backend/app/agents/channel_best_practices_agent.py index 67237de..0417d53 100644 --- a/backend/app/agents/channel_best_practices_agent.py +++ b/backend/app/agents/channel_best_practices_agent.py @@ -54,6 +54,9 @@ Your response MUST include: self, images: List[Tuple[bytes, str]], previous_review: Optional[PreviousReviewContext] = None, + channel: Optional[str] = None, + sub_channel: Optional[str] = None, + proof_type: Optional[str] = None, ) -> SubReview: """ Analyze the proof for channel best practices and content strategy. @@ -61,6 +64,9 @@ Your response MUST include: Args: images: List of (file_data, mime_type) tuples representing the proof previous_review: Optional context from previous version for revision-aware analysis + channel: Target channel (e.g. "Social", "Digital") + sub_channel: Target sub-channel (e.g. "Meta", "Google") + proof_type: Proof format type (e.g. "In-feed 1x1", "Banner") Returns: SubReview with channel best practices assessment @@ -81,6 +87,14 @@ Here are the channel best practices guidelines to use for your analysis: {revision_context} --- +**PROOF METADATA** +- Channel: {channel or "Not specified"} +- Sub-Channel: {sub_channel or "Not specified"} +- Proof Type: {proof_type or "Not specified"} + +Use this metadata to focus your analysis on the specific best practices for this channel and format. +--- + Analyze the uploaded proof for adherence to channel best practices, checking: 1. **Content Strategy**: diff --git a/backend/app/agents/channel_tech_specs_agent.py b/backend/app/agents/channel_tech_specs_agent.py index 4da7b29..ca1372d 100644 --- a/backend/app/agents/channel_tech_specs_agent.py +++ b/backend/app/agents/channel_tech_specs_agent.py @@ -54,6 +54,9 @@ Your response MUST include: self, images: List[Tuple[bytes, str]], previous_review: Optional[PreviousReviewContext] = None, + channel: Optional[str] = None, + sub_channel: Optional[str] = None, + proof_type: Optional[str] = None, ) -> SubReview: """ Analyze the proof for technical specifications compliance. @@ -61,6 +64,9 @@ Your response MUST include: Args: images: List of (file_data, mime_type) tuples representing the proof previous_review: Optional context from previous version for revision-aware analysis + channel: Target channel (e.g. "Social", "Digital") + sub_channel: Target sub-channel (e.g. "Meta", "Google") + proof_type: Proof format type (e.g. "In-feed 1x1", "Banner") Returns: SubReview with technical specifications assessment @@ -81,6 +87,14 @@ Here are the channel technical specifications to use for your analysis: {revision_context} --- +**PROOF METADATA** +- Channel: {channel or "Not specified"} +- Sub-Channel: {sub_channel or "Not specified"} +- Proof Type: {proof_type or "Not specified"} + +Use this metadata to focus your analysis on the specific technical specifications for this channel and format. +--- + Analyze the uploaded proof for technical specification compliance, checking: 1. **Dimensions & Resolution**: diff --git a/backend/app/agents/lead_agent.py b/backend/app/agents/lead_agent.py index c317de1..df51e61 100755 --- a/backend/app/agents/lead_agent.py +++ b/backend/app/agents/lead_agent.py @@ -76,6 +76,9 @@ In your summary: self, reviews: dict[str, SubReview], previous_analysis: Optional[dict] = None, + channel: Optional[str] = None, + sub_channel: Optional[str] = None, + proof_type: Optional[str] = None, ) -> tuple[OverallStatus, str, str | None]: """ Synthesize specialist reviews into final verdict and summary. @@ -84,6 +87,9 @@ In your summary: reviews: Dictionary mapping agent names to their SubReview results previous_analysis: Optional dict containing the previous version's analysis results. When provided, enables revision-aware summary. + channel: Target channel (e.g. "Social", "Digital") + sub_channel: Target sub-channel (e.g. "Meta", "Google") + proof_type: Proof format type (e.g. "In-feed 1x1", "Banner") Returns: Tuple of (overall_status, summary, financial_promotion_reason) @@ -106,11 +112,21 @@ In your summary: if previous_analysis and previous_analysis.get("version"): revision_context = self._build_revision_context(previous_analysis, reviews) + # Build proof metadata context + metadata_context = f""" +**PROOF METADATA** +- Channel: {channel or "Not specified"} +- Sub-Channel: {sub_channel or "Not specified"} +- Proof Type: {proof_type or "Not specified"} +""" + # Build the prompt for Gemini to generate summary prompt = f""" You are a Lead Agent responsible for auditing a marketing proof. You have received feedback from specialist AI agents. Your task is to provide a final verdict and write a concise, professional summary to the user. +{metadata_context} + Here is the logic you must follow: 1. The Legal Agent has determined if this is a financial promotion: {is_financial_promotion}. 2. If it IS a financial promotion, the final verdict MUST be 'Requires Manual Legal Review'. Your summary should state this clearly, explain that a separate manual legal review is required, and then summarize any other issues found by the other agents. diff --git a/backend/app/agents/legal_agent.py b/backend/app/agents/legal_agent.py index 65f46e5..d34cbc5 100755 --- a/backend/app/agents/legal_agent.py +++ b/backend/app/agents/legal_agent.py @@ -54,6 +54,9 @@ Your response MUST include: self, images: List[Tuple[bytes, str]], previous_review: Optional[PreviousReviewContext] = None, + channel: Optional[str] = None, + sub_channel: Optional[str] = None, + proof_type: Optional[str] = None, ) -> SubReview: """ Analyze the proof for legal compliance. @@ -61,6 +64,9 @@ Your response MUST include: Args: images: List of (file_data, mime_type) tuples representing the proof previous_review: Optional context from previous version for revision-aware analysis + channel: Target channel (e.g. "Social", "Digital") + sub_channel: Target sub-channel (e.g. "Meta", "Google") + proof_type: Proof format type (e.g. "In-feed 1x1", "Banner") Returns: SubReview with legal compliance assessment @@ -81,6 +87,14 @@ Here are the legal guidelines to use for your analysis: {revision_context} --- +**PROOF METADATA** +- Channel: {channel or "Not specified"} +- Sub-Channel: {sub_channel or "Not specified"} +- Proof Type: {proof_type or "Not specified"} + +Use this metadata to focus your analysis on the specific legal requirements for this channel and format. +--- + Analyze the uploaded proof for legal compliance, checking: 1. **Financial Promotion Detection**: diff --git a/backend/app/services/analysis_service.py b/backend/app/services/analysis_service.py index 95d2ddf..6a6e595 100755 --- a/backend/app/services/analysis_service.py +++ b/backend/app/services/analysis_service.py @@ -105,6 +105,9 @@ class AnalysisService: brand: str, on_agent_update: AgentCallback | None, previous_review: Optional[PreviousReviewContext] = None, + channel: Optional[str] = None, + sub_channel: Optional[str] = None, + proof_type: Optional[str] = None, ) -> Tuple[str, SubReview]: """Run a single agent with callback notifications.""" agent = self.agents[agent_name] @@ -114,9 +117,9 @@ class AnalysisService: await on_agent_update(agent_name, None) if agent_name == "Brand Agent": - review = await agent.analyze(images, previous_review=previous_review, brand=brand) + review = await agent.analyze(images, previous_review=previous_review, brand=brand, channel=channel, sub_channel=sub_channel, proof_type=proof_type) else: - review = await agent.analyze(images, previous_review=previous_review) + review = await agent.analyze(images, previous_review=previous_review, channel=channel, sub_channel=sub_channel, proof_type=proof_type) logger.info(f"[ANALYSIS] Agent completed: {agent_name} - ragStatus: {review.ragStatus}") if on_agent_update: @@ -132,6 +135,9 @@ class AnalysisService: is_wip: bool = False, brand: str = "Barclaycard", previous_analysis: Optional[dict] = None, + channel: Optional[str] = None, + sub_channel: Optional[str] = None, + proof_type: Optional[str] = None, ) -> Tuple[AgentReview, Optional[List[Tuple[bytes, int, int]]]]: """ Analyze a proof using all agents in parallel. @@ -198,6 +204,9 @@ class AnalysisService: brand, on_agent_update, previous_review=self._extract_previous_review_context(agent_name, previous_analysis), + channel=channel, + sub_channel=sub_channel, + proof_type=proof_type, ) for agent_name in self.AGENT_ORDER ] @@ -210,7 +219,8 @@ class AnalysisService: await on_agent_update("Summary", None) overall_status, summary, financial_promotion_reason = await self.lead_agent.synthesize( - reviews, previous_analysis=previous_analysis + reviews, previous_analysis=previous_analysis, + channel=channel, sub_channel=sub_channel, proof_type=proof_type, ) logger.info(f"[ANALYSIS] Analysis complete - overallStatus: {overall_status}") diff --git a/backend/app/websocket/handlers.py b/backend/app/websocket/handlers.py index bb9ddb2..8464108 100755 --- a/backend/app/websocket/handlers.py +++ b/backend/app/websocket/handlers.py @@ -127,6 +127,11 @@ async def handle_analyze_message( logger.warning(f"[WEBSOCKET] Failed to fetch previous analysis: {str(e)}") # Continue without previous analysis - still run the current analysis + # Extract proof metadata for agent context + channel = data.get("channel") + sub_channel = data.get("sub_channel") + proof_type = data.get("proof_type") + # Run the analysis logger.info("[WEBSOCKET] Starting analysis...") result, pdf_pages = await analysis_service.analyze_proof( @@ -136,6 +141,9 @@ async def handle_analyze_message( is_wip=is_wip, brand=brand, previous_analysis=previous_analysis, + channel=channel, + sub_channel=sub_channel, + proof_type=proof_type, ) # Build the result dict