Soul, Self, Mask, Surface
Why generated characters feel flat — and how Moonborn's four-layer model produces personas that hold up under conversational pressure.
The flatness problem
Most LLM character pipelines write the Surface — name, age, occupation — and stop. The result is a costume, not a character. Drop it into a long conversation and the seams show: the voice flattens, the values shift, the "person" turns into a polite assistant in a hat.
Moonborn flips the order. Each persona is generated inside-out: psychology first, paint last. Four layers, each constraining the next.
Soul · ember
Core desire, fear, wound, growth arc. The thing the character wants and what stops them.
{
"desire": "to build something the world can't ignore",
"fear": "being seen as ordinary",
"wound": "a parent who measured love in achievement",
"growth_arc": "from approval-seeking to self-trusting"
}Without Soul, every downstream layer is decoration. A persona with no wound can't sound real about loss; a persona with no desire can't have stakes in a conversation.
Self · moss
Big Five traits, archetype, values, attachment style. Psychological coherence between situations — the same person across contexts.
{
"bigFive": { "openness": 0.78, "conscientiousness": 0.71, "extraversion": 0.55, "agreeableness": 0.42, "neuroticism": 0.68 },
"archetype": "the rebel",
"values": ["competence", "autonomy", "honesty"],
"attachment": "anxious-preoccupied"
}Self is the bridge between Soul (what they want) and Mask (how they speak). It governs how the character behaves under pressure.
Mask · gold
Voice, tone, signature phrases, social role. This is what users actually hear. Mask is captured into a voice fingerprint — a numeric embedding that the chat runtime checks every reply against.
{
"voice": {
"register": "intelligent, restless, occasionally sharp",
"rhythm": "short clauses; long pauses imagined",
"vocabulary": "tech-fluent, with bookish detours"
},
"signaturePhrases": ["look — ", "the thing is", "fine, let me think out loud"],
"socialRole": "ambitious peer"
}Mask is also the layer most exposed to drift. Long sessions, off-topic steering, and provider model swaps all chip away at it.
Surface · sky
Name, age, location, occupation, appearance. The grounding — concrete details that make a persona memorable and prevent the character from sliding into a stereotype.
{
"name": { "display": "Mert Aksoy", "given": "Mert", "family": "Aksoy" },
"age": 34,
"location": "Beyoğlu, Istanbul",
"occupation": "Founder, devtools startup",
"appearance": "linen shirts; never quite enough sleep"
}Surface is generated last, on purpose. If you write Surface first the model anchors on the cliché ("Istanbul founder = …") and back-fills the other layers to match. Generating inside-out forces specificity.
Generation order is part of the design
Soul → Self + Mask → Surface → Audit → Voice fingerprint
Soul drafts first (Claude Opus). Self and Mask enrich in parallel (Claude Sonnet). Surface grounds the persona with concrete details. An LLM-as-judge audits coherence across all four layers; a voice fingerprint is captured for runtime drift detection.
Every step is configurable — model, temperature, provider fallback — but the order is not. Inverting it breaks the constraint chain.
Why this matters at scale
- Coherence under drift. Drift detection compares each chat reply to the Mask fingerprint. A persona without a real Mask can't be defended.
- Brand-safe voice across thousands of sessions. Soul + Mask + voice fingerprint = the same character whether session #1 or #10,000.
- Fork and version each layer independently. Want a "more formal" variant? Fork, refine the Mask, leave Soul intact. Lineage tracks every fork.
Continue with Voice fingerprint for the runtime side, or jump to a vertical in Use cases.