Add all custom Hermes skills from general profile (33 skills)
agent-workflows: workspace-context-organization autonomous-ai-agents: hermes-agent computer-use devops: hermes-config-bulk-update, hermes-profile-management, holographic-memory, telegram-integration, webhook-subscriptions email: himalaya mcp: native-mcp, searxng-smart-search media: voice-systems, youtube-content mlops: local-vector-memory, qdrant-collection-management productivity: maps, notion, ocr-and-documents project-knowledge-base research: arxiv, blogwatcher, ecosystem-surveillance save-agents-md social-media: social-media-scraping, xurl software-development: agent-self-audit, simplify-code, spike, subagent-driven-development, systematic-debugging, test-driven-development, writing-plans user-response-style
This commit is contained in:
411
hermes-profile-management/SKILL.md
Normal file
411
hermes-profile-management/SKILL.md
Normal file
@@ -0,0 +1,411 @@
|
||||
---
|
||||
name: hermes-profile-management
|
||||
description: "Create, configure, and validate Hermes profiles with linked workspaces. Covers the full lifecycle: clone, model selection, cwd binding, AGENTS.md seeding, and two-round validation."
|
||||
version: 1.1.0
|
||||
author: agent
|
||||
license: MIT
|
||||
platforms: [linux]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [hermes, profiles, workspace, configuration, setup]
|
||||
related_skills: [hermes-agent, hermes-config-bulk-update]
|
||||
---
|
||||
|
||||
# Hermes Profile Management
|
||||
|
||||
Create and configure Hermes profiles with linked workspace directories. This skill covers the standard workflow for spinning up a new profile, binding it to a workspace, and validating everything is correct.
|
||||
|
||||
## Trigger Conditions
|
||||
|
||||
- User asks to create a new Hermes profile
|
||||
- User asks to set up a workspace for a specific purpose (VS Code, coding, research, etc.)
|
||||
- User asks to clone an existing profile for a new use case
|
||||
- User says they already cloned/copied a profile and asks to "finish setup" or "update files" — see Audit Mode below
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Hermes Agent installed and configured
|
||||
- At least one existing profile to clone from (usually `general`)
|
||||
- Workspace directory convention: `/home/n8n/workspace/<profile-name>/`
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Survey Current State
|
||||
|
||||
Before creating anything, check what exists:
|
||||
|
||||
```bash
|
||||
hermes profile list # See all profiles, models, gateway status
|
||||
ls -la /home/n8n/workspace/ # See existing workspace directories
|
||||
```
|
||||
|
||||
### 2. Confirm Model Choice
|
||||
|
||||
Ask the user which model to use. Present the most common options from existing profiles. Default to `deepseek-v4-pro:cloud` if the user doesn't specify — it's the most common choice across profiles.
|
||||
|
||||
### 3. Create Workspace Directory
|
||||
|
||||
```bash
|
||||
mkdir -p /home/n8n/workspace/<profile-name>
|
||||
```
|
||||
|
||||
### 4. Create Profile (Clone from Source)
|
||||
|
||||
```bash
|
||||
hermes profile create <name> --clone-from <source-profile>
|
||||
```
|
||||
|
||||
This copies config.yaml, .env, SOUL.md, and skills from the source.
|
||||
|
||||
### 5. Bind Workspace to Profile
|
||||
|
||||
Set BOTH keys — they are independent and both required:
|
||||
|
||||
```bash
|
||||
hermes config set terminal.cwd /home/n8n/workspace/<name> --profile <name>
|
||||
hermes config set workspace /home/n8n/workspace/<name> --profile <name>
|
||||
```
|
||||
|
||||
`terminal.cwd` controls where shell commands start. `workspace:` controls which workspace root Hermes loads AGENTS.md / CLAUDE.md / .cursorrules from. A profile with only one set will have subtle failures (wrong context files loaded, or commands running from home directory).
|
||||
|
||||
### 6. Create AGENTS.md
|
||||
|
||||
Write `/home/n8n/workspace/<name>/AGENTS.md` with:
|
||||
- Profile name and purpose
|
||||
- Model and provider
|
||||
- Usage notes
|
||||
- Any profile-specific conventions
|
||||
|
||||
### 7. Validate (Two Rounds)
|
||||
|
||||
**Round 1 — Structural:**
|
||||
```bash
|
||||
hermes profile show <name> # Profile exists, model correct
|
||||
ls -la /home/n8n/workspace/<name>/ # Directory exists, AGENTS.md present
|
||||
grep "cwd:" ~/.hermes/profiles/<name>/config.yaml # cwd points to workspace
|
||||
grep -A3 "^model:" ~/.hermes/profiles/<name>/config.yaml | head -4 # Model correct
|
||||
```
|
||||
|
||||
**Round 2 — Functional:**
|
||||
```bash
|
||||
hermes -p <name> config check # Config passes health check
|
||||
touch /home/n8n/workspace/<name>/.test_write && rm /home/n8n/workspace/<name>/.test_write # Writable
|
||||
hermes profile list | grep <name> # Appears in profile list
|
||||
hermes -p <name> config # Full config dump confirms settings
|
||||
```
|
||||
|
||||
## Audit Mode (Partially-Completed Clones)
|
||||
|
||||
When the user says they already cloned a profile or copied a workspace but asks you to "finish setup" or "update files," do NOT assume the standard workflow steps are done. Audit each layer before fixing:
|
||||
|
||||
1. **Workspace dir**: `ls -la /home/n8n/workspace/<name>/` — may not exist even if the profile does. Create + copy from source if missing.
|
||||
2. **cwd binding**: `grep "cwd:" ~/.hermes/profiles/<name>/config.yaml` — often still `.` or unset. Bind it: `hermes config set terminal.cwd /home/n8n/workspace/<name> --profile <name>`
|
||||
3. **AGENTS.md**: Check if it still references the source profile name/path. Rewrite for the new workspace (workspace path, purpose, model, provider, hindsight note).
|
||||
4. **Cloned cron jobs**: `cat ~/.hermes/profiles/<name>/cron/jobs.json` — the clone inherits ALL of the source's cron jobs. Any job that writes to a shared resource (Qdrant collection, database, file path) will now run TWICE — once from each profile. Pause or delete duplicates in the new profile. This is the most commonly missed step.
|
||||
5. **Hindsight bank_id (LEGACY — migrated to Holographic 2026-07-01)**: `cat ~/.hermes/profiles/<name>/hindsight/config.json` — the clone inherits the source's `bank_id` (e.g., `hermes`). Memories are SHARED across both profiles, not isolated. This is usually fine for dev/test profiles but document it in AGENTS.md so the operator knows. If isolation is needed, change `bank_id` to a unique value.
|
||||
6. **Config version**: `hermes -p <name> config check` — the clone may be behind the source's config version. Run `hermes -p <name> config migrate` if so.
|
||||
|
||||
## Profile Deletion
|
||||
|
||||
When the user asks to remove profiles, follow this workflow:
|
||||
|
||||
### 1. List and Number
|
||||
|
||||
Present all profiles as a numbered list so the user can pick by number. Use `hermes profile list` and number them sequentially.
|
||||
|
||||
### 2. Confirm Workspaces
|
||||
|
||||
Before deleting, check which profiles have matching workspace directories:
|
||||
|
||||
```bash
|
||||
for p in <profile_names>; do ls -d ~/workspace/$p 2>/dev/null && echo "exists" || echo "no workspace"; done
|
||||
```
|
||||
|
||||
### 3. Delete Workspaces First
|
||||
|
||||
Workspaces are just directories — remove them directly:
|
||||
|
||||
```bash
|
||||
rm -rf ~/workspace/<name>
|
||||
```
|
||||
|
||||
### 4. Delete Profiles (Interactive Confirmation)
|
||||
|
||||
`hermes profile delete` requires interactive confirmation — you must type the profile name. Pipe it in:
|
||||
|
||||
```bash
|
||||
echo "<name>" | hermes profile delete <name>
|
||||
```
|
||||
|
||||
There is no `--force` flag. The confirmation prompt is mandatory.
|
||||
|
||||
### 5. Verify
|
||||
|
||||
```bash
|
||||
hermes profile list # Profile gone
|
||||
ls ~/workspace/<name> 2>&1 # Workspace gone (No such file or directory)
|
||||
```
|
||||
|
||||
### Pitfalls
|
||||
|
||||
- **`--force` does not exist**: `hermes profile delete` has no `--force` flag. The only way to automate is piping the name to stdin.
|
||||
- **Delete workspaces before profiles**: Workspaces are simple `rm -rf`. Profiles require interactive confirmation. Do workspaces first so if the profile delete fails, you haven't lost the workspace yet.
|
||||
- **Never delete the active profile**: The current profile (marked with ◆) cannot be deleted while in use. Switch away first if needed.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- **model.base_url MUST match model.default (critical, silent failure)**: The #1 silent error in cloned configs. `model.default` names a model, `model.base_url` points at the endpoint that serves it. If the source profile's `base_url` was an Epyc vLLM endpoint (10.0.0.26:8000, serves only `qwen3.6-35b-a3b-uncensored`) and the new profile's `model.default` is `minimax-m3:cloud` (served by Ollama at localhost:11434), the primary model will silently fail to load. ALWAYS cross-check: if model.default is a `:cloud` Ollama-routed model, base_url must be `http://localhost:11434/v1`, NOT an Epyc/DGX endpoint. The fix: `config['model']['base_url'] = 'http://localhost:11434/v1'` for any Ollama-routed primary model.
|
||||
- **context_length: 131072, not 262144**: DGX qwen3 DFlash has a native max context of 262,144 tokens, but you MUST configure `model.context_length: 131072`. The DGX vLLM runs `max_num_seqs: 3` with a shared ~457K token KV pool. Setting 262144 limits you to 1 concurrent stream; 131072 allows 3 streams. Epyc qwen3.6-35b uses 262144 (single stream, no KV pool sharing).
|
||||
- **browser.allow_private_urls must match security.allow_private_urls**: If `security.allow_private_urls: true` but `browser.allow_private_urls: false`, the browser tool will silently block LAN URLs (10.0.0.x) even though security permits them. ALWAYS set both to the same value.
|
||||
- **display.platforms leftovers after section removal**: Removing the top-level `telegram:` and `discord:` sections does NOT remove `display.platforms.telegram` and `display.platforms.discord`. After removing platform sections, explicitly clean `display.platforms` (set to `{}` for non-gateway profiles).
|
||||
- **Clone inherits base_url**: The cloned profile gets the source's `model.base_url`. If the source uses a remote endpoint (e.g., `http://10.0.0.26:8000/v1`), the new profile will too. This is usually correct but verify if the profile needs a different backend.
|
||||
- **Clone inherits cron jobs**: The clone gets a COPY of the source's `cron/jobs.json`. Any job that targets shared infrastructure (Qdrant, databases, file paths) will execute from both profiles on the same schedule. Always audit and pause/delete duplicates in the new profile. This is the #1 missed step in partial-clone setups.
|
||||
- **Clone inherits hindsight bank_id (LEGACY — migrated to Holographic 2026-07-01)**: Memories are shared across profiles with the same `bank_id`. NOT isolated by default. For all profiles except `general`, change `bank_id` in `hindsight/config.json` to `hermes-<profile>` (e.g. `hermes-dev`, `hermes-finance`). Only `general` keeps `bank_id: hermes` (shared, primary). **The `hindsight/` directory may not be copied at all during clone** — if `~/.hermes/profiles/<name>/hindsight/config.json` doesn't exist, create the directory and write config.json from scratch (mirror the source profile's config.json but change `bank_id`). Without a profile-level config.json, the profile falls back to the base `~/.hermes/hindsight/config.json` which has `bank_id: hermes` — the cross-profile bank_id leak pitfall.
|
||||
- **Clone inherits config version**: May be behind the source. Run `hermes config migrate` to bring it current.
|
||||
- **AGENTS.md still references source workspace**: Copied workspace files still have the old workspace path and purpose. Rewrite AGENTS.md for the new profile.
|
||||
- **Profile alias**: `hermes profile create` auto-creates a wrapper at `~/.local/bin/<name>`. Use it as `vscode chat` or `hermes -p vscode`.
|
||||
- **Skills are cloned**: The new profile gets a copy of the source's skills directory. They diverge independently after creation.
|
||||
- **Fallback model should be DGX qwen, not Ollama**: The standard fallback is `qwen` via DGX (http://10.0.0.6:8000/v1, api_key: dummy), NOT another Ollama model. DGX is the failover endpoint — if Ollama is down, the fallback must point at a different infrastructure, not the same one.
|
||||
- **cronjob tool pause may not persist to jobs.json**: The `cronjob action='pause'` tool reports success and returns `enabled: false, state: paused` in its response, but the on-disk `cron/jobs.json` may still show `enabled: true, state: scheduled` on next read. The tool's in-memory state and the file can diverge. After pausing, ALWAYS verify by reading jobs.json directly, and if it didn't persist, write the pause directly: `j['enabled']=False; j['state']='paused'; j['paused_at']=<iso>; j['paused_reason']=<reason>` and dump back to the file. This is the only reliable way to pause a cloned cron job.
|
||||
- **.env HINDSIGHT_LLM_* may point to wrong endpoint after clone**: The cloned .env may have `HINDSIGHT_LLM_BASE_URL=http://localhost:11434/v1` (Ollama) and `HINDSIGHT_LLM_MODEL=qwen3:8b` while hindsight/config.json correctly points to Epyc (`http://10.0.0.26:8000/v1`, `qwen3.6-35b-a3b-uncensored`). The .env overrides config.json at runtime. ALWAYS check .env's HINDSIGHT_LLM_MODEL and HINDSIGHT_LLM_BASE_URL match config.json — the Hindsight LLM does extraction/synthesis and must use the strongest reasoning model (Epyc), not local Ollama.
|
||||
- **Hindsight bank-level config is missing on cloned/new banks**: When a new bank_id is first used (e.g. `hermes-dev`), Hindsight auto-creates it with ALL defaults (concise extraction, no memory defense, 2048 recall tokens, no disposition, no missions). You MUST apply the bank-level config via the daemon API after the bank exists. See `references/hindsight-bank-config-apply.md` for the API path, payload format, and replication script.
|
||||
- **The `patch` tool refuses writes to config.yaml**: You cannot use the `patch` tool on `~/.hermes/profiles/<name>/config.yaml` — it errors with "Agent cannot modify security-sensitive configuration." Use `hermes config set <key> <value>` instead, which writes safely and confirms the change. For the top-level `workspace:` key: `hermes config set workspace /workspace/<name>`. For `terminal.cwd`: `hermes config set terminal.cwd /home/n8n/workspace/<name>`. Both keys exist independently — `workspace:` controls which workspace's AGENTS.md gets auto-loaded, `terminal.cwd` controls the shell's starting directory. When binding a profile to its workspace, set BOTH.
|
||||
- **`workspace:` key vs `terminal.cwd` are independent**: The top-level `workspace:` key (e.g. `/workspace/general`) controls which workspace root Hermes loads AGENTS.md / CLAUDE.md / .cursorrules from. The `terminal.cwd` key controls where shell commands start. They can diverge after a clone or partial setup — always verify both point at the intended workspace for the active profile.
|
||||
- **Symptom: model lists files from home directory instead of workspace**: When `terminal.cwd: .` (the default), the session starts in whatever directory the process was launched from — typically `/home/n8n`. If the user says "list md files in your workspace" and the model returns files from the home folder (random scripts, memory files, etc.) instead of `~/workspace/<profile>/`, the cwd is unbound. Fix: `hermes config set terminal.cwd /home/n8n/workspace/<profile>`. This is the #1 cause of "model is looking at wrong files" confusion.
|
||||
|
||||
- **SOUL.md text duplicated via CLAUDE.md/AGENTS.md**: SOUL.md is loaded as identity (slot #1 in stable tier). CLAUDE.md/AGENTS.md are loaded as project context (separate code path in context tier). `skip_soul` only prevents SOUL.md from being loaded twice — it does NOT skip CLAUDE.md or AGENTS.md. If `~/workspace/CLAUDE.md` contains the same persona text as SOUL.md, the model sees it twice: once as "who I am" and once as "project instructions I should follow." Fix: keep CLAUDE.md/AGENTS.md for project-specific instructions (build commands, conventions, architecture), not persona text. Delete workspace-level CLAUDE.md if it only contains SOUL.md content.
|
||||
|
||||
- **agent.system_prompt config key**: `hermes config set agent.system_prompt "text"` appends text to the system prompt after the identity block. It augments, not replaces. Useful for injecting directives that must appear in every session without editing SOUL.md. Unlike SOUL.md, this is per-profile (set in each profile's config.yaml).
|
||||
|
||||
- **memory.write_approval config flag**: `hermes config set memory.write_approval true` gates ALL memory tool writes (add/replace/remove) to MEMORY.md and USER.md. When true, foreground writes prompt inline for approval; background-review writes are staged for `/memory pending` / `/memory approve` / `/memory reject`. Default is false (writes happen freely). This only gates the built-in `memory` tool — it does NOT affect Holographic/fact_store writes. Stronger than a SOUL.md directive since it's enforced at the tool level. **Per-profile, not global** — must be set in each profile's config.yaml. Use the `hermes-config-bulk-update` pattern to apply across all profiles in one pass.
|
||||
|
||||
- **Temperature is set in THREE places, not one**: A profile's temperature lives in three independent locations: (1) `moa.presets.<name>.reference_temperature` — the research sub-agent's reference stage, (2) `moa.presets.<name>.aggregator_temperature` — the research sub-agent's aggregation stage, (3) `custom_providers[].extra_body.temperature` — the main model's temperature passed via the Ollama provider's extra_body. All three must be set to the same value for consistent behavior. The main model temperature is NOT a top-level `model.temperature` key — it's embedded in the provider's `extra_body` block. To set all three: `sed` for the MOA temps (simple value replacement), and `patch` or `execute_code` to insert `extra_body: { temperature: 0.3 }` into the Ollama provider block (which may not exist yet). See `references/temperature-config.md` for the full pattern.
|
||||
|
||||
## SOUL.md Symlink Propagation (One File, All Profiles)
|
||||
|
||||
Instead of maintaining independent SOUL.md copies per profile, use a single canonical file with symlinks. `load_soul_md()` does `get_hermes_home() / "SOUL.md"` — a simple file read, so symlinks are transparent.
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
# 1. Write canonical SOUL.md once
|
||||
# (edit ~/.hermes/SOUL.md with the desired persona)
|
||||
|
||||
# 2. Replace all profile SOUL.md files with symlinks
|
||||
for p in ~/.hermes/profiles/*/; do
|
||||
rm -f "$p/SOUL.md"
|
||||
ln -s ../../SOUL.md "$p/SOUL.md"
|
||||
done
|
||||
|
||||
# 3. Verify
|
||||
for p in ~/.hermes/profiles/*/SOUL.md; do
|
||||
profile=$(basename "$(dirname "$p")")
|
||||
if [ -L "$p" ]; then
|
||||
echo "$profile: symlink OK ($(wc -c < "$p") bytes)"
|
||||
else
|
||||
echo "$profile: NOT A SYMLINK"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
One edit to `~/.hermes/SOUL.md` updates all profiles instantly. No copying, no drift.
|
||||
|
||||
### Pitfalls
|
||||
|
||||
- **The `general` profile may have the default 513-byte SOUL.md** while other profiles have a custom one. Symlinking replaces the default with the custom persona — this is usually desired but verify the canonical file has the intended content first.
|
||||
- **SOUL.md is for identity/tone/style, not operational directives.** The docs recommend keeping SOUL.md focused on persona. Operational rules (search protocols, validation steps) belong in AGENTS.md or `agent.system_prompt`. A bloated SOUL.md competes with built-in guidance and can cause inconsistent model behavior.
|
||||
- **`skip_soul` is not a config toggle.** It's hardcoded logic in `agent/system_prompt.py` line 418: `skip_soul=_soul_loaded`. `_soul_loaded` is True when SOUL.md successfully loads as identity, preventing it from being loaded again as a context file. This only skips SOUL.md — it does NOT skip CLAUDE.md, AGENTS.md, or any other context file.
|
||||
|
||||
## Audit Checklist Quick Reference
|
||||
|
||||
When auditing a partially-completed clone, run these in order:
|
||||
|
||||
```bash
|
||||
# 1. Workspace dir exists?
|
||||
ls -la /home/n8n/workspace/<name>/
|
||||
|
||||
# 2. cwd bound?
|
||||
grep "cwd:" ~/.hermes/profiles/<name>/config.yaml
|
||||
|
||||
# 3. AGENTS.md references correct workspace?
|
||||
head -5 /home/n8n/workspace/<name>/AGENTS.md
|
||||
|
||||
# 4. Cloned cron jobs — check for duplicates that target shared resources
|
||||
python3 -c "
|
||||
import json
|
||||
with open('/home/n8n/.hermes/profiles/<name>/cron/jobs.json') as f:
|
||||
data = json.load(f)
|
||||
jobs = data if isinstance(data, list) else data.get('jobs', [])
|
||||
for j in jobs:
|
||||
if isinstance(j, dict):
|
||||
print(f'{j.get(\"id\",\"?\")}: {j.get(\"name\",\"?\")} | enabled={j.get(\"enabled\",True)} | deliver={j.get(\"deliver\",\"origin\")}')
|
||||
"
|
||||
|
||||
# 5. Hindsight bank_id — shared or isolated?
|
||||
grep bank_id ~/.hermes/profiles/<name>/hindsight/config.json
|
||||
|
||||
# 6. Config version current?
|
||||
hermes -p <name> config check
|
||||
```
|
||||
|
||||
## Config Deep-Clean & Optimization
|
||||
|
||||
When the user asks to "update," "fix," or "optimize" a profile's config.yaml, follow this workflow:
|
||||
|
||||
### Phase 1 — Read-Only Audit (always first)
|
||||
|
||||
Read the full config.yaml and produce a categorized summary BEFORE making any changes:
|
||||
- **Stale references**: workspace paths pointing to wrong profile, leaked keys (TELEGRAM_HOME_CHANNEL), old config version
|
||||
- **Unused platform sections**: slack, discord, telegram, mattermost, matrix, bedrock, moa — remove if gateway is stopped and no platforms configured
|
||||
- **Platform toolsets**: trim to only the platforms actually used (usually just `cli`)
|
||||
- **Empty values that should be filled**: delegation.api_mode, delegation.reasoning_effort, stt.local.language, timezone
|
||||
- **Intentionally empty (leave alone)**: dashboard auth, browser cdp_url, cron chronos, terminal docker_*, security blocklist domains, TTS provider-specific fields for unused providers
|
||||
|
||||
Present the summary to the user and ask whether to proceed before editing.
|
||||
|
||||
### Phase 2 — Clean & Remove
|
||||
|
||||
Use `execute_code` with `yaml.safe_load` / `yaml.dump` (sort_keys=False, allow_unicode=True, width=120) for bulk changes in one pass:
|
||||
- Remove unused platform sections, bedrock, moa, smart_model_routing (if unwanted)
|
||||
- Remove stale workspace: key, leaked TELEGRAM_HOME_CHANNEL
|
||||
- Remove stale custom_providers and their model_aliases (e.g., remove Nous entries and all nous-* aliases)
|
||||
- Trim platform_toolsets to cli only
|
||||
- Run `hermes -p <name> config migrate` to update _config_version
|
||||
|
||||
### Phase 3 — Max & Optimize Settings
|
||||
|
||||
When the user says "max" or "full permission" or "don't ask", apply the max/permissive config pattern. See `references/profile-config-deep-clean.md` in the `hermes-config-bulk-update` skill for the full value table. Key changes:
|
||||
- **Permissions**: approvals.mode off, cron_mode off, hooks_auto_accept true, subagent_auto_approve true, allow_private_urls true
|
||||
- **Limits**: agent.max_turns 300, max_live_sessions 32, terminal.timeout 600, tool_output.max_bytes 50000, file_read_max_chars 200000
|
||||
- **Auxiliary models**: set all 18 tasks to explicit provider/model/base_url (not auto) — use local Ollama models (kimi for light, deepseek for reasoning, gemini-3-flash for vision)
|
||||
- **Fallback**: configure fallback_model + fallback_providers to local Ollama
|
||||
- **Delegation**: set provider/model/base_url (was empty), max_iterations 300, max_concurrent_children 5, max_spawn_depth 3
|
||||
|
||||
### Phase 4 — Test Infrastructure
|
||||
|
||||
Before declaring done, test every endpoint referenced in the config:
|
||||
```bash
|
||||
curl -s --connect-timeout 3 http://localhost:11434/api/tags # Ollama
|
||||
curl -s --connect-timeout 3 http://10.0.0.26:8000/v1/models # vLLM epyc
|
||||
curl -s --connect-timeout 3 http://10.0.0.8:8888 # SearXNG
|
||||
curl -s --connect-timeout 3 http://10.0.0.22:6333/collections # Qdrant
|
||||
```
|
||||
Test auxiliary models respond:
|
||||
```bash
|
||||
curl -s http://localhost:11434/v1/chat/completions -H "Content-Type: application/json" \
|
||||
-d '{"model":"<model>","messages":[{"role":"user","content":"Reply with exactly: hello there"}],"max_tokens":100}'
|
||||
```
|
||||
Note: `:cloud` models via Ollama proxy may return empty content with `max_tokens: 5` — use 100+ tokens for a valid response.
|
||||
|
||||
### Phase 5 — Empty-Value Scan
|
||||
|
||||
Run a recursive scan for all empty/null/0/[] values, then categorize:
|
||||
- **Must fill**: delegation.api_mode (chat), delegation.reasoning_effort (high), stt.local.language (en), timezone (America/Chicago)
|
||||
- **Optional**: display.pet.slug (only if pet enabled)
|
||||
- **Intentionally empty**: dashboard auth, browser cdp_url, cron chronos, terminal docker_*, etc. — leave alone
|
||||
|
||||
### Phase 6 — Validate
|
||||
|
||||
```bash
|
||||
hermes -p <name> config check # Config version current, YAML valid
|
||||
hermes profile show <name> # Model, provider, skills count
|
||||
hermes -p <name> config # Full config dump
|
||||
```
|
||||
|
||||
### Key Architectural Facts
|
||||
|
||||
- **Profiles do NOT inherit from base `~/.hermes/config.yaml`.** Each profile's config.yaml is standalone — merged only with hardcoded DEFAULT_CONFIG at runtime. Nothing falls through from base. A profile must have all settings it needs in its own config.yaml.
|
||||
- **Credential pool (`~/.hermes/auth.json`) IS shared across all profiles** — even when HERMES_HOME points at a profile path. That's why all profiles can use the same API keys without duplicating them.
|
||||
- **Hindsight bank_id is shared across cloned profiles** — memories are NOT isolated by default. Change bank_id in hindsight/config.json if isolation is needed.
|
||||
|
||||
## Clean Cloned Junk (Workspace + Profile)
|
||||
|
||||
Cloning copies EVERYTHING — including the source profile's runtime state, logs, caches, and scratch files. This bloats the new profile by ~800MB+ and carries stale state that can cause confusion. Always clean after cloning.
|
||||
|
||||
### Workspace — remove source profile's scratch files
|
||||
|
||||
Files cloned from `general/workspace/` that don't belong to the new profile:
|
||||
- `memories-organizer-log.json`, `memories-org-*.py`, `memories-*-batch.json` — source's cron job artifacts
|
||||
- `qdrant-collections.json`, `hindsight-validation.md` — source's reference notes
|
||||
- `stt_server.py`, `claude_code.md`, `jotty.md` — source's reference docs
|
||||
- `docs/` dir — source's reference docs (how_agent_loop_works.md, etc.)
|
||||
- `scripts/` dir if empty
|
||||
- Keep: `AGENTS.md` (after rewriting it for the new profile)
|
||||
|
||||
### Profile — remove cloned runtime state and caches
|
||||
|
||||
These all regenerate or are stale:
|
||||
- `gateway.lock`, `gateway.pid`, `gateway_state.json`, `gateway_voice_mode.json` — stale gateway state (gateway is stopped)
|
||||
- `channel_directory.json` — has source's Telegram/Discord channels
|
||||
- `interrupt_debug.log` — cloned debug log
|
||||
- `checkpoints/store/` contents — cloned snapshots (especially if checkpoints disabled)
|
||||
- `state-snapshots/` — cloned pre-update snapshots (can be 80MB+)
|
||||
- `logs/agent.log*`, `logs/errors.log*`, `logs/gateway*.log*`, `logs/mcp-stderr.log`, `logs/hindsight-embed.log`, `logs/update.log`, `logs/curator/` — all cloned (can be 120MB+)
|
||||
- `models_dev_cache.json`, `ollama_cloud_models_cache.json`, `provider_models_cache.json`, `context_length_cache.yaml` — caches regenerate
|
||||
- `cache/openrouter_model_metadata.json`, `cache/model_catalog.json` — caches regenerate
|
||||
- `config.yaml.bak.*` — stale backups
|
||||
- `mem0.json` — if using hindsight, not mem0
|
||||
- `sessions/*` — cloned session transcripts (start fresh)
|
||||
- `state.db`, `state.db-shm`, `state.db-wal` — cloned SQLite (start fresh; 90MB+)
|
||||
- `verification_evidence.db` — cloned
|
||||
- `.hermes_history` — cloned shell history
|
||||
- `audio_cache/*`, `pastes/*`, `image_cache/*`, `images/*` — cloned media
|
||||
|
||||
### Do NOT remove (functional):
|
||||
- `bin/` (tirith, uv, uvx binaries — 80MB, functional)
|
||||
- `lsp/` (language servers — 37MB, functional)
|
||||
- `skills/` (skills directory — 20MB, functional)
|
||||
- `cron/jobs.json` (cron job definitions — keep, just pause duplicates per Audit Mode)
|
||||
- `hindsight/config.json` (hindsight config — keep)
|
||||
- `.env` (API keys — keep)
|
||||
- `auth.json` (credential pool — keep, shared across profiles)
|
||||
- `SOUL.md` (personality — keep)
|
||||
- `config.yaml` (the config — keep)
|
||||
|
||||
**Expected result**: profile dir drops from ~960MB to ~140MB. Remaining size is bin+lsp+skills (all functional).
|
||||
|
||||
A full itemized checklist for the entire profile setup workflow (including junk cleanup) is in `references/profile-setup-checklist.md`.
|
||||
|
||||
## Cross-Profile Cron Health Audit (Operational)
|
||||
|
||||
Beyond clone-time cleanup (Audit Mode step 4 above), you may need to audit cron health across ALL profiles at runtime — "check all cron jobs worked." The `cronjob action='list'` tool only sees the current profile; it does not enumerate other profiles' jobs. You must inspect each profile's `cron/jobs.json`, ticker timestamps, and output dirs directly. This also covers identifying and removing orphaned duplicate jobs (same job_id inherited via clone, sitting dead in a profile whose gateway no longer runs).
|
||||
|
||||
Full procedure: `references/cross-profile-cron-audit.md`.
|
||||
|
||||
## Remote ACP / VS Code Setup
|
||||
|
||||
When Hermes runs in an LXC/container on the network and VS Code is on a laptop, ACP (stdio-based) needs a bridge. See `references/remote-acp-vscode.md` for the full breakdown of options and the fundamental filesystem limitation.
|
||||
|
||||
## Post-Config Validation
|
||||
|
||||
After any deep-clean or optimization, run a structured validation pass BEFORE declaring done. `hermes config check` only validates YAML parse + version — it does NOT catch semantic errors like wrong endpoint for a model, shared hindsight banks, or missing env vars.
|
||||
|
||||
Key validation steps:
|
||||
1. Test all infrastructure endpoints are live (curl each one)
|
||||
2. Test primary + fallback models respond (note: `:cloud` models need max_tokens 100+, reasoning models need 500+)
|
||||
3. **Cross-check model.base_url matches model.default** — the #1 silent failure: model name on one endpoint, base_url pointing at a different endpoint that doesn't serve that model (e.g., `minimax-m3:cloud` with `base_url: http://10.0.0.26:8000/v1` — epyc only serves qwen3.6-35b)
|
||||
4. Check hindsight bank_id isolation (general=shared, others should be isolated)
|
||||
5. Scan for empty values that should be filled (delegation.api_mode, stt.local.language, timezone)
|
||||
6. Check for leftover platform references after section removal
|
||||
7. Verify .env keys are set for config references (FIRECRAWL_API_KEY, SEARXNG_URL, HINDSIGHT_*)
|
||||
|
||||
Surface decision points to the user: hindsight bank isolation, model.context_length, browser vs security allow_private_urls alignment.
|
||||
|
||||
Full validation script and cross-check code: `references/post-config-validation.md`.
|
||||
|
||||
## Support Files
|
||||
|
||||
- `references/remote-acp-vscode.md` — Remote Hermes + VS Code ACP: SSH tunnel options, filesystem limitation, and workarounds
|
||||
- `references/profile-setup-checklist.md` — Full 22-step checklist for profile setup (workspace, cron, config cleanup, permissions, max settings, fallback, junk cleanup, validation). Copy this into the new profile's workspace as a tracking doc.
|
||||
- `references/post-config-validation.md` — Structured post-config validation pass: endpoint testing, model respond tests, base_url/model cross-check, hindsight bank audit, empty-value scan, decision points to surface to user.
|
||||
- `references/dgx-qwen3-dflash-details.md` — DGX qwen3 DFlash technical reference: endpoint, context_length 131072 (not 262144), 3-stream KV pool, tool calling, performance metrics, testing (needs 500+ max_tokens).
|
||||
- `references/cross-profile-cron-audit.md` — Cross-profile cron health audit: the cronjob tool only sees the current profile, so filesystem inspection is required. Covers ticker health, run output dirs, orphaned duplicate detection, and cross-profile job removal.
|
||||
- `references/hindsight-bank-config-apply.md` — Hindsight bank-level config application: API path (`/v1/default/banks/<id>/config`), `updates` wrapper format (flat PATCH returns 422), replication script to copy general's overrides to a new bank.
|
||||
- `references/soul-md-propagation.md` — SOUL.md system-wide propagation: 23 locations, one-at-a-time workflow, diff-based validation, pitfalls.
|
||||
- `references/system-prompt-assembly.md` — Full system prompt assembly reference: three tiers, key files, config toggles, SOUL.md vs context files, symlink pattern.
|
||||
- `scripts/profile-config-automation.py` — Standalone Python script that applies the full deep-clean + max/optimize config pattern. Run as `python3 profile-config-automation.py <profile_name>` after cloning. Handles all config changes in one pass.
|
||||
- `references/profile-launch-slowdown-diagnosis.md` — Diagnose why a profile takes several seconds longer to launch than others: MCP connection failures, skill count, state.db size, checkpoints. Includes diagnostic script.
|
||||
- `references/skill-pruning-workflow.md` — Systematic skill pruning: group by likelihood tier, present as numbered list, remove LOW, re-list, remove specific MEDIUM items by number. Covers nested subdirectory cleanup and verification.
|
||||
- `references/mcp-server-http-sharing.md` — Convert per-profile stdio MCP servers to a single shared HTTP instance with systemd persistence. Eliminates redundant npx processes and cold-start delays across profiles.
|
||||
- `references/temperature-config.md` — Temperature is set in THREE places (MOA reference, MOA aggregator, Ollama provider extra_body). Full pattern for setting all three consistently.
|
||||
- `references/telegram-bot-token-conflict.md` — Diagnose and fix Telegram bot token conflicts where messages route to the wrong profile because two gateways compete for the same token.
|
||||
Reference in New Issue
Block a user