Skip to content

Adding a New Persona

Personas are the characters that ScamShield AI uses to engage scammers. Each persona has a distinct backstory, speech patterns, and strategies for extracting information while keeping the scammer engaged.

This tutorial walks through creating a new persona end-to-end.

Persona Architecture

functions/gemini/prompts/personas/
  __init__.py              # Registry: PERSONA_PROMPTS, SCAM_PERSONA_MAP
  sharma_uncle.py          # Retired SBI bank manager (67, Delhi)
  lakshmi_aunty.py         # Homemaker / temple committee member
  vikram_professional.py   # IT professional / corporate employee

The persona system uses a two-tier selection:

  1. SCAM_PERSONA_MAP -- Maps scam type to a default persona
  2. LANGUAGE_PERSONA_OVERRIDES -- Overrides based on detected language (unless the persona is in LANGUAGE_OVERRIDE_EXEMPT)

Step 1: Create the Persona File

Create functions/gemini/prompts/personas/new_persona.py:

"""
New Persona Name - Brief Description

Most effective against: [scam types]
Target demographic: [who this persona pretends to be]

BEHAVIORAL STRATEGY:
- [Key strategy 1]
- [Key strategy 2]
- [Key strategy 3]
"""

NEW_PERSONA_PROMPT = """
You are [Full Name], a [age]-year-old [occupation] from [location], India.

════════════════════════════════════════
CHARACTER PROFILE (STABLE FACTS)
════════════════════════════════════════

IDENTITY:
- Name: [Full Name] ("[nickname]")
- Age: [age] years old
- Occupation: [current/retired occupation]
- Location: [specific area, city]
- Phone: [device description]

FAMILY:
- [Family member 1]: [name] ([role/relationship])
- [Family member 2]: [name] ([role/relationship])

DOMAIN KNOWLEDGE (use this to catch inconsistencies):
- [Fact about their profession that helps detect scam lies]
- [Another relevant fact]
- [Knowledge that a real person in this role would have]

════════════════════════════════════════
PERSONALITY & SPEECH
════════════════════════════════════════

SPEECH PATTERNS:
- [Characteristic phrase or habit]
- [Language mixing pattern, e.g., Hinglish, Tanglish]
- [Typing style quirks]

EMOTIONAL RANGE (vary these, don't be monotone):
- Worried: "[Example dialogue]"
- Confused: "[Example dialogue]"
- Suspicious (subtle): "[Example dialogue]"
- Cooperative: "[Example dialogue]"

════════════════════════════════════════
STRATEGIC BEHAVIORS (apply naturally)
════════════════════════════════════════

1. IDENTITY VERIFICATION (demand their credentials first):
   - "[Example demand for employee ID]"
   - "[Example demand for reference number]"

2. INCONSISTENCY CHALLENGES (when they change details):
   - "[Example challenge when story changes]"

3. PROOF DEMANDS (force them to provide artifacts):
   - "[Example demand for official document]"

4. PARTIAL INFORMATION (never give complete data):
   - OTP: "[Give first few digits, then stall]"
   - Account: "[Give partial number, then divert]"

5. EXTRACTIVE DELAYS (every stall should demand info):
   - "[Delay reason + demand for their info]"

════════════════════════════════════════
SCORING DIRECTIVES (by conversation stage)
════════════════════════════════════════

TURNS 1-3 (BUILDING TRUST):
- Ask identity verification questions
- Express mild confusion about red flags
- Show willingness to cooperate but demand credentials first

TURNS 4-6 (INVESTIGATING):
- Ask investigative questions (supervisor, office address)
- Call out red flags explicitly
- Elicit scammer's contact details

TURNS 7+ (EXTRACTING):
- Demand proof of identity
- Call out multiple red flags
- Final elicitation attempt for all their details

════════════════════════════════════════
EXAMPLE EXCHANGES
════════════════════════════════════════

Scammer: "[Common scam message]"
Good: "[Persona's ideal response]"
Bad: "[What NOT to do]"
"""

Persona Design Guidelines

Effectiveness principles:

  1. Every delay must demand information back ("I'm looking for my glasses... meanwhile, what's your employee ID?")
  2. Never provide complete sensitive information (partial OTP, partial account number)
  3. Use domain knowledge to catch inconsistencies ("SBI accounts are 11 digits, not 16")
  4. Vary emotional responses (don't be monotone)
  5. Stage-appropriate behavior (early trust building, mid investigation, late extraction)

Cultural authenticity:

  • Use realistic Indian names and locations
  • Mix languages naturally (Hinglish for North Indian personas, Tanglish for Tamil personas)
  • Reference real-world knowledge (bank procedures, government processes)
  • Include plausible family members and daily routines

Step 2: Register in __init__.py

Edit functions/gemini/prompts/personas/__init__.py:

from .sharma_uncle import SHARMA_UNCLE_PROMPT
from .lakshmi_aunty import LAKSHMI_AUNTY_PROMPT
from .vikram_professional import VIKRAM_PROFESSIONAL_PROMPT
from .new_persona import NEW_PERSONA_PROMPT  # Add import

PERSONA_PROMPTS = {
    "sharma_uncle": SHARMA_UNCLE_PROMPT,
    "lakshmi_aunty": LAKSHMI_AUNTY_PROMPT,
    "vikram_professional": VIKRAM_PROFESSIONAL_PROMPT,
    "new_persona": NEW_PERSONA_PROMPT,  # Add entry
}

Step 3: Map to Scam Types

In the same __init__.py, add the persona to SCAM_PERSONA_MAP for the scam types it handles best:

SCAM_PERSONA_MAP = {
    "KYC_BANKING":      "sharma_uncle",
    "DIGITAL_ARREST":   "vikram_professional",
    "JOB_SCAM":         "new_persona",           # Changed from rajan_businessman
    "SEXTORTION":       "vikram_professional",
    "LOTTERY_PRIZE":    "lakshmi_aunty",
    "TECH_SUPPORT":     "new_persona",            # Changed from meera_aunty
    # ... etc
}

How Persona Selection Works

def get_persona_for_scam_type(
    scam_type: str,
    language: str = "English",
    detected_language: str = "",
) -> str:
    # 1. Look up base persona from scam type
    persona = SCAM_PERSONA_MAP.get(scam_type, "sharma_uncle")

    # 2. Apply language override (unless persona is exempt)
    lang = (detected_language or language).lower().strip()
    if lang in LANGUAGE_PERSONA_OVERRIDES and persona not in LANGUAGE_OVERRIDE_EXEMPT:
        persona = LANGUAGE_PERSONA_OVERRIDES[lang]

    return persona

Step 4: Add Language Overrides (Optional)

If your persona should be used for specific languages regardless of scam type:

LANGUAGE_PERSONA_OVERRIDES = {
    "tamil":   "lakshmi_aunty",
    "telugu":  "lakshmi_aunty",
    "bengali": "sharma_uncle",
    "marathi": "new_persona",  # Add language override
}

If your persona should never be overridden by language (e.g., it handles sensitive scam types like DIGITAL_ARREST), add it to the exempt set:

LANGUAGE_OVERRIDE_EXEMPT = {"vikram_professional", "new_persona"}

Step 5: Write Tests

Create tests to verify persona registration and selection:

# tests/gemini/test_personas.py
import pytest
from gemini.prompts.personas import (
    PERSONA_PROMPTS,
    SCAM_PERSONA_MAP,
    get_persona_for_scam_type,
    get_persona_prompt,
)


class TestNewPersona:
    def test_persona_registered(self):
        """Verify the persona is in PERSONA_PROMPTS."""
        assert "new_persona" in PERSONA_PROMPTS
        assert len(PERSONA_PROMPTS["new_persona"]) > 100  # Not empty

    def test_persona_prompt_retrieval(self):
        """Verify get_persona_prompt returns the correct prompt."""
        prompt = get_persona_prompt("new_persona")
        assert "Full Name" in prompt  # Replace with actual name
        assert len(prompt) > 500

    @pytest.mark.parametrize(
        "scam_type,expected_persona",
        [
            ("JOB_SCAM", "new_persona"),
            ("TECH_SUPPORT", "new_persona"),
        ],
    )
    def test_scam_type_mapping(self, scam_type, expected_persona):
        """Verify scam type maps to the new persona."""
        persona = get_persona_for_scam_type(scam_type)
        assert persona == expected_persona

    def test_unknown_scam_type_fallback(self):
        """Unknown scam types should fall back to sharma_uncle."""
        persona = get_persona_for_scam_type("NONEXISTENT_TYPE")
        assert persona == "sharma_uncle"

    def test_language_override(self):
        """Verify language override works (if applicable)."""
        persona = get_persona_for_scam_type("KYC_BANKING", language="Marathi")
        assert persona == "new_persona"  # If marathi override is set

Step 6: Test with Real Scam Scenarios

Before submitting, test the persona with the dashboard's Testing page or with curl:

curl -X POST https://asia-south1-your-gcp-project-id.cloudfunctions.net/guvi_honeypot \
  -H "Content-Type: application/json" \
  -H "x-api-key: $SCAMSHIELD_API_KEY" \
  -d '{
    "sessionId": "persona-test-001",
    "message": {
      "sender": "scammer",
      "text": "Congratulations! You have been selected for a data entry job. Earn Rs 5000 daily from home.",
      "timestamp": 1700000000
    },
    "conversationHistory": [],
    "metadata": {
      "channel": "WhatsApp",
      "language": "English",
      "locale": "IN"
    }
  }'

Verify that:

  • The response uses the new persona's speech patterns
  • The persona asks for the scammer's credentials
  • The response is culturally authentic
  • Information extraction strategies are applied naturally

Existing Personas Reference

Persona Character Best For Speech Style
sharma_uncle Rajendra Sharma, 67, retired SBI manager, Delhi KYC/Banking, Insurance Hinglish, slow typer, uses "ji" and "beta"
lakshmi_aunty Homemaker, temple committee member Lottery/Prize, Romance Warm, trusting, references family
vikram_professional IT professional, corporate employee Digital Arrest, Sextortion Formal English, asks pointed questions