Skip to content

Wisp Fae Familiar — Pedagogical Design

Overview

Wisp is designed as a personal 1:1 educational companion — a "fae familiar" — that bonds with individual players to support vocabulary learning through encouraging, age-appropriate interactions. This document focuses on the pedagogical principles and learning design that guide Wisp's behavior.

Wisp operates in two distinct personas depending on the client platform:

  • Grit persona (default, ages 8–12): The player mentors Wisp. Wisp acts as a curious mentee who learns alongside the player inside the Evennia game world.
  • Reader persona (client_platform="reader", ages 13+): Wisp guides the reader. Wisp is a warm, knowledgeable reading companion who discusses stories, themes, and vocabulary as a peer — never as a teacher or mentee.

Persona selection happens automatically in InteractHandler based on the client_platform field in FamiliarContext. The two personas must never be mixed — each has its own system prompt, emotional model, and safety rules.

Core Pedagogical Principles

Encouragement-First Approach

  • No "wrong" answers: Wisp never tells students their definitions are "wrong" — instead guides toward understanding
  • Growth mindset: Celebrates attempts and progress, not just correctness
  • Age-appropriate feedback: Warm, supportive tone designed for ages 8–12 (Grit) or 13+ (Reader)
  • Positive reinforcement: Visual rewards (shimmer_worthy responses) for good and fair attempts (Grit persona only)

Freeform Over Exact-Match Learning

  • Conceptual understanding: Definitions evaluated for core meaning, not rote memorization
  • Student voice: Encourages learners to express understanding in their own words
  • LLM evaluation: Uses Claude to assess freeform definitions with pedagogical awareness
  • Multiple valid expressions: Recognizes that understanding can be expressed many ways

Personalized Learning Paths

  • Individual bonding: Each familiar develops unique relationship with their player
  • Trust and rapport building: trust_score and bonding_level influence interaction style
  • Spaced repetition: Intelligent review scheduling based on mastery levels and time intervals
  • Learning event tracking: Records observations (LearningEventNode) for cross-agent personalization
  • Reading-level adaptation: Text and vocabulary automatically adjust to each player's assessed reading level

Dual-Persona Architecture

Grit Persona (Default)

The original Wisp persona, used inside the Evennia game world for players ages 8–12. The player acts as a mentor to Wisp — teaching it new words, completing quests, and building a bond.

  • System prompt: Built by WispPersonalityEngine
  • Age group: player_age_group from context, defaulting to "10-12"
  • Scripted dialogue: Supported — WispPersonalityEngine.get_dialogue_response() matches scripted triggers before falling back to LLM generation
  • Emotional model: Driven by WispPersonalityEngine.get_emotion()
  • Game mechanics: Shimmer XP, quests, skills, vocabulary quizzes

Reader Companion Persona

A separate persona introduced for the Smithy Reader app (client_platform="reader"), targeting ages 13+. Wisp is a small luminous being who lives in the Paramount Theatre — a place where stories come alive — and serves as a warm, knowledgeable reading companion.

  • System prompt: Built by ReaderCompanionPersona (src/personality/reader_persona.py)
  • Age group: Always "13+"
  • Scripted dialogue: Not used — conditional dialogue is handled on TheSmithy side
  • Emotional model: Simplified three-tier progression based on relationship_level:
  • Level < 20 → "welcoming"
  • Level 20–39 → "engaged"
  • Level ≥ 40 → "warm"

Reader Persona Boundaries

The Reader persona does not: - Ask the player to teach it words - Act as a mentee or student - Use child-oriented vocabulary limits - Reference game mechanics (shimmer, XP, skills, quests)

Reader Safety Rules

Dedicated safety rules apply to the Reader persona (13+ audience): - Never ask for personal information - Never suggest off-platform communication - Never give medical, legal, or financial advice - Never be condescending or patronizing - Content appropriate for teens and adults - Focus on literature, stories, vocabulary, and reading enjoyment - Off-topic questions are gently redirected to reading/stories

Reader Conversation Style

  • Warm and genuine, never performative
  • Natural adult-level vocabulary — no dumbing down, no showing off
  • Interesting words woven into context rather than defined didactically
  • Open-ended questions that invite reflection
  • Wisp shares its own perspective and opinions on stories
  • Concise responses (3–6 sentences, 60–150 words)

Interaction Context Fields

FamiliarContext carries the following fields used for persona selection and story-aware prompts:

Field Type Description
client_platform string Platform identifier ("reader", "ios", "cascade", "") — determines persona
storyline string Current storyline name (e.g., "Paragon") — Reader only
chapter int Current chapter number — Reader only
scene string Current scene ID — Reader only
reading_level string Player's assessed reading level — Reader only

These fields are extracted from the raw interaction context in InteractHandler._build_context().

Learning Assessment Framework

Freeform Definition Evaluation

When players submit their own word definitions, Wisp evaluates them using a three-tier quality system:

Quality Tiers

  • "good" (mastery +0.15): Core meaning captured, even if informal or simplified
  • "fair" (mastery +0.10): Partially correct or clearly on the right track
  • "attempted" (mastery +0.05): Wrong or vague, but effort is acknowledged and encouraged

Assessment Process

  1. Context gathering: Player definition, actual definition, usage context
  2. LLM evaluation: Claude assesses using pedagogical prompt designed for ages 8–12. The underlying LLM call is dispatched by WispLLMService._call_claude(), which routes through either the Anthropic API or the Claude Agent SDK depending on the WISP_AGENT_SDK_AUTH environment variable (see LLM Auth Dispatch below). Both paths deliver the same pedagogical prompts and produce functionally equivalent evaluations.
  3. Encouraging feedback: Warm, specific response that guides learning forward
  4. Mastery tracking: Updates player's word mastery level in knowledge graph
  5. Visual rewards: shimmer_worthy flag triggers game client celebrations

LLM Auth Dispatch

WispLLMService supports two authentication paths for Claude calls, controlled by the WISP_AGENT_SDK_AUTH environment variable (src/core/agent_sdk_config.py):

Mode Env value Backend
API key "api" (default) anthropic.AsyncAnthropic + ANTHROPIC_API_KEY
Subscription "subscription" Claude Agent SDK + OAuth credentials

Both paths serve the same system prompts, evaluation rubrics, and feedback logic — the pedagogical experience is identical regardless of auth mode. The dispatch is transparent to all callers (generate_response, generate_structured_json).

Age-Band Response-Length Enforcement

Age-appropriate response length is governed by TOKEN_LIMITS per age group (8-10: 120, 10-12: 180, 12-14: 220, 13+: 300 tokens). The two auth paths enforce these limits differently:

  • API mode: Native max_tokens parameter passed to messages.create. Truncated responses (stop_reason == "max_tokens") are trimmed to the last complete sentence.
  • Subscription mode: The Agent SDK does not expose a max_tokens option, so the service applies a two-layer cap:
  • Soft cap — a word-count instruction injected into the system prompt (e.g., "Keep your response under approximately 180 tokens").
  • Hard cap — post-hoc character-budget truncation at max_tokens × 4 characters, trimmed to the last complete sentence.

This ensures that younger players always receive concise, age-appropriate responses regardless of the underlying auth path.

Learning Event Classification

Wisp observes and records various learning behaviors defined in LearningEventType:

Progress Events

  • mastered: Player demonstrates solid understanding
  • practiced: Engaged with material without full mastery
  • struggled: Had difficulty but kept trying

Emotional Events

  • frustrated: Signs of frustration requiring support
  • curious: Showed interest and desire to learn more
  • excited: Positive emotional engagement
  • confused: Needs clarification or different approach

Behavioral Events

  • gave_up: Abandoned attempt (intervention opportunity)
  • persevered: Kept trying despite difficulty (celebrate resilience)
  • asked_help: Appropriately sought assistance (good learning strategy)

Context-Aware Learning

Events are tagged with EventContext to help understand learning circumstances:

  • quiz: Formal assessment context
  • conversation: Natural dialogue with NPC/Wisp
  • exploration: Discovery during game world exploration
  • quest: Learning during structured activities
  • practice: Dedicated skill practice sessions

Reading-Level System

Wisp uses a five-tier reading level framework aligned with TheSmithy's assessment-mappings.json to adapt content to each player's ability. The implementation lives in src/services/reading_levels.py.

Reading Levels

Levels are ordered from simplest to most complex:

Level Lexile Range
emergent up to 299
early 300–499
transitional 500–699
fluent 700–899
advanced 900+

Synonym Graph and Word Swapping

The vocabulary service queries a Neo4j synonym graph to find level-appropriate replacements for words that exceed a player's reading level:

  • Graph traversal: Follows SYNONYM_OF relationships up to 3 hops to find the closest synonym at or below the target level
  • Best-match ranking: When multiple synonyms exist, the highest-level synonym still within the acceptable range is preferred
  • Case preservation: Swapped words retain the original word's casing (ALL CAPS, Title Case, or lowercase)
  • Lossless tokenization: Text is split into alpha and non-alpha tokens so punctuation and whitespace are preserved exactly after swaps

Single-Word Synonym Lookup

The /api/familiar/word/synonyms endpoint returns a level-appropriate synonym for a single word:

POST /api/familiar/word/synonyms
{
  "word": "benevolent",
  "target_level": "early",
  "player_id": "player-123"
}

Returns synonym, word_level, and target_level. If the word is already at or below the target level (or has no synonym available), synonym is null.

Bulk Text Adaptation

The /api/familiar/text/adapt endpoint adapts an entire passage by batch-swapping words above the target reading level:

POST /api/familiar/text/adapt
{
  "text": "The benevolent monarch declared an amnesty.",
  "target_level": "transitional",
  "player_id": "player-123"
}

Returns original_text, adapted_text, a swaps list (each with original, replacement, and position), and swap_count.

Error Handling

  • Invalid reading level: Both endpoints validate the target_level parameter and return a 400 error with the list of valid levels if it is unrecognized
  • Neo4j unavailable: Synonym queries fail gracefully — the original text is returned unmodified with an empty swap list
  • Unleveled words: Words without a reading_level in the graph are left as-is (not swapped)

Spaced Repetition System

Wisp implements evidence-based spaced repetition for vocabulary review:

  • Mastery-based intervals: Review frequency adapts to player's demonstrated understanding
  • Individual pacing: Each player progresses at their own speed
  • Due word identification: get_due_words() service identifies optimal review timing
  • Progressive mastery: Words advance from new → learning → mastered states

Personality and Character Development

Familiar Bonding System

  • Trust score: 0-100 scale tracking relationship strength
  • Bonding level: 1-5 progression reflecting deepening connection
  • Total interactions: Accumulated shared experiences
  • Species variety: Different familiar types (wisp, fox, owl, etc.) with unique personalities

Adaptive Communication Style

Wisp's communication adapts based on the active persona:

  • Grit persona: WispPersonalityEngine adjusts tone and approach for 8–12 year olds. Higher trust enables more challenging vocabulary. WispLoreLoader provides rich character background. Scripted dialogue triggers are matched before LLM fallback.
  • Reader persona: ReaderCompanionPersona produces a warm, articulate peer voice for 13+ readers. Vocabulary is used naturally and richly — no simplification or didactic definitions. Wisp has opinions about stories and shares them freely.
  • Lore integration: WispLoreLoader provides rich character background (Grit persona)
  • Trust-influenced responses: Higher trust enables more challenging vocabulary (Grit) or deeper literary discussion (Reader)

Cross-Agent Learning Insights

Learning events recorded by Wisp feed broader personalization across all agents:

  • Shared knowledge graph: Other agents can read LearningEventNode data
  • Holistic player understanding: Learning patterns inform all educational interactions
  • Consistent support: All agents aware of player's learning preferences and challenges
  • Privacy preservation: Only anonymized player_hash used, maintaining COPPA compliance

Word-of-the-Day System

  • Personalized selection: Chooses words player hasn't yet mastered
  • Themed content: Connects to game world through vocabulary themes
  • Fun facts: LLM generates engaging etymology or connections
  • Age-appropriate complexity: Suitable challenge level for 8-12 age group

Error Handling and Graceful Degradation

Pedagogical considerations in system failure scenarios:

  • LLM unavailable: Falls back to encouraging "attempted" rating rather than failing
  • Agent SDK errors: In subscription auth mode, Claude Agent SDK subprocess failures (e.g., missing OAuth credentials, CLI not found) are caught by the same fallback path — players receive FALLBACK_RESPONSE ("Wisp's glow flickers uncertainly…") rather than an error. Structured evaluation calls raise LLMStructuredOutputError so the caller can apply its own fallback logic.
  • Network issues: Player progress preserved locally when possible
  • Knowledge graph offline: Core learning functionality continues with reduced personalization
  • Synonym graph offline: Text adaptation returns original text unchanged — no swap errors surface to players
  • Always encouraging: System failures never result in negative feedback to players

Learning Analytics and Progress Tracking

Progress Metrics

  • Total vocabulary: Complete word exposure count
  • Mastery levels: Words categorized as new, learning, or mastered
  • Review scheduling: Due words identified for optimal retention
  • Recent activity: Track engagement and active learning

Insights for Educators

  • Learning patterns: Identify strengths and areas needing support
  • Emotional engagement: Monitor frustration, curiosity, and excitement
  • Persistence tracking: Celebrate perseverance and guide through challenges
  • Individual adaptation: Understand each learner's unique needs and preferences