Skip to main content

Hermes and Veles Agent Personality Handling

Why This Matters

Veles currently has a conceptual conflict:
  • SOUL.md is the default agent personality.
  • Nerve creates top-level identities with their own prompt or character.
  • Veles must inject the selected identity’s SOUL.md instead of always injecting the default SOUL.md.
Hermes has already separated these concepts more clearly. It treats the agent’s soul/personality, project instructions, and temporary personality overlays as different layers.

Hermes Model

Hermes uses SOUL.md as the primary identity slot. In hermes-agent/agent/system_prompt.py, build_system_prompt_parts() builds three tiers:
  • stable: identity from SOUL.md or fallback identity, tool guidance, skills, model guidance, environment hints.
  • context: caller-supplied system message and project context files like AGENTS.md.
  • volatile: memory, user profile, external memory, timestamp/session/provider metadata.
The important detail is that SOUL.md is loaded first as identity:
if agent.load_soul_identity or not agent.skip_context_files:
    _soul_content = _r.load_soul_md()
    if _soul_content:
        stable_parts.append(_soul_content)
        _soul_loaded = True
If no SOUL.md is available, Hermes falls back to DEFAULT_AGENT_IDENTITY.

Project Context Is Separate

Hermes does not treat AGENTS.md as the agent’s personality. In hermes-agent/agent/prompt_builder.py, project context is loaded separately:
  1. .hermes.md / HERMES.md
  2. AGENTS.md / agents.md
  3. CLAUDE.md / claude.md
  4. .cursorrules / .cursor/rules/*.mdc
Only one project-context source wins. SOUL.md is independent and comes from HERMES_HOME, not from the current project directory. This gives Hermes a clean split:
  • SOUL.md: who the agent is.
  • AGENTS.md: how to behave in this project.
  • USER.md / memory: what the agent knows about the user or past work.

Profiles Are First-Class Agent Identities

Hermes also has profiles in hermes-agent/hermes_cli/profiles.py. A profile is a full isolated HERMES_HOME:
  • config.yaml
  • .env
  • SOUL.md
  • memories/
  • sessions/
  • skills/
  • cron/
  • logs/
  • workspace/
  • per-profile subprocess home/
Named profiles live under ~/.hermes/profiles/<name>/. The default profile is ~/.hermes. This is the strongest Hermes answer to “different agents”: each profile can have its own SOUL.md, memory, sessions, skills, runtime config, cron jobs, and logs. Hermes web management exposes profile endpoints:
  • GET /api/profiles
  • POST /api/profiles
  • PATCH /api/profiles/{name}
  • DELETE /api/profiles/{name}
  • GET /api/profiles/{name}/soul
  • PUT /api/profiles/{name}/soul

Personality Command Is Only An Overlay

Hermes also has a lighter /personality command. In hermes-agent/cli.py, /personality <name> resolves a configured personality and writes it to agent.system_prompt in config. This value becomes agent.ephemeral_system_prompt. In hermes-agent/agent/conversation_loop.py, Hermes appends it at API-call time:
effective_system = active_system_prompt or ""
if agent.ephemeral_system_prompt:
    effective_system = (effective_system + "\n\n" + agent.ephemeral_system_prompt).strip()
This is not the same as a profile. It does not replace SOUL.md; it overlays extra instructions on top of the base identity. Hermes is careful about this because its stable system prompt is cached once per session to preserve provider prompt-cache efficiency. The overlay can change, but the cached base system prompt remains stable.

Current Veles Model

Veles now treats Personalities as workspace identities: the soul is Markdown, while small metadata is JSON. The default main Personality uses the workspace-root SOUL.md; custom Personalities live under:
personalities/<personality-id>/
  personality.json
  SOUL.md
personality.json stores machine-readable metadata. SOUL.md stores the actual personality prompt. Personalities do not currently create separate workspaces, memories, sessions, cron stores, logs, or runtime homes. Those remain shared workspace concerns until Veles intentionally designs isolation for them. Skills are the one lightweight overlay: active Personality skills are loaded from personalities/<personality-id>/skills ahead of shared workspace skills. veles/agent/context.py no longer loads SOUL.md through the generic bootstrap bundle:
BOOTSTRAP_FILES = ["AGENTS.md", "TOOLS.md"]
Instead, the active Personality SOUL.md is injected in the identity/personality layer. AGENTS.md remains shared project/operational context. The resulting Veles prompt layers are:
  • hardcoded Veles runtime identity
  • active Personality SOUL.md
  • shared project context from AGENTS.md and TOOLS.md
  • shared workspace memory
  • shared workspace skills
Session keys use personality:<id>:..., for example personality:main:main and personality:reviewer:subagent:<id>. Nerve uses personalities.* gateway RPC methods and personalityId request fields for Personality creation and editing. Workspace files, memory, and cron continue to use shared workspace storage. Skills are mostly shared through skills/<skill>/SKILL.md, but a custom Personality may also provide active-only skills under personalities/<id>/skills/<skill>/SKILL.md.

Nerve Starter Prompt Is Not A Real Agent Personality

Older Nerve builds stored a root starter prompt in browser local storage. Those prompts used to be prepended to the first outbound user message and stripped from the visible transcript. That path is removed; the Personality SOUL.md is the only durable personality prompt. This gives the appearance of a custom agent prompt, but it has important limitations:
  • It is client-side state, not Veles-side state.
  • It is injected as part of the first user message, not the system prompt.
  • It is consumed once per session.
  • It does not replace SOUL.md.
  • It can conflict with SOUL.md because the default soul is still in the system prompt.
That behavior is being removed. The Personality SOUL.md is now the durable prompt source.

Main Difference

Hermes has separate layers:
ConceptHermesVeles
Default personalitySOUL.md identity slotworkspace-root SOUL.md for main Personality
Project instructionsAGENTS.md as project contextworkspace-root AGENTS.md as project context
Custom identityProfile with its own SOUL.mdpersonalities/<id>/SOUL.md
Temporary personalityagent.system_prompt / ephemeral overlaynot used for first-class Personalities
Injection pointSystem promptsystem prompt identity/personality layer
PersistenceHermes profile directory/configworkspace Markdown identity files
Memory/sessions/workspaceprofile-isolatedshared workspace storage for now
The key lesson is not that Veles must copy Hermes profiles exactly. The key lesson is the separation of responsibility:
  • A soul/personality belongs in an identity layer.
  • Project rules belong in a project-context layer.
  • Temporary overlays are different from agent identity.
  • First-class Personalities need server-side storage, not browser-only prompts.

Implication For Veles

For Veles, the product term is Personality, not profile and not agent. Current Veles direction:
  • Keep workspace SOUL.md as the default main Personality soul.
  • Store custom Personalities as Markdown under personalities/<id>/.
  • Inject the active Personality SOUL.md in the system prompt.
  • Keep AGENTS.md as shared project context.
  • Keep memory, sessions, skills, cron, logs, and workspace files shared for now.
  • Remove Nerve’s first-message starter-prompt behavior.
  • Migrate persisted agent: session keys to personality: keys.
  • Deleting a custom Personality removes its Markdown identity and associated root-history conversations; deleting main is not supported.
  • The cutover migration rewrites live session JSONL files, root-history index records, archived root-history transcripts under sessions/archive/, cron jobs, tasks records, and conversation metadata.
This mirrors Hermes’ useful conceptual split while keeping the source of truth visible in the Veles workspace. Nerve should use Personality naming for this top-level identity everywhere it talks about creation, switching, workspace scoping, and session families. Names such as agent log, agent status, assistant display name, and subagent still refer to runtime execution concepts rather than first-class Personalities.

Test Coverage Notes

Personality coverage should pin the same product contracts Hermes pins for profiles, adjusted for Veles’s intentionally smaller scope:
  • Storage: main uses workspace-root SOUL.md plus personality.json; custom Personalities use personalities/<id>/SOUL.md plus personalities/<id>/personality.json; custom Personalities may have active-only skills in personalities/<id>/skills; no per-Personality workspace, memory, sessions, cron, logs, or home directories are created.
  • Prompt assembly: the active Personality soul is injected as the identity layer, while shared AGENTS.md remains project context.
  • Runtime and RPC: personalities.* methods create, patch, list, fetch, and delete Personalities with personalityId fields and personality:<id>:main root sessions.
  • Migration: persisted agent: keys and agentId metadata are rewritten to personality: and personalityId, including root, subagent, cron, cron-run, archive, and conversation records.
  • Cutover healing: if an existing personality:<id>:... session has no Markdown identity yet, startup and prompt assembly materialize personalities/<id>/SOUL.md plus metadata instead of crashing.

Design Warning

Do not store the long-lived custom Personality soul only in session metadata. Veles session/root-history activation can rewrite live session metadata from root-history records, and session metadata is already used for labels, model choice, thinking level, parent links, and root-history behavior. A custom Personality should survive session switching and should be editable as Markdown in the workspace, so its soul belongs in personalities/<id>/SOUL.md. It should not imply a separate workspace or memory model yet.

Short Version

Hermes solves the problem by making SOUL.md the identity layer and AGENTS.md the project-context layer. For multiple identities, Hermes uses profiles, where each profile has its own SOUL.md and runtime state. Hermes also supports personality overlays, but those are not true isolated identities. Veles uses the term Personality for that first-class identity. Personalities store their soul as workspace Markdown, and the active Personality SOUL.md is injected into the system prompt as the active soul. Runtime isolation is intentionally out of scope for this implementation.