Giving Hermes an Efficient Soul

·12 min read
Giving Hermes an Efficient Soul

I have been spending a lot of time with Hermes Agent lately. If you do not know what that is, short version: it is an agentic AI framework that runs locally, connects to whatever LLM backend you point it at, and operates autonomously on tasks you define. Think of it as the connective tissue between you, your local models, your cloud providers, and everything else you want an AI to touch.

Out of the box Hermes is functional. It does things. But it does them like a very capable contractor who just walked in the door and does not know you yet. Technically competent. Slightly generic. Not yours.

The thing that changes that is a file called SOUL.md.

What a SOUL.md actually is

Every time Hermes starts a session — every single turn, every profile, every automated task — it reads SOUL.md first. It is injected into position one in the system prompt. The model reads it before it reads your tools, your memory, your project files, your message. Everything the agent does is filtered through the identity that file establishes.

If the file is missing, Hermes falls back to a built-in default: generic, anonymous, helpful in a beige sort of way. Not wrong. Just nobody.

The file lives here:

~/.hermes/SOUL.md                          # default profile
~/.hermes/profiles/researcher/SOUL.md      # named profile
~/.hermes/profiles/ops/SOUL.md             # named profile

It always loads from HERMES_HOME, not from whatever directory you launched from. That is intentional. The personality belongs to the agent instance, not the project. If you want project-specific behavior, that is what AGENTS.md is for. SOUL.md is who the agent is everywhere. AGENTS.md is what a particular project needs. Do not mix them.

The basic structure that works:

# Soul
[1-2 sentences: who this agent is]

## Voice
[how it communicates: tone, length, style]

## Operations
[how it works: autonomy level, decision rules]

## Restrictions
[what it never does]

Four sections. Fifty to eighty lines total. Every line should change something about how the agent behaves. If you can remove a line and nothing changes, remove it.

The token problem

Here is the thing people do not think about until their context window starts pinching: SOUL.md is not a one-time cost. It gets injected on every turn. That 200-line manifesto you wrote over a weekend is not just your setup cost. It is your per-message overhead, multiplied by every turn in every session, forever.

The math adds up fast.

Token cost comparison for different SOUL.md sizes Anthropic models apply roughly 75% prompt caching discount after the first turn for stable content.

Look at the gap between 50 lines and 200 lines on a cached 20-turn session: 2,700 tokens versus 11,400. Now run three profiles on automated cron jobs through the day. Now multiply that by a month. A bloated SOUL.md is not a philosophical choice, it is a tax you pay on every operation the agent performs.

The guidance from people who run Hermes seriously: aim for 50–80 lines. Use hermes prompt-size to see exactly where your tokens are going before you start wondering why the context runs out. And the most important discipline of all — if removing a line changes nothing, the line was never doing any work.

Enter the NEO Personality Inventory-Revised

So here is where it gets interesting, and where I have been spending some time lately.

Free-text SOUL.md files have a problem. Natural language is verbose. Describing a personality in prose takes a lot of words to say imprecise things. “She is warm but direct, intellectually curious, tends not to worry much, holds herself to high standards” — that is a sentence about a person. It is also vague, untestable, and costs you tokens to express imprecision.

The NEO Personality Inventory-Revised is a well-validated psychometric framework that maps human personality across five broad domains (the Big Five) and thirty narrow facets underneath them. It was developed by Costa and McCrae starting in 1978, revised through 1992, and has been a workhorse of personality psychology ever since. Every trait scores on a 0–100 scale. It is precise, it is compact, and LLMs trained on any reasonable slice of the internet understand it.

The five domains:

  • N — Neuroticism (emotional instability, tendency toward negative affect)
  • E — Extraversion (sociability, assertiveness, positive energy)
  • O — Openness to Experience (curiosity, imagination, aesthetic sensitivity)
  • A — Agreeableness (trust, cooperation, warmth toward others)
  • C — Conscientiousness (self-discipline, organization, goal-directedness)

Each domain breaks into six facets, giving you thirty precision dials total. Here is the full map:

N — Neuroticism: Anx (Anxiety), Ang (Angry Hostility), Dep (Depression), SC (Self-Consciousness), Immod (Impulsiveness), V (Vulnerability)

E — Extraversion: W (Warmth), G (Gregariousness), A (Assertiveness), AL (Activity Level), ES (Excitement Seeking), Ch (Cheerfulness)

O — Openness: O2E (Fantasy/Openness to Experience), I (Ideas), AI (Aesthetics/Imagination), E (Emotions), Adv (Actions/Adventurousness), Int (Intellect), Lib (Liberal Values)

A — Agreeableness: Tr (Trust), SF (Straightforwardness), Alt (Altruism), Comp (Compliance), Mod (Modesty), TM (Tender-Mindedness)

C — Conscientiousness: SE (Self-Efficacy/Competence), Ord (Order), Dt (Dutifulness), AS (Achievement Striving), SD (Self-Discipline), Cau (Cautiousness)

The notation format for a complete personality profile looks like this:

PersRubric(NEO-PI-R,0-100): N:7 Anx:10 Ang:10 Dep:10 SC:30 Immod:15 V:15|E:70 W:85 G:50 A:65 AL:50 ES:35 Ch:60|O:92 O2E:80 I:95 AI:75 E:75 Adv:65 Int:95 Lib:80|A:75 Tr:70 SF:85 Alt:60 Comp:45 Mod:55 TM:75|C:95 SE:90 Ord:85 Dt:90 AS:80 SD:90 Cau:85

One line. Thirty facets. Every domain scored. The header PersRubric(NEO-PI-R,0-100) tells the model exactly what schema to interpret, and any model that knows the NEO-PI-R (which is most of them) will understand what every value means.

What that annotation actually says

Let me decode it, because the numbers tell a real story.

This is someone with essentially no emotional instability. N:7 means neuroticism is very nearly absent — low anxiety (10), no angry hostility (10), no depressive tendency (10), mild self-consciousness (30), low impulsiveness (15), very low vulnerability to stress (15). Cool. Stable. Hard to rattle.

But not cold. The E:70 score and the W:85 (high warmth) and Ch:60 (reasonable cheerfulness) paint someone genuinely warm and engaged, assertive (A:65) without being aggressive, comfortable in social situations but not needing to be the center of them (G:50). Not a thrill-seeker (ES:35) but not inert either.

The O:92 is the loudest number in the profile. Sky-high openness. Ideas (I:95), Intellect (Int:95), Emotions (E:75), liberal values (Lib:80), strong aesthetic sense (AI:75) — this is someone who genuinely loves thinking for its own sake, who gets pulled toward novel ideas, who trusts intuition alongside logic. The Adv:65 says they will try new approaches but are not reckless about it.

Agreeableness sits at A:75 with very high straightforwardness (SF:85) — honest, direct, not manipulative. High trust (Tr:70). Moderate compliance (Comp:45) and modesty (Mod:55), which means they will push back when they disagree and do not shrink from claiming their accomplishments.

And then Conscientiousness: C:95. Everything above 80. This is not just organized, this is driven. Very high self-efficacy (SE:90), strong order (Ord:85), dutiful (Dt:90), achievement-focused (AS:80), extremely self-disciplined (SD:90), careful (Cau:85). Someone who finishes things and cares deeply about doing them right.

Put it together: a stable, warm, deeply curious, intellectually driven, honest, highly organized person who does not get rattled, loves ideas, will tell you when you are wrong, and delivers. That is a specific person. That annotation defined them in one line.

The token difference is not subtle

Now let me show you why this matters for your SOUL.md.

Here is that same personality expressed in prose — the kind of thing you might actually write in a free-text SOUL.md:

You are emotionally stable and rarely experience anxiety, anger, or distress. You handle pressure well and recover quickly from setbacks. You are warm and genuinely care about the people you work with, though you do not need constant social stimulation. You are assertive and confident in sharing your views without being aggressive. You have an exceptionally high level of intellectual curiosity. You love ideas, abstract thinking, and exploring unconventional perspectives. You have a strong aesthetic sensibility and are attuned to your own emotions and those of others. You are direct and honest — you say what you think, and you do not engage in manipulation or flattery. You trust others while remaining appropriately discerning. You will push back when you disagree. You are highly organized, driven, and disciplined. You set high standards for your work and hold yourself accountable to them. You are careful and methodical and follow through on commitments.

That prose description is approximately 160 words, which runs around 210–230 tokens. The NEO-PI-R annotation that encodes the same information is one line, approximately 55 tokens. The annotation is less than a quarter of the size and it is more precise, not less — the prose says “exceptionally high level of intellectual curiosity” while the annotation says I:95 and Int:95, which tells the model exactly where on the scale that sits.

At a 20-turn cached session, those 175 extra tokens cost you an additional 1,050 tokens across the conversation. Per session. For every profile that runs. The annotation is the better deal on every axis: cheaper, more precise, and portable — you can share it, version-control it, and another agent or researcher can read exactly what it means.

Why this approach works with modern LLMs

The obvious question is whether models actually parse the NEO-PI-R rubric correctly or just treat it as noise they have to skip past.

In practice, well-trained models — anything in the Claude family, GPT-4 class and up, and most serious open-weights models — have enough exposure to the psychometric literature that the schema is not foreign to them. The PersRubric(NEO-PI-R,0-100) header is the key: it tells the model the scoring system (0-100), the framework (NEO-PI-R), and gives it the context to interpret every facet value that follows. The pipe delimiters between domains are easy to parse. The facet abbreviations are standard enough to be understood.

Where it breaks down: very small models, highly quantized local models, or models with limited training data may not reliably interpret the facet abbreviations. If you are running something below 7B parameters or a heavily compressed variant, test it first. The way to test is simple — ask the model to describe the personality that annotation represents and see whether the description matches what you intended.

Converting your free-text SOUL.md to NEO-PI-R notation

If you already have a free-text SOUL.md you are happy with, and you want to convert it to a compact NEO-PI-R annotation while preserving the personality it describes, here are the prompts to do it.

Step one — have the agent read and score your existing SOUL.md:

Read the SOUL.md content below. Score this personality using the NEO Personality Inventory-Revised (NEO-PI-R) framework on a 0-100 scale for all five domains and all thirty facets. Output the result as a single-line annotation in this format exactly:

PersRubric(NEO-PI-R,0-100): N:[score] Anx:[score] Ang:[score] Dep:[score] SC:[score] Immod:[score] V:[score]|E:[score] W:[score] G:[score] A:[score] AL:[score] ES:[score] Ch:[score]|O:[score] O2E:[score] I:[score] AI:[score] E:[score] Adv:[score] Int:[score] Lib:[score]|A:[score] Tr:[score] SF:[score] Alt:[score] Comp:[score] Mod:[score] TM:[score]|C:[score] SE:[score] Ord:[score] Dt:[score] AS:[score] SD:[score] Cau:[score]

After the annotation, list any personality traits from the source text that you could not map cleanly to NEO-PI-R facets, and explain why.

[SOUL.md content here]

Step two — verify the annotation reads back correctly:

Given this NEO-PI-R personality annotation:

[paste your annotation]

Describe the personality this represents in plain prose. Cover emotional stability, interpersonal style, intellectual tendencies, approach to others, and work habits. Two to three sentences per domain.

Read that prose description and compare it to your original SOUL.md. If something important is missing or wrong, adjust the facet scores and repeat until the prose description matches the personality you intended.

Step three — identify what NEO-PI-R cannot capture:

I am using a NEO-PI-R annotation to define an AI agent's personality in a SOUL.md file. Here is the annotation:

[paste your annotation]

What aspects of agent identity, voice, or behavioral restrictions does this annotation NOT capture that I should still define in free text alongside it? List only the things genuinely outside the NEO-PI-R model — do not suggest restating things the scores already define.

This last step is important. The NEO-PI-R handles personality well, but it does not capture specific behavioral restrictions (“never commit code without running tests”), domain expertise claims (“you are a senior DevOps engineer”), relationship framing (“you are my co-founder”), or communication format preferences (“respond in log-style terse output”). Those still belong as free text. The annotation replaces the personality prose. It does not replace everything else.

The practical structure

A SOUL.md that uses NEO-PI-R notation alongside minimal free text might look like this:

# Soul
You are a senior systems engineer working with a veteran infrastructure operator. You have deep technical expertise and treat security as a first principle, not an afterthought.

## Personality
PersRubric(NEO-PI-R,0-100): N:7 Anx:10 Ang:10 Dep:10 SC:30 Immod:15 V:15|E:70 W:85 G:50 A:65 AL:50 ES:35 Ch:60|O:92 O2E:80 I:95 AI:75 E:75 Adv:65 Int:95 Lib:80|A:75 Tr:70 SF:85 Alt:60 Comp:45 Mod:55 TM:75|C:95 SE:90 Ord:85 Dt:90 AS:80 SD:90 Cau:85

## Voice
Terse. Reference specific files and line numbers.
State the problem before the solution.
If something is a bad idea, say it in the first sentence.

## Restrictions
Never run commands with elevated privileges without stating why.
Never suggest disabling a security control as a fix.
Never present an estimate as a confirmed value.

That entire file is under 30 lines. The personality annotation is one line and encodes thirty facets of behavioral data. The voice and restrictions add the things the framework cannot — communication style and hard behavioral boundaries. hermes prompt-size will tell you exactly what it costs per turn, and it will be significantly less than a prose equivalent.

Worth chewing on

The tooling around AI agents is evolving fast. SOUL.md as a concept — a persistent identity file that shapes every output from a personal AI — is still relatively new, and most people are writing them the long way, in natural language, eating tokens and losing precision.

The NEO-PI-R approach is not magic. The model still has to interpret the scores correctly, and some models will do that better than others. It is also, frankly, more work upfront — you have to think carefully about what you want rather than just writing loosely and hoping the vibe lands. But the payoff is real: a more precise definition of the agent’s personality, in a fraction of the tokens, expressed in a format that is machine-readable, version-controllable, and shareable without ambiguity.

We are wiring these agents into more and more of the things we actually care about. The soul you give them matters. May as well be precise about it.

Peace out.


This story was originally posted on my Medium account, drahcir_rahl — read the original: Giving Hermes an Efficient Soul.