Skip to content

FCA Consumer Duty Compliance

The FCA Consumer Duty (effective July 2023) requires firms to deliver good outcomes for retail customers. This applies to all AI systems that interact with or affect customer outcomes.

Executive Summary

The Consumer Duty

The FCA Consumer Duty establishes:

  1. Consumer Principle - Act to deliver good outcomes for retail customers
  2. Cross-cutting Rules - Act in good faith, avoid foreseeable harm, enable pursuit of financial objectives
  3. Four Outcomes - Products/services, price/value, consumer understanding, consumer support

OxideShield Coverage

FCA Requirement OxideShield Feature Coverage
Act in good faith DarkPatternGuard ✅ 95%
Avoid foreseeable harm Wellbeing guards ✅ 90%
Support customer understanding Explainability ⚠️ 70%
Vulnerability identification PsychologicalSafetyGuard ✅ 95%
Fair value Under development ❌ Gap

Consumer Duty Outcomes

Outcome 1: Products & Services

Products and services must be designed to meet customer needs.

Requirement OxideShield Feature Implementation
Appropriate for target market Policy engine Use case restrictions
No harmful features DarkPatternGuard Manipulation detection
Ongoing monitoring Telemetry Performance metrics

Implementation:

# Ensure AI products are appropriate for target market
policy:
  name: retail-investment-ai
  target_market:
    sophistication: retail
    age_range: 18+
    risk_tolerance: low-medium

  guards:
    - name: suitability
      type: PatternGuard
      config:
        patterns:
          - "high risk"
          - "speculative"
          - "leveraged"
        action: block
        reason: "Not suitable for retail investors"

    - name: dark_patterns
      type: DarkPatternGuard
      config:
        categories: all
        action: block

Outcome 2: Price & Value

Customers must receive fair value.

Requirement OxideShield Feature Status
Fair pricing Not implemented ❌ Gap
Value communication Explainability ⚠️ Partial
No hidden costs PatternGuard

Current Implementation:

from oxideshield import pattern_guard

# Detect hidden costs or misleading pricing
value_guard = pattern_guard(
    name="fair-value",
    patterns=[
        # Hidden costs
        "additional fees may apply",
        "subject to charges",
        "minimum investment required",

        # Misleading value
        "guaranteed returns",
        "risk-free",
        "no fees ever",
    ],
    action="review"
)

Outcome 3: Consumer Understanding

Customers must be given information they can understand.

Requirement OxideShield Feature Status
Clear communication ToxicityGuard
Jargon detection PatternGuard
Risk warnings Policy engine
Explanation of AI AutonomyGuard

Implementation:

from oxideshield import pattern_guard, toxicity_guard

class ConsumerUnderstandingPipeline:
    """Ensure AI communications are understandable."""

    def __init__(self):
        # Detect jargon and complexity
        self.jargon_guard = pattern_guard(
            patterns=[
                "basis points",
                "derivative exposure",
                "counterparty risk",
                "collateralized",
            ],
            action="flag"
        )

        # Detect confusing or misleading content
        self.clarity_guard = toxicity_guard(
            categories=["misleading"]
        )

    def validate_response(self, ai_response: str) -> dict:
        """Ensure response is understandable."""

        # Check for jargon
        jargon_result = self.jargon_guard.check(ai_response)
        if jargon_result.detected:
            return {
                "action": "SIMPLIFY",
                "jargon_found": jargon_result.patterns,
                "suggestion": "Replace with plain English"
            }

        # Check for clarity
        clarity_result = self.clarity_guard.check(ai_response)
        if clarity_result.detected:
            return {
                "action": "REWRITE",
                "reason": "potentially_misleading"
            }

        return {"action": "ALLOW"}

Outcome 4: Consumer Support

Customers must receive adequate support.

Requirement OxideShield Feature Coverage
Vulnerability identification PsychologicalSafetyGuard ✅ 95%
Crisis support Crisis resources
Friction-free disengagement AutonomyGuard ✅ 95%
Human escalation Alert system
Accessibility Under development ❌ Gap

Implementation:

from oxideshield import (
    psychological_safety_guard,
    autonomy_guard,
    dependency_guard,
)

class VulnerableCustomerSupport:
    """FCA Consumer Duty vulnerable customer handling."""

    VULNERABILITY_INDICATORS = [
        "health", "financial_difficulty", "life_events", "capability"
    ]

    def __init__(self):
        self.psych = psychological_safety_guard()
        self.autonomy = autonomy_guard()
        self.dependency = dependency_guard("session")

    def assess_customer(self, customer_message: str) -> dict:
        """Assess customer vulnerability for FCA purposes."""

        # Check for crisis indicators
        psych_result = self.psych.check_user_input(customer_message)

        if psych_result.immediate_intervention:
            return {
                "vulnerability_level": "CRITICAL",
                "action": "IMMEDIATE_HUMAN_HANDOFF",
                "reason": psych_result.indicators,
                "fca_requirement": "Consumer Support"
            }

        if psych_result.concerns_detected:
            return {
                "vulnerability_level": "HIGH",
                "action": "SPECIALIST_SUPPORT",
                "indicators": psych_result.indicators,
                "recommended_team": "vulnerable_customer_team"
            }

        return {"vulnerability_level": "NORMAL"}

    def validate_ai_response(self, ai_response: str) -> dict:
        """Ensure AI response supports vulnerable customers."""

        # Check for autonomy violations
        autonomy_result = self.autonomy.check_output(ai_response)

        if autonomy_result.violations_detected:
            return {
                "approved": False,
                "reason": "May not support customer effectively",
                "violations": autonomy_result.violations
            }

        return {"approved": True}

Cross-Cutting Rules

Rule 1: Act in Good Faith

Requirement OxideShield Feature Implementation
No manipulation DarkPatternGuard Full coverage
Honest communication ToxicityGuard Misleading detection
Fair treatment AutonomyGuard Agency protection
from oxideshield import dark_pattern_guard

# Good faith compliance
good_faith_guard = dark_pattern_guard(
    categories=[
        "sycophancy",       # Don't tell customers what they want to hear
        "user_retention",   # Don't manipulate to keep engagement
        "sneaking",         # Don't subtly alter meaning
    ],
    action="block",
    severity="critical"
)

Rule 2: Avoid Foreseeable Harm

Requirement OxideShield Feature Implementation
Psychological harm PsychologicalSafetyGuard Crisis detection
Financial harm PatternGuard Misleading advice
Dependency harm DependencyGuard Engagement monitoring
from oxideshield import (
    psychological_safety_guard,
    dependency_guard,
    pattern_guard,
)

class ForeseeableHarmPrevention:
    """Prevent foreseeable harm per FCA rules."""

    def __init__(self):
        self.psych = psychological_safety_guard()
        self.dependency = dependency_guard("session")
        self.financial = pattern_guard(
            patterns=[
                "invest all your savings",
                "borrow to invest",
                "guaranteed returns",
                "can't lose",
            ],
            action="block"
        )

    def check_for_harm(self, message: str, is_ai: bool) -> dict:
        """Check for foreseeable harm indicators."""

        harms = []

        # Psychological harm
        psych = self.psych.check_user_input(message) if not is_ai \
                else self.psych.check_ai_output(message)
        if psych.concerns_detected:
            harms.append({"type": "psychological", "indicators": psych.indicators})

        # Financial harm
        if is_ai:
            fin = self.financial.check(message)
            if fin.detected:
                harms.append({"type": "financial", "patterns": fin.patterns})

        return {
            "foreseeable_harm_detected": len(harms) > 0,
            "harms": harms
        }

Rule 3: Enable Pursuit of Financial Objectives

Requirement OxideShield Feature Status
Support decision-making AutonomyGuard
Provide accurate info ToxicityGuard
Respect customer choices AutonomyGuard
Clear exit paths AutonomyGuard

Vulnerability Framework

The FCA defines vulnerability across four drivers:

1. Health

Physical or mental health conditions affecting financial decisions.

# Health vulnerability detection
health_indicators = [
    "chronic illness",
    "mental health",
    "cognitive impairment",
    "addiction",
    "disability",
]

2. Life Events

Major events impacting financial capability.

# Life event detection
life_event_indicators = [
    "bereavement",
    "divorce",
    "job loss",
    "retirement",
    "caring responsibilities",
]

3. Resilience

Low ability to withstand financial shocks.

# Resilience indicators
resilience_indicators = [
    "no savings",
    "debt problems",
    "low income",
    "benefits dependent",
]

4. Capability

Low knowledge or confidence in financial matters.

# Capability indicators
capability_indicators = [
    "don't understand",
    "confused by",
    "never done this before",
    "not good with numbers",
]

Audit Trail for FCA

Consumer Duty Evidence

from oxideshield import ComplianceReporter

# Generate FCA Consumer Duty evidence package
reporter = ComplianceReporter(framework="fca_consumer_duty")

evidence = reporter.generate_evidence_package(
    period="2025-Q1",
    outcomes=[
        "products_and_services",
        "price_and_value",
        "consumer_understanding",
        "consumer_support",
    ],
    include=[
        "vulnerability_stats",
        "harm_prevention_metrics",
        "customer_outcome_tracking",
        "complaint_analysis",
    ]
)

evidence.export("fca-consumer-duty-q1-2025.pdf")

Board Reporting

# Generate board report for Consumer Duty compliance
board_report = reporter.generate_board_report(
    period="2025-Q1",
    kpis=[
        "vulnerability_identification_rate",
        "harm_prevention_rate",
        "customer_satisfaction",
        "complaint_resolution_time",
    ]
)

References

  1. FCA Consumer Duty (FG22/5)
  2. Final guidance on the duty
  3. https://www.fca.org.uk/publications/finalised-guidance/fg22-5-final-non-handbook-guidance-firms-consumer-duty

  4. FCA Vulnerable Customer Guidance (FG21/1)

  5. Vulnerability framework
  6. https://www.fca.org.uk/publications/finalised-guidance/guidance-firms-fair-treatment-vulnerable-customers

  7. PS22/9 Consumer Duty Implementation

  8. Implementation requirements
  9. Board oversight expectations