> ## Documentation Index
> Fetch the complete documentation index at: https://docs.velesagent.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Hermes and Veles Agent Personality Handling

> Technical comparison of how Hermes and Veles assemble agent identity, project instructions, and workspace-backed personalities.

# 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:

```python theme={null}
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:

```python theme={null}
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:

```text theme={null}
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:

```python theme={null}
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:

| Concept                   | Hermes                                    | Veles                                           |
| ------------------------- | ----------------------------------------- | ----------------------------------------------- |
| Default personality       | `SOUL.md` identity slot                   | workspace-root `SOUL.md` for `main` Personality |
| Project instructions      | `AGENTS.md` as project context            | workspace-root `AGENTS.md` as project context   |
| Custom identity           | Profile with its own `SOUL.md`            | `personalities/<id>/SOUL.md`                    |
| Temporary personality     | `agent.system_prompt` / ephemeral overlay | not used for first-class Personalities          |
| Injection point           | System prompt                             | system prompt identity/personality layer        |
| Persistence               | Hermes profile directory/config           | workspace Markdown identity files               |
| Memory/sessions/workspace | profile-isolated                          | shared 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.
