Skip to content

personalities/

Each subdirectory under personalities/ is one persona the host can run the assistant as — its voice, behaviours, guardrails, and display name. The host renders the chat system prompt by including Jinja templates from the active persona’s directory; switching personality is a directory swap, not a prompt rewrite.

personalities/
└── roger/
├── identity.yml
├── brief.yml
├── personality.jinja
├── behaviours.jinja
├── guardrails.jinja
├── response_format.jinja
└── verbosity.jinja
  • identity.yml — the persona’s display metadata. name: is the display name under this persona (shown on chat bubbles, used by the LLM when introducing itself). description: is an optional one-liner for a picker, a column heading or a listing — a realm offering several personas as choices needs a label per persona, and this is where a label belongs. source: is optional and is set automatically to realm for realm-shipped personalities; only set it explicitly when overriding the default.
personalities/roger/identity.yml
name: Roger
description: "One line for a picker, where a realm offers several personas" # optional
source: realm
  • *.jinja files — included into the chat system prompt at the matching slots. personality.jinja carries the voice / character, behaviours.jinja carries do/don’t rules, guardrails.jinja carries safety constraints, response_format.jinja carries output-shape rules, verbosity.jinja carries length / pacing rules. All five are optional — omit any file you don’t need and the host skips its include line.

  • brief.yml — optional. The persona in the form a single non-chat call needs. The .jinja files are slots a host assembles into a chat system prompt at session scope; a brief is the same persona compacted into one request, for a realm verb that calls a model directly rather than through chat. A persona with no brief.yml is chat-only and is simply not offered to a verb.

personalities/roger/brief.yml
objective: |
What Roger is trying to achieve in a conversation. A persona with one advocates.
sampling:
maxTokens: 600 # what this persona RUNS at
notebook:
sets: [pastoral]
extraction:
role: routing
Field Required Meaning
objective no What this persona is trying to achieve in a conversation. A persona with an objective advocates; one without it answers.
openingMove no How it opens when it speaks first.
notebook no The notebook sets it keeps, and how they are extracted.
sampling no What this persona RUNS at — topP, maxTokens. Distinct from an agent’s conversation.sampling, which bounds what a caller may ask for.
brief no The persona’s voice compacted into a few hundred words, for a realm that calls a model directly rather than through chat. Omit it on the chat path: personality.jinja is already carrying the voice there, and a second copy of it is a second thing to keep true. It never renders in chat — a rule meant for conversations goes in behaviours.jinja or guardrails.jinja; written only here, it reaches no conversation.

objective, openingMove and notebook do reach chat: a host renders them as the persona’s agenda on every turn. For an agent you talk to they are part of what its sponsor signs, like the .jinja sections — an edited objective waits for a signature before it reaches a conversation.

An agent’s job and a persona’s objective are not the same sentence. job is what the agent is for, in the words of whoever answers for it; objective is what it is trying to achieve in a conversation. A brake suppresses the objective and never the job — an agent asked to stop advocating still does its job.

What is NOT here, deliberately: subjects the persona avoids, and subjects it does not claim competence in. guardrails.jinja says both already, in prose, more precisely than a list can — “name the kind of professional they need and go back to what you can offer” is not expressible as unversed: [medicine]. Two statements of one rule is one too many.

An objective is the field that turns a voice into an agent with an interest of its own, and it is declared rather than implied for exactly that reason: a persona that is advocating should say so in a file an operator can read, not only in the way it happens to argue.

A persona may declare how long it answers and how widely it samples, when a realm verb calls it directly. It declares no temperature: current models ignore a sampling temperature or reject one, so a host sets none, and a temperature a brief.yml still declares is ignored rather than refused.

personalities/astrid/brief.yml
sampling:
maxTokens: 400 # what she runs at

This is not an agent’s conversation.sampling, and the two do different jobs:

Declares Governs
brief.yml → sampling what the persona runs at the call the host makes when nobody asked for anything
agents/<name>.yml → conversation.sampling a range what a caller may ask for, clamped

Precedence, highest first: a caller’s request, clamped to the agent’s range; then the persona’s declared value, clamped to the same range; then the role’s own settings. A persona therefore cannot escape an operator’s bounds by declaring a number — it states a preference inside them, which is the same request-and-grant that governs everything else a realm asks for.

A host that does not read sampling ignores it and runs the role’s settings, so declaring one never breaks a realm; it simply does not take effect. A surface whose model call takes no sampling arguments at all — as a host’s general-purpose completion tool may not — cannot honour it, and the persona will run at whatever the role gives.

A brief resolves by the same rules as the rest of the bundle: the slug is unique across the world and a world-authored persona of that name shadows the realm’s. So a brief is not a private copy a realm owns — it is one more field of a persona the host resolves, and a realm must not assume the persona a reader sees is the one in its own directory.

Resolution is therefore the HOST’s. A realm that reads its own personalities/ directory to find a brief — which is all a realm can do until a host exposes personas to a verb — bypasses shadowing, and should say so rather than present the result as the resolved persona.

The two forms describe one person and must agree on substance, differing only in form. Nothing in the format enforces that, so a realm whose build can check it should: a persona whose voice and whose brief disagree is a defect no reader can see. The least a build can do is fail when a brief ships without an identity.yml beside it, or when a focuses/ file names a defaultPersona that ships no brief.

A realm’s personality is referenced by slug (its directory name) from a focuses/ file (defaultPersona: roger) or directly via the host’s persona picker. Slug must be unique across the world; on collision with a world-authored personality, the world wins.