mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 01:21:43 +00:00
feat: multi-agent architecture — named agents with routing, tool policies, and isolated workspaces
Implements the full multi-agent system for Hermes Agent, allowing a single
installation to host multiple named agents, each with its own model,
personality, toolset, workspace, and session history.
## New Files
- gateway/agent_registry.py: AgentConfig, ToolPolicy, SubagentPolicy,
AgentRegistry, TOOL_PROFILES (minimal/coding/messaging/full), and
normalize_tool_config() for shorthand YAML parsing
- gateway/router.py: BindingRouter with 7-tier deterministic routing
(chat_id > peer > guild+type > guild > platform+type > platform > default)
## Core Changes
- model_tools.py: get_tool_definitions() accepts agent_tool_policy for
per-agent tool filtering; handle_function_call() extended enabled_tools
check to gate ALL tool calls (defense-in-depth)
- gateway/session.py: build_session_key() now accepts agent_id and dm_scope
parameters, replacing hardcoded 'agent:main' with 'agent:{agent_id}'
- tools/memory_tool.py: MemoryStore accepts memory_dir parameter for
per-agent memory isolation
- agent/prompt_builder.py: build_context_files_prompt() accepts
agent_workspace for SOUL.md lookup; build_skills_system_prompt()
accepts agent_skills_dir for per-agent skill overlay
- run_agent.py: AIAgent accepts agent_tool_policy and agent_workspace,
passes policy through to get_tool_definitions()
- gateway/run.py: Initializes AgentRegistry + BindingRouter, resolves
agent per-message in _handle_message(), passes config to _run_agent(),
adds /agents command
- cli.py: --agent flag for selecting named agent profiles, /agents
slash command, agent config override for model/personality/tools
- hermes_cli/config.py: agents/bindings in DEFAULT_CONFIG, version 7
- tools/delegate_tool.py: Configurable max_depth per-agent, tool policy
inheritance from parent to child
## Config Format
agents:
main:
default: true
coder:
model: anthropic/claude-sonnet-4
personality: 'You are a coding assistant.'
tools: coding # or [tool1, tool2] or {profile: x, deny: [...]}
bindings:
- agent: coder
telegram: '-100123456'
## Tests
168 new tests across 3 test files (agent_registry, router, integration).
All 3106 tests pass.
This commit is contained in:
parent
1115e35aae
commit
b159002078
17 changed files with 2489 additions and 53 deletions
|
|
@ -126,6 +126,14 @@ DEFAULT_CONFIG = {
|
|||
# "model": "google/gemini-3-flash-preview",
|
||||
},
|
||||
|
||||
# Named agent profiles — reusable bundles of model + toolsets + prompt.
|
||||
# Define profiles here and activate them with `hermes chat --agent <name>`.
|
||||
"agents": {},
|
||||
|
||||
# Bindings — map trigger patterns or platforms to named agent profiles.
|
||||
# Example: [{"pattern": "review *", "agent": "code-reviewer"}]
|
||||
"bindings": [],
|
||||
|
||||
"display": {
|
||||
"compact": False,
|
||||
"personality": "kawaii",
|
||||
|
|
@ -189,7 +197,7 @@ DEFAULT_CONFIG = {
|
|||
"command_allowlist": [],
|
||||
|
||||
# Config schema version - bump this when adding new required fields
|
||||
"_config_version": 6,
|
||||
"_config_version": 7,
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
|
|
@ -654,6 +662,23 @@ def migrate_config(interactive: bool = True, quiet: bool = False) -> Dict[str, A
|
|||
tz_display = config["timezone"] or "(server-local)"
|
||||
print(f" ✓ Added timezone to config.yaml: {tz_display}")
|
||||
|
||||
# ── Version 6 → 7: add agents and bindings keys ──
|
||||
if current_ver < 7:
|
||||
config = load_config()
|
||||
changed = False
|
||||
if "agents" not in config:
|
||||
config["agents"] = {}
|
||||
results["config_added"].append("agents={}")
|
||||
changed = True
|
||||
if "bindings" not in config:
|
||||
config["bindings"] = []
|
||||
results["config_added"].append("bindings=[]")
|
||||
changed = True
|
||||
if changed:
|
||||
save_config(config)
|
||||
if not quiet:
|
||||
print(" ✓ Added agents and bindings to config.yaml")
|
||||
|
||||
if current_ver < latest_ver and not quiet:
|
||||
print(f"Config version: {current_ver} → {latest_ver}")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue