Persona is a deterministic harness to your AI characters. It adds what most AI model roleplaying don't have: persistent conversational tone, consistent character, and more. It aims to remove one thing from AI NPCs/Characters: hallucinations.
AI doesn't understand the nuance of human conversations. Sometimes, it just acts weird.
Player: I killed your father and mother.
AI: No! I will never forgive you for that!
Player: I am so sorry!
AI: I understand. I feel bad, but I forgive you
Persona understands that AI conversations don't have consistency; this is what it aims to implement. A persistent, life-like character simulation for NPCs in-game (or in any setting, like D&D and more). It removes the weirdness, by implementing something called determinism.
At the heart of Persona are what we call .pfile files. They are the living, breathing, source of character representation in Persona's engine:
{
"format": "twd.persona/1",
"ruleset": "persona-core/1.0.0",
"meta": { "name": "Maren", "contentVersion": "1.0.0", "author": "you", "license": "..." },
"identity": { "characterId": "urn:persona:you:maren", "instanceId": null },
"sheet": {
"name": "the Caretaker",
"archetype": "doorkeeper of a ruined chapel",
"pronouns": "she/her",
"voice": "guarded, economical, no performed emotion",
"background": "She was the chapel's doorkeeper. Eleven winters ago...",
"goals": [ { "id": "vigil", "text": "keep the threshold a working door", "weight": 5 } ],
"triggers":[ { "match": ["gaunt","den"], "emotions": { "fear": 12, "sadness": 6 } } ],
"taboos": [ { "text": "will not hold or accept a key",
"restrict": { "all": [ { "actionIn": ["accept","pick_up"] },
{ "targetHasAnyTag": ["key"] } ] } } ],
"lies": [ { "id": "no_family", "line": "I never had family." } ],
"secrets": [ { "id": "S3", "content": "Her daughter Liss died in the massacre.",
"gate": { "trust": 75, "requires": ["reciprocity"] },
"belowGate": { "mode": "lie", "ref": "no_family" } } ],
"disclosure": "hybrid"
},
"body": {
"abilities": { "str": 11, "dex": 12, "con": 13, "int": 12, "wis": 15, "cha": 9 },
"hp": { "current": 22, "max": 22 }, "ac": 12, "speed": 30,
"saves": ["wis","con"], "skills": { "insight": 4 }, "resources": {}
},
"repertoire": [
{ "id": "staff_strike", "kind": "attack",
"targeting": { "kind": "entity", "min": 1, "max": 1 },
"toHit": "str", "damage": "1d6+STR", "tags": ["aggressive"],
"useWhen": "cornered, or the chapel is threatened" }
],
"mind": {
"personality": { "O": 0.5, "C": 0.6, "E": 0.35, "A": 0.45, "N": 0.55 },
"moralCharacter": 10,
"config": {},
"state": null
},
"runtime": null
}Each persona has 4 parts:
- Sheet — who they are: name, history, personality, secrets, and hard limits ("will never hold a key"). The biography.
- Mind — how they feel: emotions, moods, needs (hunger, safety), willpower, and a sense of right and wrong that can erode or heal. The psychology.
- Body — the physical stats: Strength, Dexterity, hit points, armor — standard d20 numbers any D&D player recognizes instantly.
- Repertoire — what they can do: their attacks, spells, and actions, defined as data so the character can never invent a power they don't have.
Most of this info and more can be found on the Persona Documentation.
Once the Persona runs and receives player input, that input follows a specific path:
When the LLM receives a response from the player, the engine wraps it around a JSON body and requires the AI to respond with {tone, reply}. It then gives feedback, returns the tone to the model along with important character information, and the AI responds accordingly, with those stats and tone in mind.
The result is a robust, consistently-toned conversation with Character behaviors being considered when responding.