Skip to content

Feature: Agent Mode System — Persona + Tool Scoping + Behavioral Constraints (inspired by Kilocode) #476

@teknium1

Description

@teknium1

Overview

Hermes Agent currently has two independent mechanisms for customizing agent behavior: /personality (which swaps system prompt text) and toolsets (which control which tools are available). These two systems are completely disconnected — changing personality doesn't change tool access, and changing toolsets doesn't change behavioral guidance. There is no concept of a "mode" that pairs a persona with specific tool permissions and behavioral rules.

Kilocode (the #1 agent on OpenRouter, 1.5M+ users, fork of OpenCode) implements a formal Mode System that is one of its most compelling features. Each mode is a named configuration combining: (1) a system prompt/persona, (2) a tool permission ruleset that allows/denies/asks per-tool, and (3) behavioral constraints. Users can switch modes mid-session and create custom modes.

This would be the single highest-value architectural pattern to adopt from Kilocode. It applies to single-agent usage (not just multi-agent), improves safety, and creates natural guardrails for different development phases.


Research Findings

How Kilocode's Mode System Works

Modes are defined as Agent.Info objects with these key fields:

{
  name: string,           // "code", "plan", "debug", "ask", "orchestrator"
  description: string,    // Human-readable description
  prompt?: string,        // Optional system prompt override
  mode: "primary" | "subagent" | "all",  // Visibility
  permission: Ruleset     // Tool permission rules
}

The Ruleset is the core mechanism — an ordered array of { permission, pattern, action } rules where action is "allow", "deny", or "ask" (requires user confirmation). Rules use glob matching and the LAST matching rule wins.

Built-in Modes:

Mode Persona Tool Access Use Case
Code Skilled engineer Full access (read, edit, terminal, browser, MCP) Writing/implementing code
Ask Technical assistant Read-only (read, grep, glob, web) — NO edit, NO terminal Learning, exploring without risk
Architect System designer Read + Markdown-only edit — NO code edit, NO terminal Planning and system design
Debug Diagnostic expert Full access + debug-oriented prompt Systematic troubleshooting
Orchestrator Workflow coordinator Read + bash + task delegation — NO direct edit Breaking down large projects
Review Code reviewer Read + conditional edit Pre-commit code review

Tool filtering happens at two levels:

  1. Pre-LLM: Before sending tools to the model, PermissionNext.disabled() removes denied tools from the schema entirely — the model doesn't even see them
  2. At execution: Each tool call goes through PermissionNext.ask() which evaluates the merged ruleset. Denied tools throw DeniedError, "ask" tools pause for user confirmation

Custom modes: Users can define custom modes in config with arbitrary persona text + permission rulesets. Custom modes get mode: "all" by default (usable as both primary and subagent).

Key Design Decisions

  1. Last-match-wins rule evaluation — Rules are evaluated by findLast(), making rule composition intuitive (later rules override earlier ones)
  2. Three-action permissionsallow/deny/ask provides a middle ground where risky-but-useful tools can require confirmation rather than being fully blocked
  3. Mode visibilityprimary modes are user-selectable, subagent modes are only available for delegation (e.g., "explore" and "general" subagent modes), all works in both contexts
  4. Mode-coupled delegation — The Orchestrator's task tool spawns subtasks in specific modes, inheriting that mode's tool restrictions

Current State in Hermes Agent

What we have:

  • /personality command (cli.py:1545) — swaps system prompt personality text. Purely cosmetic; does NOT restrict tools or change behavioral rules
  • /prompt command (cli.py:1491) — sets arbitrary system prompts
  • SOUL.md support (prompt_builder.py:309-333) — loads persona/tone from project-level file
  • ephemeral_system_prompt on AIAgent — injected at runtime for gateway/delegate contexts
  • Toolsets system (toolsets.py) — pre-defined tool groupings per platform (hermes-cli, hermes-telegram, etc.). This already supports tool filtering but is tied to platform, not user-selected modes
  • --tools CLI flag — allows specifying toolsets at launch

The gap: We have the ingredients for a mode system (persona text via /personality, tool filtering via toolsets) but they are not linked. There is no concept of "switch to Architect mode" which simultaneously changes the persona, restricts tools, and modifies behavioral guidance. The toolsets system is platform-bound, not user-mode-bound.


Implementation Plan

Skill vs. Tool Classification

This is a core codebase change — it touches run_agent.py (tool dispatch), toolsets.py (tool filtering), prompt_builder.py (system prompt assembly), and cli.py (mode switching commands). Not a skill or tool.

What We'd Need

  1. A Mode data structure pairing persona + tool permissions
  2. Built-in mode definitions (Code, Plan, Ask, Debug, Review)
  3. Mode switching mechanism (slash command, programmatic)
  4. Tool filtering integration with the existing toolsets system
  5. Config support for custom user-defined modes
  6. Integration with delegate_task for mode-coupled delegation

Phased Rollout

Phase 1: Mode definitions + switching (foundation)

Define modes as dataclasses combining persona text + tool whitelist/blacklist:

@dataclass
class AgentMode:
    name: str
    description: str
    persona: str                    # System prompt addition
    allowed_tools: set[str] | None  # None = all tools allowed
    denied_tools: set[str] | None   # None = no tools denied
    ask_tools: set[str] | None      # Requires user confirmation
    visibility: str = "all"         # "primary" | "subagent" | "all"

BUILT_IN_MODES = {
    "code": AgentMode(
        name="code",
        description="Full-access coding mode",
        persona="You are a skilled software engineer...",
        allowed_tools=None,  # all
        denied_tools=None,
        ask_tools=None,
    ),
    "ask": AgentMode(
        name="ask",
        description="Read-only exploration mode — cannot modify files or run commands",
        persona="You are a knowledgeable technical assistant...",
        allowed_tools={"read_file", "search_files", "web_search", "web_extract",
                       "vision_analyze", "session_search", "skills_list", "skill_view"},
        denied_tools=None,
        ask_tools=None,
    ),
    "architect": AgentMode(
        name="architect",
        description="Planning mode — can read everything, edit only markdown/docs",
        persona="You are a technical leader and system architect...",
        allowed_tools=None,  # all read tools
        denied_tools={"terminal", "execute_code"},
        ask_tools={"write_file", "patch"},  # ask before writing
    ),
    "debug": AgentMode(
        name="debug",
        description="Diagnostic mode with systematic troubleshooting focus",
        persona="You are an expert debugger and diagnostic specialist...",
        allowed_tools=None,
        denied_tools=None,
        ask_tools=None,
    ),
}
  • /mode <name> slash command to switch modes mid-session
  • Mode name shown in prompt/banner
  • Tool filtering applied in _execute_tool_calls() before dispatch

Phase 2: Custom modes + config

  • Allow custom mode definitions in ~/.hermes/config.yaml:
modes:
  security-reviewer:
    description: "Security-focused code review"
    persona: "You are a security engineer. Focus on vulnerabilities..."
    allowed_tools: [read_file, search_files, web_search, terminal]
    denied_tools: [write_file, patch, execute_code]
  • /mode list to show available modes
  • Mode persistence across sessions (remember last mode per project)

Phase 3: Mode-coupled delegation + subagent modes

  • Add mode parameter to delegate_task:
delegate_task(
    goal="Review this PR for security issues",
    mode="security-reviewer"
)

Pros & Cons

Pros

  • Safety — "Ask" mode prevents accidental file modifications during exploration. "Architect" mode prevents premature implementation during planning. Tool restrictions are structural, not just "please don't"
  • Workflow optimization — Different phases of work (plan → implement → debug → review) get tailored tool access and behavioral guidance
  • Builds on existing infrastructure — We already have toolsets for tool grouping and /personality for persona text; modes link them together
  • Custom modes are a power feature — Users can create domain-specific modes (e.g., "database-admin" with only SQL-related tools, "documentation-writer" with only file and web tools)
  • Prerequisite for better multi-agent — Mode-coupled delegation (Feature: Multi-Agent Architecture — Orchestration, Cooperation, Specialized Roles & Resilient Workflows #344) becomes possible, enabling specialized sub-agents
  • Low risk — Default "code" mode = current behavior. Modes are opt-in. No breaking changes.

Cons / Risks

  • Complexity — Adds another dimension to the already-complex tool dispatch pipeline
  • Mode confusion — Users might forget what mode they're in and be confused when tools are blocked (mitigation: clear mode indicator in prompt, helpful error messages)
  • Maintenance burden — Built-in modes need to be updated when new tools are added
  • CLI vs. Gateway tension — Mode switching via slash commands works in CLI, but gateway platforms need a different UX (buttons? reactions? inline commands?)
  • Interaction with existing toolsets — Need clear semantics for how mode tool restrictions interact with platform toolsets (intersection? override?)

Open Questions

  1. Mode × Toolset interaction — If the platform toolset already restricts tools, and the mode further restricts, should they intersect (most restrictive wins) or should mode override platform? Recommend: intersection.
  2. Mode switching restrictions — Should certain modes prevent switching to others? (e.g., during an active terminal command) Or is switching always allowed?
  3. Per-project mode defaults — Should projects be able to set a default mode? (e.g., SOUL.md could specify mode: architect for planning repos)
  4. Gateway platform UX — How do Telegram/Discord users switch modes? Inline /mode command? Bot buttons?
  5. Skill-defined modes — Should skills be able to define modes? (e.g., a "security-audit" skill that includes a "security" mode with specific tool restrictions)
  6. Tool "ask" action UX — Kilocode uses an "ask" permission that pauses for user confirmation. We have approval.py for dangerous commands — should mode-level "ask" reuse that system?

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions