Skip to main content

Knowledge > Processes > Theological Lens Matching

Theological Lens Matching

How the system adapts to each church's theological tradition across both the voice agent and chatbot. The lens controls vocabulary, doctrinal rules, RAG filtering, and agent personality.


Theological Lens Taxonomy

17 theological lenses (IDs 1-17) plus 1 universal (ID 0), stored in sai_theological_lenses.

ID Lens Name
── ──────────────────────
0 Universal (shows in all traditions)
1 Evangelical / Restoration
2 Progressive
3 Missional
4 Reformed / Presbyterian
5 Wesleyan / Methodist
6 Lutheran
7 Catholic
8 Anabaptist
9 Pentecostal
10 Christocentric (DEFAULT — non-denominational)
11 Orthodox
12 Black Church
13 Anglican / Episcopal
14 Baptist
15 Charismatic
16 Dispensational
17 Liberation

Lens Resolution (Priority Order)

The system resolves a church's theological lens through a cascade of sources. The first match wins.

Chatbot Resolution (route.ts)

PRIORITY 1: CLIENT-SIDE OVERRIDE (demo mode)
IF lensOverride is a valid number (1-17)
AND lensNameOverride is a non-empty string (<=50 chars):
lensId = lensOverride
lensName = sanitized lensNameOverride
# Used in demo/preview when user selects a tradition

PRIORITY 2: EXPLICIT CHURCH SETTING (church_theological_lenses)
query church_theological_lenses
WHERE church_id = church.id
JOIN sai_theological_lenses for lens_name
LIMIT 1
IF found:
lensId = theological_lens_id
lensName = lens_name

PRIORITY 3: DENOMINATION AUTO-DETECT (DENOMINATION_TO_LENS mapping)
IF church.denomination is not null:
lensId = DENOMINATION_TO_LENS[church.denomination] ?? 10
query sai_theological_lenses for lens_name WHERE lens_id = lensId

PRIORITY 4: DEFAULT
lensId = 10 (Christocentric)
lensName = "Christocentric"

Voice Agent Resolution (core/rag.py)

FUNCTION get_lens_id(denomination: str | None) -> int:
IF denomination is None or empty:
RETURN 10 (Christocentric — DEFAULT_LENS_ID)
RETURN DENOMINATION_TO_LENS.get(denomination, 10)

Denomination-to-Lens Mapping

70+ denomination strings mapped to 17 lens IDs. This mapping is maintained in sync across three files:

  • churchwiseai-web/voice-agent-livekit/core/rag.py (DENOMINATION_TO_LENS)
  • churchwiseai-web/src/lib/rag.ts (DENOMINATION_TO_LENS)
  • Legacy: voice-agent/rag.js (reference only)
BAPTIST FAMILY → Lens 14 (Baptist)
Baptist, Southern Baptist, American Baptist, Free Will Baptist

CATHOLIC → Lens 7
Catholic, Roman Catholic

WESLEYAN/METHODIST FAMILY → Lens 5
Methodist, United Methodist, Free Methodist, AME
Church of the Nazarene, Nazarene, Wesleyan

REFORMED/PRESBYTERIAN → Lens 4
Presbyterian, PCA, PCUSA, Reformed

LUTHERAN → Lens 6
Lutheran, ELCA, LCMS, Missouri Synod

PENTECOSTAL → Lens 9
Pentecostal, Assembly of God, Assemblies of God
Church of God, Foursquare

ANGLICAN/EPISCOPAL → Lens 13
Episcopal, Anglican

ORTHODOX → Lens 11
Orthodox, Greek Orthodox, Eastern Orthodox, Russian Orthodox

ANABAPTIST → Lens 8
Mennonite, Amish, Anabaptist, Brethren

NON-DENOMINATIONAL → Lens 10 (Christocentric, DEFAULT)
Non-denominational, Nondenominational, Community Church, Bible Church

CHARISMATIC → Lens 15
Charismatic

EVANGELICAL / RESTORATION → Lens 1
Evangelical, Church of Christ, Disciples of Christ, Christian Church

BLACK CHURCH → Lens 12
AME Zion, CME, COGIC, National Baptist

DISPENSATIONAL → Lens 16
Dispensational

PROGRESSIVE → Lens 2
Progressive, UCC, United Church of Christ

MISSIONAL → Lens 3
Missional

LIBERATION → Lens 17
Liberation

What the Lens Controls

1. RAG Filtering

Both voice agent and chatbot filter search results by lens ID.

VOICE AGENT (fetch_session_rag in core/rag.py):
lens_id = get_lens_id(denomination)
search_unified_rag(embedding, lens_ids=[lens_id], match_count=5)
# Returns content tagged with this lens OR universal (lens_id=0)

CHATBOT (route.ts):
searchRAG({ queryEmbedding: embedding, lensIds: [lensId], matchCount: 8 })
# Supabase RPC search_unified_rag_content filters by p_theological_lens_ids

RESULT:
A Baptist church gets Baptist-tradition illustrations
A Catholic church gets Catholic-tradition content
Universal content (lens_id=0) appears for all traditions

2. Doctrinal Rules (theological_contradictions)

Per-lens rules that constrain what the AI must/must-not say.

QUERY: theological_contradictions WHERE lens_id = lensId

FIELDS PER RULE:
doctrine_category: e.g., "baptism", "eucharist", "ordination"
primary_position: "Believers' baptism by immersion only"
contrary_positions: ["infant baptism", "sprinkling"]
must_include_terms: ["credobaptism", "immersion"]
must_exclude_terms: ["christening", "infant sprinkling"]
explanation: context for the AI

INJECTED AS:
"IMPORTANT DOCTRINAL REQUIREMENTS:
BAPTISM:
- This church's position: Believers' baptism by immersion only
- MUST include: credobaptism, immersion
- MUST NEVER mention: christening, infant sprinkling
- DO NOT recommend: infant baptism, sprinkling
This means your answers should strictly follow the Baptist
theological positions listed above."

CHURCH-SPECIFIC OVERRIDES (organization_settings.doctrinal_overrides):
A church can override standard lens positions:
{ "baptism": { custom_practice: true,
explanation: "We practice both infant dedication and believer's baptism" }}
Appended as "CUSTOM CHURCH PRACTICES" section

3. Vocabulary (lens_knowledge → lens-vocabulary.ts)

Per-lens preferred and avoided vocabulary injected into the chatbot prompt.

EXAMPLES:
Baptist (lens 14):
PREFER: "baptism by immersion", "believer's baptism", "Sunday school"
AVOID: "christening", "infant baptism", "catechism"

Catholic (lens 7):
PREFER: "Holy Mass", "Eucharist", "parish", "sacrament", "priest"
AVOID: "worship service", "communion table", "pastor" (use "Father")

Orthodox (lens 11):
PREFER: "Divine Liturgy", "Theotokos", "Holy Tradition"
AVOID: "worship service", "Bible study" (use "catechesis")

Lutheran (lens 6):
PREFER: "the Lord's Supper", "Real Presence", "sacrament"
AVOID: "mere symbol", "just symbolic"

IMPLEMENTATION:
fetchLensVocabulary(lensId) → queries lens_knowledge table
buildChatVocabularyBlock(vocab, lensName) → formats for prompt injection

4. Agent Personality

The theological lens influences the chatbot's conversational style.

FORMAL TRADITIONS (Catholic, Orthodox, Anglican, Lutheran):
More formal language
Liturgical calendar awareness
Proper titles (Father, Reverend, Bishop)
Reference to sacraments, tradition, church fathers

INFORMAL TRADITIONS (Non-denominational, Community, Charismatic):
Conversational tone
Contemporary language
First-name basis
Focus on personal relationship with God

REFORMED TRADITIONS (Presbyterian, Reformed, Baptist):
Theological precision
Scripture-first approach
Doctrinal clarity
Respect for confessional standards

BLACK CHURCH TRADITION:
Rich call-and-response patterns
Social justice awareness
Community emphasis
Musical/worship tradition references

Cross-Channel Consistency

The lens resolution produces identical results across both channels because:

  1. Both use the same DENOMINATION_TO_LENS mapping (kept in sync manually)
  2. Both search the same unified_rag_content table with the same lens filter
  3. Both read the same theological_contradictions rules
  4. Default is always Christocentric (lens 10) when denomination is unknown

The voice agent resolves lens once at session initialization (fetch_session_rag) and caches it for the call. The chatbot resolves lens on every request (stateless API).