feat: add profiles — run multiple isolated Hermes instances#3681
Merged
feat: add profiles — run multiple isolated Hermes instances#3681
Conversation
81bc7ac to
d774104
Compare
Each profile is a fully independent HERMES_HOME with its own config,
API keys, memory, sessions, skills, gateway, cron, and state.db.
Core module: hermes_cli/profiles.py (~900 lines)
- Profile CRUD: create, delete, list, show, rename
- Three clone levels: blank, --clone (config), --clone-all (everything)
- Export/import: tar.gz archive for backup and migration
- Wrapper alias scripts (~/.local/bin/<name>)
- Collision detection for alias names
- Sticky default via ~/.hermes/active_profile
- Skill seeding via subprocess (handles module-level caching)
- Auto-stop gateway on delete with disable-before-stop for services
- Tab completion generation for bash and zsh
CLI integration (hermes_cli/main.py):
- _apply_profile_override(): pre-import -p/--profile flag + sticky default
- Full 'hermes profile' subcommand: list, use, create, delete, show,
alias, rename, export, import
- 'hermes completion bash/zsh' command
- Multi-profile skill sync in hermes update
Display (cli.py, banner.py, gateway/run.py):
- CLI prompt: 'coder ❯' when using a non-default profile
- Banner shows profile name
- Gateway startup log includes profile name
Gateway safety:
- Token locks: Discord, Slack, WhatsApp, Signal (extends Telegram pattern)
- Port conflict detection: API server, webhook adapter
Diagnostics (hermes_cli/doctor.py):
- Profile health section: lists profiles, checks config, .env, aliases
- Orphan alias detection: warns when wrapper points to deleted profile
Tests (tests/hermes_cli/test_profiles.py):
- 71 automated tests covering: validation, CRUD, clone levels, rename,
export/import, active profile, isolation, alias collision, completion
- Full suite: 6760 passed, 0 new failures
Documentation:
- website/docs/user-guide/profiles.md: full user guide (12 sections)
- website/docs/reference/profile-commands.md: command reference (12 commands)
- website/docs/reference/faq.md: 6 profile FAQ entries
- website/sidebars.ts: navigation updated
d774104 to
aa1848d
Compare
Contributor
|
sir , I'm not entirely sure, but I wanted to point out a possible bug here If the environment were to change between those two calls (for example with the new profile system), the value used to release the lock might differ from the one used to acquire it, which could leave the original lock unreleased. Other adapters seem to store the identity at connect time and reuse it during disconnect. Maybe Slack should follow the same pattern, but I might be misunderstanding the flow. |
d748928 to
08f3bca
Compare
eloklam
added a commit
to eloklam/hermes-agent
that referenced
this pull request
Mar 29, 2026
Add OhMyOpenCode-style multi-agent orchestration enabling one profile to delegate tasks to other profiles via HTTP with full conversation history passing and SQLite persistence. Features: - Profile-to-profile delegation via HTTP (sync and async modes) - Full conversation history passing between multi-turn delegations - Async mode with SQLite persistence (survives process restarts) - Cross-task memory loading from previous orchestration tasks - ThreadPoolExecutor for reliability (simplified from aiohttp) - Dual lookup pattern: memory + SQLite for check_profile_task Bug Fixes: - UnboundLocalError: 'json' (removed local import shadowing) - TypeError: parent_agent unexpected (added to function signatures) - asyncio not defined (simplified to ThreadPoolExecutor) - Task IDs expiring (SQLite persistence) - Results returning None (fixed _sync_request + callback) - check_profile_task intermittent (dual lookup) - cancel_profile_task unknown (SQLite status update) Stress Test Results: - 72 consecutive calls, 100% success rate - 15 parallel async + 15 parallel sync + 15 rapid sequential - Edge cases: unicode, special chars, multiline, heavy computation Files changed: - NEW: tools/profile_orchestrator.py (~1000 lines) - NEW: hermes_cli/profiles.py (~45 lines) - MODIFIED: tools/delegate_tool.py (+400 lines, bug fixes) - MODIFIED: gateway/platforms/api_server.py (session creation) - MODIFIED: hermes_state.py (orchestration_tasks table) - MODIFIED: toolsets.py (delegation toolset extended) Requires PR NousResearch#3681 (profile infrastructure) 100% offline capable using local SQLite
jecruz
pushed a commit
to jecruz/hermes-agent
that referenced
this pull request
Mar 29, 2026
…arch#3681) Each profile is a fully independent HERMES_HOME with its own config, API keys, memory, sessions, skills, gateway, cron, and state.db. Core module: hermes_cli/profiles.py (~900 lines) - Profile CRUD: create, delete, list, show, rename - Three clone levels: blank, --clone (config), --clone-all (everything) - Export/import: tar.gz archive for backup and migration - Wrapper alias scripts (~/.local/bin/<name>) - Collision detection for alias names - Sticky default via ~/.hermes/active_profile - Skill seeding via subprocess (handles module-level caching) - Auto-stop gateway on delete with disable-before-stop for services - Tab completion generation for bash and zsh CLI integration (hermes_cli/main.py): - _apply_profile_override(): pre-import -p/--profile flag + sticky default - Full 'hermes profile' subcommand: list, use, create, delete, show, alias, rename, export, import - 'hermes completion bash/zsh' command - Multi-profile skill sync in hermes update Display (cli.py, banner.py, gateway/run.py): - CLI prompt: 'coder ❯' when using a non-default profile - Banner shows profile name - Gateway startup log includes profile name Gateway safety: - Token locks: Discord, Slack, WhatsApp, Signal (extends Telegram pattern) - Port conflict detection: API server, webhook adapter Diagnostics (hermes_cli/doctor.py): - Profile health section: lists profiles, checks config, .env, aliases - Orphan alias detection: warns when wrapper points to deleted profile Tests (tests/hermes_cli/test_profiles.py): - 71 automated tests covering: validation, CRUD, clone levels, rename, export/import, active profile, isolation, alias collision, completion - Full suite: 6760 passed, 0 new failures Documentation: - website/docs/user-guide/profiles.md: full user guide (12 sections) - website/docs/reference/profile-commands.md: command reference (12 commands) - website/docs/reference/faq.md: 6 profile FAQ entries - website/sidebars.ts: navigation updated
8 tasks
erosika
added a commit
to erosika/hermes-agent
that referenced
this pull request
Mar 30, 2026
Derives the Honcho host key from the active Hermes profile so that each profile gets its own Honcho host block, workspace, and AI peer identity. Profile "coder" resolves to host "hermes.coder", reads from hosts["hermes.coder"] in honcho.json, and defaults workspace + aiPeer to the derived host name. Resolution order: HERMES_HONCHO_HOST env var > active profile name > "hermes" (default). Complements NousResearch#3681 (profiles) with the Honcho identity layer that was part of NousResearch#2845 (named instances), adapted to the merged profiles system.
This was referenced Mar 30, 2026
erosika
added a commit
to erosika/hermes-agent
that referenced
this pull request
Mar 30, 2026
Derives the Honcho host key from the active Hermes profile so that each profile gets its own Honcho host block, workspace, and AI peer identity. Profile "coder" resolves to host "hermes.coder", reads from hosts["hermes.coder"] in honcho.json, and defaults workspace + aiPeer to the derived host name. Resolution order: HERMES_HONCHO_HOST env var > active profile name > "hermes" (default). Complements NousResearch#3681 (profiles) with the Honcho identity layer that was part of NousResearch#2845 (named instances), adapted to the merged profiles system.
erosika
added a commit
to erosika/hermes-agent
that referenced
this pull request
Mar 31, 2026
Derives the Honcho host key from the active Hermes profile so that each profile gets its own Honcho host block, workspace, and AI peer identity. Profile "coder" resolves to host "hermes.coder", reads from hosts["hermes.coder"] in honcho.json, and defaults workspace + aiPeer to the derived host name. Resolution order: HERMES_HONCHO_HOST env var > active profile name > "hermes" (default). Complements NousResearch#3681 (profiles) with the Honcho identity layer that was part of NousResearch#2845 (named instances), adapted to the merged profiles system.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Profiles let you run multiple fully independent Hermes agents from a single install. Each profile gets its own
HERMES_HOMEdirectory — separate config, API keys, memories, sessions, skills, gateway, cron, and state.db. One shared codebase, complete data isolation.Architecture
The core mechanism: 119+ files reference
get_hermes_home(). SettingHERMES_HOMEbefore import makes every command profile-scoped automatically — zero per-command changes needed.What's in this PR (19 files, +2788 lines)
New:
hermes_cli/profiles.py(~900 lines)--clone(config only),--clone-all(full duplicate including sessions, skills, memory, cron, plugins)hermes profile export coder→ tar.gz,hermes profile import archive.tar.gz~/.local/bin/<name>with collision detectionhermes profile use coder→~/.hermes/active_profilehermes completion bash/zshCLI:
hermes_cli/main.py_apply_profile_override(): Pre-import-p/--profilescanner + sticky default fallback. All exceptions caught — never prevents hermes from starting.cmd_profile(): 9 subcommands (status, list, use, create, delete, show, alias, rename, export, import)cmd_completion(): Shell completion outputcmd_update(): Syncs bundled skills to ALL profiles after git pullDisplay:
cli.py,banner.py,gateway/run.pycoder ❯— Banner:Profile: coder— Gateway log:Active profile: coderGateway safety (6 adapters)
Diagnostics:
hermes_cli/doctor.pyTests:
tests/hermes_cli/test_profiles.py(71 tests)Documentation
website/docs/user-guide/profiles.md: Full user guide — 12 sections with code exampleswebsite/docs/reference/profile-commands.md: Command reference — 12 commands with optionswebsite/docs/reference/faq.md: 6 profile FAQ entrieswebsite/sidebars.ts: Navigation updatedDeveloper guidance
AGENTS.md: New "Profiles: Multi-Instance Support" section with 6 rules for profile-safe code, test fixture patterns, and tool development guidanceAGENTS.md: New "DO NOT hardcode ~/.hermes paths" pitfall entrywebsite/docs/developer-guide/contributing.md: Profile-safe paths in Code Style sectionLive E2E test results
22 live tests passed during development:
-pflag in all formats (before/after subcommand,--profile=) ✓CI results
All 6 checks pass:
Backward compatibility
Zero impact for non-profile users.
_apply_profile_override()returns immediately when no-pflag and noactive_profilefile exist — zero imports, zero overhead, zero visual changes. No config migration needed. The feature is fully opt-in.Pre-work PRs (merged)
get_hermes_home(). Added_profile_suffix()for service names. Fixed macOS launchd HERMES_HOME.display_hermes_home(). Swept 30+ user-facing strings across 12 files.Command reference