Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Core AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Loop
Overview
The AIAgent class (run_agent.py) is the narrow waist of the entire system: a synchronous conversation loop that sends messages with tool schemas to an OpenAI-compatible API, processes tool calls, manages budgets and iterations, and returns final responses. All surfaces (CLICommand-Line Interface, gateway, TUITerminal User Interface, desktop) funnel through it.
Stakeholders
| Stakeholder | Interest |
|---|---|
| All users | The agent must respond correctly, handle multi-turn tool use, respect iteration budgets, and recover from API errors |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles/skill developers | The loop must correctly inject tool schemas from enabled toolsets and plugins |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe agent shall accept a user message and return a response after zero or more tool-calling iterations | Must | The agent shall accept a user message and return a response after zero or more tool-calling iterations |
| FR-2MustThe agent shall support a configurable max_iterations limit and stop gracefully when exceeded | Must | The agent shall support a configurable max_iterations limit and stop gracefully when exceeded |
| FR-3MustThe agent shall maintain an iteration budget that is shared with subagents and decr across turns | Must | The agent shall maintain an iteration budget that is shared with subagents and decr across turns |
| FR-4MustThe agent shall support interrupt requests that stop the loop at the next safe point | Must | The agent shall support interrupt requests that stop the loop at the next safe point |
| FR-5MustThe agent shall preserve strict message role alternation (never two same-role messages in a row) | Must | The agent shall preserve strict message role alternation (never two same-role messages in a row) |
| FR-6MustThe agent shall maintain a byte-stable system prompt across turns for prompt caching | Must | The agent shall maintain a byte-stable system prompt across turns for prompt caching |
| FR-7MustThe agent shall dispatch tool calls to registered handlers and append results as tool-role messages | Must | The agent shall dispatch tool calls to registered handlers and append results as tool-role messages |
| FR-8ShouldThe agent shall support a predictive usage mode that estimates tokens before the API call | Should | The agent shall support a predictive usage mode that estimates tokens before the API call |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustThe loop shall not add more than 50ms overhead per turn beyond the LLM API call time | Must | Performance | The loop shall not add more than 50ms overhead per turn beyond the LLM API call time |
| NFR-2MustAgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory shall recover gracefully from transient API errors with configurable retry logic | Must | Reliability | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory shall recover gracefully from transient API errors with configurable retry logic |
| NFR-3MustThe agent shall work with any OpenAI-compatible chat completions endpoint | Must | Compatibility | The agent shall work with any OpenAI-compatible chat completions endpoint |
Constraints
- Tool handlers must return JSON strings
- Message format must follow OpenAI chat completions schema
- Budget tracking must be consistent across parent and child (subagent) sessions
Acceptance Criteria
- FR-1MustThe agent shall accept a user message and return a response after zero or more tool-calling iterations
- Given a running agent
- When a user sends a message that requires no tool calls
- Then the agent returns the final response directly
- FR-2MustThe agent shall support a configurable max_iterations limit and stop gracefully when exceeded
- Given an agent configured with max_iterations=3
- When the LLM issues tool calls on every turn
- Then the loop stops after 3 iterations and returns the last assistant response
- FR-5MustThe agent shall preserve strict message role alternation (never two same-role messages in a row)
- Given a conversation with history
- When the agent processes a tool call result and an assistant response
- Then no two consecutive messages have the same role
- NFR-1MustThe loop shall not add more than 50ms overhead per turn beyond the LLM API call time
- Given a call to run_conversation()
- When the LLM returns immediately
- Then the overhead between receiving the LLM response and appending the tool result is under 50ms
Conflicts
None identified yet.
Open Questions
- Should the budget be configurable per-turn or only per-session?
Specification: Core AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Loop
Overview
The core agent loop is a synchronous cycle inside AIAgent.run_conversation() that sends the message history plus tool schemas to the LLM, processes tool calls or text responses, and repeats until a terminal condition is met.
Architecture
User Message
│
v
┌──────────────────────────────────────────┐
│ AIAgent.run_conversation() │
│ │
│ while (budget.remaining > 0 and │
│ api_call_count < max_iterations): │
│ response = client.create( │
│ messages=messages, │
│ tools=get_tool_definitions()) │
│ │
│ if response.tool_calls: │
│ for call in response.tool_calls: │
│ result = handle_function_call( │
│ call.name, call.args, task_id) │
│ messages.append(tool_result) │
│ api_call_count++ │
│ else: │
│ return response.content │
│ │
│ return fallback response │
└──────────────────────────────────────────┘
Data Models
Conversation Message
| Field | Type | Constraints | Description |
|---|---|---|---|
| role | string | one of system/user/assistant/tool | Message role |
| content | string | nullable | Message text content |
| tool_calls | array | nullable | List of tool call objects from the LLM |
| tool_call_id | string | present on tool responses | Correlation ID for the tool call being responded to |
| name | string | present on tool responses | Name of the tool that was called |
API Contracts
The agent communicates with LLM providers via the OpenAI chat completions format. No internal API contracts exist beyond the function call dispatch mechanism.
handle_function_call(name, args)
Input: tool name + JSON arguments dict + optional task_id Output: JSON string result
| Field | Type | Description |
|---|---|---|
| name | string | Tool name matching a registered schema |
| args | dict | JSON-serializable params matching the schema's parameters |
| task_id | string | Optional subagent task ID for delegation |
Sequences
Basic turn (no tool calls)
User → AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory → LLM → text response → User
Tool-calling turn
User → AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory → LLM → tool_call(name, args)
AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory → registry.dispatch(name, args) → handler → JSON result
AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory → messages.append(tool role)
AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory → LLM (next turn) → text response → User
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Synchronous loop | Single-threaded blocking loop | Simpler state management, no race conditions on message history, easy interrupt handling |
| OpenAI format | OpenAI chat completions schema | Universal compatibility — most providers support it natively |
| Tool results as messages | Append tool-role messages to history | Standard OpenAI pattern; preserves full context for next LLM call |
| Budget grace call | One extra turn after budget exhaustion | Ensures the agent can summarize/clean up instead of being cut off mid-response |
| Interrupt check | Injected check at top of each iteration | No need for threading or signals; the check is just a boolean flag read |
Risks and Unknowns
- Large tool call loops can exhaust the iteration budget before producing a final response — the budget grace call mitigates this
- Synchronous loop blocks the calling thread; the gateway uses asyncio to wrap the call, but long tool operations (browser, terminal) still block the agent
Out of Scope
- Streaming response delivery (handled by surfaces, not by AIAgent)
- Async agent loop (future consideration)
Test Plan: Core AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Loop
Scope
Tests covering the AIAgent class, conversation loop, tool calling, budget tracking, interrupt handling, message role alternation, provider adapters, and error recovery.
Test Files
- tests/run_agent/ — 115+ test files covering run_agent.py core loop behavior
- tests/agent/ — 226 test files covering provider adapters, memory, compression, tool calling, streaming, error recovery
- tests/run_agent/test_run_agent.py — Main test suite for conversation loop
- tests/run_agent/test_streaming.py — Streaming response tests
- tests/run_agent/test_tool_call_guardrail_runtime.py — Tool call guardrail tests
- tests/run_agent/test_iteration_budget_race.py — Budget tracking tests
- tests/run_agent/test_interactive_interrupt.py — Interrupt handling
- tests/run_agent/test_provider_fallback.py — Provider fallback and error recovery
Unit Tests
Key unit test coverage areas: - Tool call dispatch and argument coercion - Message role alternation enforcement - Iteration budget tracking and grace call - System prompt byte-stability - API error recovery and retry logic - Stream interruption and circuit breaker
Integration Tests
- AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory loop with real/fake LLM providers
- Tool result persistence in message history
- Multi-turn conversation flows
- Budget sharing with subagents
- Concurrent interrupt handling
End-to-End Tests
- tests/run_agent/test_run_agent.py — Full conversation loop with tool calling
- tests/run_agent/test_codex_app_server_integration.py — Codex provider integration
Edge Cases and Failure Scenarios
| Scenario | Expected Behavior |
|---|---|
| LLM returns empty response | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory retries or returns graceful error |
| Tool call with malformed JSON | JSON decode error recovery |
| Budget exhausted mid-tool-loop | Grace call allows one final turn |
| Interrupt during tool execution | Loop breaks at next safe point |
| Provider returns 429 rate limit | Retry with backoff |
| Message sequence gets two same-role messages | Sequence repair normalizes |
Test Infrastructure
- pytest with hermetic runner (scripts/run_tests.sh)
- Mock providers for deterministic testing
- Temp HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) isolation per test
- Subprocess-per-test-file isolation
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe agent shall accept a user message and return a response after zero or more tool-calling iterations (accept message, return response) | test_run_agent.py basic flow tests |
| FR-2MustThe agent shall support a configurable max_iterations limit and stop gracefully when exceeded (max_iterations limit) | test_iteration_budget_race.py |
| FR-3MustThe agent shall maintain an iteration budget that is shared with subagents and decr across turns (iteration budget) | test_iteration_budget_race.py |
| FR-4MustThe agent shall support interrupt requests that stop the loop at the next safe point (interrupt requests) | test_interactive_interrupt.py, test_exit_cleanup_interrupt.py |
| FR-5MustThe agent shall preserve strict message role alternation (never two same-role messages in a row) (message role alternation) | test_message_sequence_repair.py |
| FR-6MustThe agent shall maintain a byte-stable system prompt across turns for prompt caching (byte-stable system prompt) | Implicit in caching tests |
| FR-7MustThe agent shall dispatch tool calls to registered handlers and append results as tool-role messages (tool call dispatch) | test_tool_call_guardrail_runtime.py, test_tool_arg_coercion.py |
| NFR-1MustThe loop shall not add more than 50ms overhead per turn beyond the LLM API call time (50ms overhead) | Performance benchmark tests |
| NFR-2MustAgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory shall recover gracefully from transient API errors with configurable retry logic (transient error recovery) | test_jsondecodeerror_retryable.py, test_nonretryable_error_html_summary.py |
| NFR-3MustThe agent shall work with any OpenAI-compatible chat completions endpoint (OpenAI-compatible) | test_create_openai_client_*.py |
requirements
- Should the budget be configurable per-turn or only per-session?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Configuration and Multi-ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ System
Overview
Hermes uses a layered configuration system: config.yaml for behavioral settings (deep-merged from DEFAULT_CONFIG), .env for secrets only, and profile support for fully isolated agent instances. Each profile has its own HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) directory (config, credentials, skills, sessions, logs). The model catalog, provider registry, and toolset configuration complete the setup story.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Power users | Want to customize agent behavior through config.yaml without editing source files |
| Multi-identity users | Want separate profiles for work vs. personal use with different models, credentials, and skills |
| Self-hosters | Want to configure terminal backends, memory providers, and gateway platforms |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustAll behavioral settings shall be configurable via config.yaml | Must | All behavioral settings shall be configurable via config.yaml |
| FR-2MustSecrets (API keys, tokens, passwords) shall be stored in .env only | Must | Secrets (API keys, tokens, passwords) shall be stored in .env only |
| FR-3MustConfiguration shall use a deep-merge from DEFAULT_CONFIG to user config.yaml | Must | Configuration shall use a deep-merge from DEFAULT_CONFIG to user config.yaml |
| FR-4MustThe system shall support multiple fully isolated profiles | Must | The system shall support multiple fully isolated profiles |
| FR-5MustEach profile shall have its own HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) directory | Must | Each profile shall have its own HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) directory |
| FR-6MustProfiles shall support the --clone option to copy an existing profile's config | Must | Profiles shall support the --clone option to copy an existing profile's config |
| FR-7MustThe system shall support a model catalog with provider-specific model lists | Must | The system shall support a model catalog with provider-specific model lists |
| FR-8MustThe system shall support toolset enable/disable per platform | Must | The system shall support toolset enable/disable per platform |
| FR-9ShouldConfig version bumps shall support migrating/transforming existing user config | Should | Config version bumps shall support migrating/transforming existing user config |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1Mustconfig.yaml changes should be backward compatible (new keys merged automatically) | Must | Compatibility | config.yaml changes should be backward compatible (new keys merged automatically) |
| NFR-2Must.env must never be committed or logged | Must | Security | .env must never be committed or logged |
| NFR-3ShouldConfig loading should complete in under 500ms | Should | Performance | Config loading should complete in under 500ms |
Constraints
- No new HERMES_* env vars for non-secret config (behavioral settings go in config.yaml)
- _config_version is bumped ONLY when migration/transformation is needed, not for new keys
- Profiles are fully independent — no live config inheritance between profiles
Acceptance Criteria
- FR-1MustAll behavioral settings shall be configurable via config.yaml
- Given a user sets display.skin: ares in config.yaml
- When the CLICommand-Line Interface starts
- Then the ares skin is applied
- FR-4MustThe system shall support multiple fully isolated profiles
- Given two profiles created with hermes -p personal and hermes -p work
- When the user runs hermes -p personal
- Then the personal profile's config, sessions, and skills are used
- FR-6MustProfiles shall support the --clone option to copy an existing profile's config
- Given the user runs hermes profile clone --from personal --name personal2
- Then a new profile with the same config as personal is created
Conflicts
None identified yet.
Open Questions
- Should profile configs support a !include directive for shared sections?
Specification: Configuration and Multi-ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ System
Overview
Config loading follows a three-path system: load_cli_config() for CLICommand-Line Interface mode (includes CLICommand-Line Interface-specific defaults), load_config() for tools/setup (merges DEFAULT_CONFIG + user YAML), and direct YAML load for the gateway. All three use deep-merge to combine defaults with user overrides without requiring users to include the entire config.
Architecture
ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/-aware path resolution:
get_hermes_home() → ~/.hermes (default) or ~/.hermes/profiles/<name> (profile)
↑
_apply_profile_override() sets HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) before any module imports
Config loaders:
├── load_cli_config() — CLICommand-Line Interface mode (cli.py)
│ └── merges CLICommand-Line Interface-specific defaults + user config.yaml
├── load_config() — tools/setup (hermes_cli/config.py)
│ └── merges DEFAULT_CONFIG + user config.yaml
└── Direct YAML — gateway runtime (gateway/run.py)
└── reads config.yaml raw
Config sections (non-exhaustive):
model, agent, terminal, compression, display, stt, tts,
memory, security, delegation, smart_model_routing, checkpoints,
auxiliary, curator, skills, gateway, logging, cron, profiles,
plugins, honcho
Data Models
Config structure (config.yaml)
No fixed schema — sections are added to DEFAULT_CONFIG as dictionaries. New keys are auto-merged without version bumps. A _config_version field tracks schema migration needs.
ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ structure (filesystem)
~/.hermes/
├── config.yaml # Default profile
├── .env # Secrets (default profile)
├── sessions.db # SessionA single conversation history stored in SQLite with FTS5 search store
├── logs/
├── skills/
├── plugins/
├── skins/
└── profiles/
├── personal/
│ ├── config.yaml
│ ├── .env
│ ├── sessions.db
│ └── ...
└── work/
└── ...
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ isolation | Independent directories | No coupling between profiles; clean separation of state |
| Config merge | Deep-merge from defaults | Users only specify overrides, not the entire config |
| Version bumps | Only for migrations | Adding a key is backward compatible without a version bump |
| Secrets location | .env only (never config.yaml) | Keeps secrets out of version control and prevents accidental exposure |
| .env vars | Secrets only | Behavioral settings go in config.yaml — env vars are reserved for API keys and tokens |
Risks and Unknowns
- Three config loaders can drift — a key may work in CLICommand-Line Interface but not in gateway or vice versa
- GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core reads raw YAML without DEFAULT_CONFIG merge — new keys added to DEFAULT_CONFIG may not appear in gateway without explicit work
- Deep-merge may produce unexpected results for nested structures (lists are replaced, not merged)
Out of Scope
- Cloud-synced profiles
- GUI config editor
Test Plan: Configuration and Multi-ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ System
Scope
Tests covering config.yaml loading and deep-merge, .env secrets loading, profile creation/clone/list/use, config version migration, toolset configuration, and model catalog.
Test Files
- tests/hermes_cli/test_config.py — Config loading and merge
- tests/hermes_cli/test_config_drift.py — Config drift detection
- tests/hermes_cli/test_config_validation.py — Config validation
- tests/hermes_cli/test_config_env_expansion.py — Env var expansion in config
- tests/hermes_cli/test_config_env_refs.py — Config references to env vars
- tests/hermes_cli/test_profiles.py — ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ operations
- tests/hermes_cli/test_profile_distribution.py — ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ distribution
- tests/hermes_cli/test_profile_describer.py — ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ description
- tests/hermes_cli/test_profile_export_credentials.py — Credential export
- tests/hermes_cli/test_apply_profile_override.py — ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ override
- tests/hermes_cli/test_model_catalog.py — Model catalog tests
- tests/hermes_cli/test_tools_config.py — ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) configuration
- tests/hermes_cli/test_toolset_validation.py — ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) validation
- tests/hermes_cli/test_models.py — Model list and filtering
- tests/hermes_cli/test_env_loader*.py — .env loading (5+ test files)
Unit Tests
- DEFAULT_CONFIG deep-merge with user config
- Config version migration
- ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ directory creation and isolation
- .env parsing and variable expansion
- Model catalog loading from provider registry
Integration Tests
- Full config loading through all three loaders (CLICommand-Line Interface, tools, gateway)
- ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/-aware HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) resolution
- ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ clone creates independent copy
- ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) enable/disable per platform
- Config drift detection and repair
Edge Cases and Failure Scenarios
| Scenario | Expected Behavior |
|---|---|
| Config yaml parse error | Graceful fallback with error message |
| Missing .env file | Continue with empty env (warn on first run) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ directory already exists | Error with existing profile message |
| Config version mismatch | Automatic migration applied |
| Unknown config key in user yaml | Ignored with warning (forward compatibility) |
Test Infrastructure
- Temp HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) and profile directories
- Controlled config yaml content per test
- Monkeypatched env for .env tests
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustAll behavioral settings shall be configurable via config.yaml (config.yaml settings) | test_config.py |
| FR-2MustSecrets (API keys, tokens, passwords) shall be stored in .env only (.env for secrets) | test_env_loader*.py |
| FR-3MustConfiguration shall use a deep-merge from DEFAULT_CONFIG to user config.yaml (deep-merge) | test_config.py |
| FR-4MustThe system shall support multiple fully isolated profiles (multi-profile) | test_profiles.py |
| FR-5MustEach profile shall have its own HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) directory (profile HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware)) | test_apply_profile_override.py |
| FR-6MustProfiles shall support the --clone option to copy an existing profile's config (profile clone) | test_profiles.py |
| FR-7MustThe system shall support a model catalog with provider-specific model lists (model catalog) | test_model_catalog.py |
| FR-8MustThe system shall support toolset enable/disable per platform (toolset per platform) | test_tools_config.py, test_toolset_validation.py |
requirements
- Should profile configs support a !include directive for shared sections?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: MCPModel Context Protocol Server Integration
Overview
Hermes implements the Model Context Protocol (MCPModel Context Protocol) as a first-class integration pattern for connecting with external tool servers. MCPModel Context Protocol servers can be configured in config.yaml, auto-discovered, and their tools are surfaced alongside built-in tools through the MCPModel Context Protocol client. The system includes an mcp_serve.py entry point for serving MCPModel Context Protocol tools and optional MCPModel Context Protocol servers (linear, n8n, unreal-engine) shipped in optional-mcps/.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Users | Connect their agent to external tools and data sources via MCPModel Context Protocol without modifying core Hermes code |
| MCPModel Context Protocol server developers | Write standard MCPModel Context Protocol servers that any MCPModel Context Protocol host can consume |
| Hermes developers | The MCPModel Context Protocol client is the canonical path for adding structured tool integrations without growing the core toolset |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe system shall connect to configured MCPModel Context Protocol servers and discover their tools | Must | The system shall connect to configured MCPModel Context Protocol servers and discover their tools |
| FR-2MustMCPModel Context Protocol tools shall be surfaced alongside built-in tools in the agent's tool schemas | Must | MCPModel Context Protocol tools shall be surfaced alongside built-in tools in the agent's tool schemas |
| FR-3MustThe system shall support both stdio and SSE transport for MCPModel Context Protocol connections | Must | The system shall support both stdio and SSE transport for MCPModel Context Protocol connections |
| FR-4MustThe system shall support OAuth authentication for MCPModel Context Protocol servers | Must | The system shall support OAuth authentication for MCPModel Context Protocol servers |
| FR-5MustThe system shall support dynamic discovery of MCPModel Context Protocol tools at runtime | Must | The system shall support dynamic discovery of MCPModel Context Protocol tools at runtime |
| FR-6MustThe system shall support mcp_serve.py for serving Hermes tools as MCPModel Context Protocol | Must | The system shall support mcp_serve.py for serving Hermes tools as MCPModel Context Protocol |
| FR-7ShouldThe system shall support circuit breaker patterns for unreliable MCPModel Context Protocol servers | Should | The system shall support circuit breaker patterns for unreliable MCPModel Context Protocol servers |
| FR-8ShouldOptional MCPModel Context Protocol servers (linear, n8n, unreal-engine) shall be available for installation | Should | Optional MCPModel Context Protocol servers (linear, n8n, unreal-engine) shall be available for installation |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustAn unresponsive MCPModel Context Protocol server must not block the agent (timeout + circuit breaker) | Must | Reliability | An unresponsive MCPModel Context Protocol server must not block the agent (timeout + circuit breaker) |
| NFR-2MustMCPModel Context Protocol server URLs and authentication must be user-configurable in config.yaml | Must | Security | MCPModel Context Protocol server URLs and authentication must be user-configurable in config.yaml |
| NFR-3ShouldMCPModel Context Protocol tool discovery should complete in under 2 seconds | Should | Performance | MCPModel Context Protocol tool discovery should complete in under 2 seconds |
Constraints
- MCPModel Context Protocol servers are configured in config.yaml under a dedicated section
- MCPModel Context Protocol tools use the same tool schema format as built-in tools
- OAuth tokens for MCPModel Context Protocol servers are stored in the credential pool
Acceptance Criteria
- FR-1MustThe system shall connect to configured MCPModel Context Protocol servers and discover their tools
- Given an MCPModel Context Protocol server is configured in config.yaml
- When the agent starts
- Then the MCPModel Context Protocol server is connected and its tools are discovered
- FR-2MustMCPModel Context Protocol tools shall be surfaced alongside built-in tools in the agent's tool schemas
- Given the agent has discovered MCPModel Context Protocol tools
- When tool schemas are collected for the LLM
- Then MCPModel Context Protocol tool schemas appear alongside built-in tool schemas
- FR-6MustThe system shall support mcp_serve.py for serving Hermes tools as MCPModel Context Protocol
- Given mcp_serve.py is running
- When an external MCPModel Context Protocol client connects
- Then it can discover and call Hermes tools via MCPModel Context Protocol
- NFR-1MustAn unresponsive MCPModel Context Protocol server must not block the agent (timeout + circuit breaker)
- Given an MCPModel Context Protocol server is unresponsive
- When the agent tries to call the MCPModel Context Protocol tool
- Then the circuit breaker opens and the agent continues without blocking
Conflicts
None identified yet.
Open Questions
- Should MCPModel Context Protocol servers be configurable per-profile?
Specification: MCPModel Context Protocol Server Integration
Architecture
MCPModel Context Protocol Tools (tools/mcp_tool.py, tools/mcp_serve.py)
│
├── MCPModel Context Protocol Client (tools/mcp_client/ or tools/*mcp*.py)
│ ├── stdio transport
│ ├── SSE transport
│ ├── OAuth authentication
│ └── Circuit breaker
│
├── MCPModel Context Protocol Server (mcp_serve.py)
│ └── Serves Hermes tools as MCPModel Context Protocol tools
│
├── Optional MCPModel Context Protocol Servers (optional-mcps/)
│ ├── linear/ — Linear issue tracking
│ ├── n8n/ — n8n workflow automation
│ └── unreal-engine/ — Unreal Engine integration
│
└── MCPModel Context Protocol Config (config.yaml → tools/mcp_config/hermes_cli)
└── Server definitions with URL, auth, transport type
Data Models
MCPModel Context Protocol Server Configuration
| Field | Type | Description |
|---|---|---|
| name | string | Server identifier |
| transport | string | stdio or SSE |
| url | string | Server URL (for SSE) |
| command | string | Shell command (for stdio) |
| auth.type | string | OAuth or none |
| timeout | int | Connection timeout |
| circuit_breaker.threshold | int | Failure count before opening |
API Contracts
MCPModel Context Protocol follows the Model Context Protocol specification. Tools are defined using JSON Schema and called via JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend messages over the configured transport.
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Transport | stdio + SSE | Covers local servers and remote servers equally |
| Auth | OAuth via credential pool | Reuses existing credential management infrastructure |
| Discovery | Connect at startup + dynamic refresh | Tools available from session start; dynamic refresh handles late-joining servers |
| Circuit breaker | Configurable threshold per server | Prevents a single failing MCPModel Context Protocol server from degrading the agent |
| Tool surface | Same schema format as built-in tools | LLM doesn't distinguish between MCPModel Context Protocol and built-in tools |
Risks and Unknowns
- MCPModel Context Protocol server reliability depends on the external server — circuit breaker mitigates but does not eliminate this
- OAuth token refresh for long-lived sessions may require re-authentication
- MCPModel Context Protocol tool schemas are fixed at connection time — dynamic tool addition mid-session may not be reflected
Out of Scope
- Hosting MCPModel Context Protocol servers (except mcp_serve.py which serves Hermes tools)
- MCPModel Context Protocol registry or marketplace
Test Plan: MCPModel Context Protocol Server Integration
Scope
Tests covering MCPModel Context Protocol client connection, tool discovery, tool calling, transport (stdio/SSE), OAuth authentication, circuit breaker, mcp_serve.py, and optional MCPModel Context Protocol server functionality.
Test Files
- tests/tools/test_mcp_tool.py — Core MCPModel Context Protocol tool calling
- tests/tools/test_mcp_tool_401_handling.py — MCPModel Context Protocol auth error handling
- tests/tools/test_mcp_tool_session_expired.py — SessionA single conversation history stored in SQLite with FTS5 search expiry handling
- tests/tools/test_mcp_cancelled_error_propagation.py — Cancellation propagation
- tests/tools/test_mcp_capability_gating.py — Capability gating
- tests/tools/test_mcp_circuit_breaker.py — Circuit breaker pattern
- tests/tools/test_mcp_client_cert.py — Client certificate auth
- tests/tools/test_mcp_dynamic_discovery.py — Dynamic tool discovery
- tests/tools/test_mcp_elicitation.py — MCPModel Context Protocol tool elicitation
- tests/tools/test_mcp_oauth_*.py — OAuth flow tests (4+ files)
- tests/tools/test_mcp_probe.py — Server probing
- tests/tools/test_mcp_sse_transport.py — SSE transport
- tests/tools/test_mcp_stdio_init_timeout.py — Stdio init timeout
- tests/tools/test_mcp_stability.py — Stability under load
- tests/tools/test_mcp_parked_self_probe.py — Self-probe behavior
- tests/tools/test_mcp_utility_capability_gating.py — Utility gating
- tests/hermes_cli/test_mcp_*.py — MCPModel Context Protocol CLICommand-Line Interface commands (5+ files)
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe system shall connect to configured MCPModel Context Protocol servers and discover their tools (connect to MCPModel Context Protocol servers) | test_mcp_tool.py, test_mcp_probe.py |
| FR-2MustMCPModel Context Protocol tools shall be surfaced alongside built-in tools in the agent's tool schemas (surface MCPModel Context Protocol tools) | test_mcp_tool.py |
| FR-3MustThe system shall support both stdio and SSE transport for MCPModel Context Protocol connections (stdio + SSE transport) | test_mcp_sse_transport.py, test_mcp_stdio_init_timeout.py |
| FR-4MustThe system shall support OAuth authentication for MCPModel Context Protocol servers (OAuth auth) | test_mcp_oauth_*.py |
| FR-5MustThe system shall support dynamic discovery of MCPModel Context Protocol tools at runtime (dynamic discovery) | test_mcp_dynamic_discovery.py |
| NFR-1MustAn unresponsive MCPModel Context Protocol server must not block the agent (timeout + circuit breaker) (circuit breaker) | test_mcp_circuit_breaker.py |
requirements
- Should MCP servers be configurable per-profile?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: ACPAgent Communication Protocol Protocol (IDEIntegrated Development Environment Integration)
Overview
Hermes implements the AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol (ACPAgent Communication Protocol) for IDEIntegrated Development Environment integration with VS Code, Zed, and JetBrains editors. The ACPAgent Communication Protocol adapter (acp_adapter/) and ACPAgent Communication Protocol registry (acp_registry/) allow developers to interact with the agent directly from their editor, enabling code-aware conversations, file editing, and terminal commands within the IDEIntegrated Development Environment context.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Developers | Interact with the agent from their code editor for code-aware assistance |
| IDEIntegrated Development Environment integrators | Use the ACPAgent Communication Protocol protocol to build Hermes integrations for any editor |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe ACPAgent Communication Protocol adapter shall provide an API endpoint for editors to connect to the agent | Must | The ACPAgent Communication Protocol adapter shall provide an API endpoint for editors to connect to the agent |
| FR-2MustThe ACPAgent Communication Protocol adapter shall support code-aware context (current file, cursor position, project structure) | Must | The ACPAgent Communication Protocol adapter shall support code-aware context (current file, cursor position, project structure) |
| FR-3MustThe ACPAgent Communication Protocol registry shall maintain a catalog of available ACPAgent Communication Protocol servers | Must | The ACPAgent Communication Protocol registry shall maintain a catalog of available ACPAgent Communication Protocol servers |
| FR-4ShouldThe adapter shall support file editing operations initiated from the IDEIntegrated Development Environment | Should | The adapter shall support file editing operations initiated from the IDEIntegrated Development Environment |
| FR-5ShouldThe adapter shall support terminal command execution from the IDEIntegrated Development Environment | Should | The adapter shall support terminal command execution from the IDEIntegrated Development Environment |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustACPAgent Communication Protocol connections shall be authenticated and scoped to the user's session | Must | Security | ACPAgent Communication Protocol connections shall be authenticated and scoped to the user's session |
| NFR-2ShouldACPAgent Communication Protocol responses should be delivered with sub-second latency for simple queries | Should | Performance | ACPAgent Communication Protocol responses should be delivered with sub-second latency for simple queries |
Constraints
- ACPAgent Communication Protocol uses a JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend protocol over WebSocket or HTTP
- Compatible with VS Code, Zed, and JetBrains editor protocols
Acceptance Criteria
- FR-1MustThe ACPAgent Communication Protocol adapter shall provide an API endpoint for editors to connect to the agent
- Given the ACPAgent Communication Protocol adapter is running
- When an editor connects via the ACPAgent Communication Protocol endpoint
- Then the editor can send queries and receive responses
- FR-2MustThe ACPAgent Communication Protocol adapter shall support code-aware context (current file, cursor position, project structure)
- Given the ACPAgent Communication Protocol adapter receives a query
- When the query includes file context
- Then the agent uses the file context to inform its response
Conflicts
None identified yet.
Open Questions
- Should ACPAgent Communication Protocol support multiple simultaneous editor connections?
Specification: ACPAgent Communication Protocol Protocol (IDEIntegrated Development Environment Integration)
Architecture
ACPAgent Communication Protocol Adapter (acp_adapter/)
│
├── ACPAgent Communication Protocol Server (acp_adapter/server.py)
│ ├── WebSocket endpoint
│ ├── HTTP endpoint
│ └── JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend message handling
│
├── ACPAgent Communication Protocol Registry (acp_registry/)
│ └── Server catalog and discovery
│
└── Editor integrations
├── VS Code extension protocol
├── Zed extension protocol
└── JetBrains plugin protocol
Data Models
ACPAgent Communication Protocol Message
| Field | Type | Description |
|---|---|---|
| method | string | RPC method name |
| params | dict | Method parameters |
| id | string | Request correlation ID |
Code Context
| Field | Type | Description |
|---|---|---|
| file_path | string | Current file path |
| cursor_position | object | Line and column |
| project_root | string | Project root directory |
| selection | string | Selected text |
API Contracts
ACPAgent Communication Protocol follows the JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend 2.0 specification over WebSocket transport. Methods include query submission, file context updates, and tool execution requests.
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Protocol | JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend 2.0 | Standard, language-agnostic, supports both HTTP and WebSocket |
| Transport | WebSocket primary, HTTP fallback | WebSocket enables streaming responses |
| Context sharing | File path + cursor + selection | Lightweight, respects user privacy (no full file upload) |
| Auth | Same credential pool as gateway | Reuses existing auth infrastructure |
Risks and Unknowns
- Editor-specific protocol differences may require adapter customization per editor
- Large project context may exceed token limits when sent as agent context
- ACPAgent Communication Protocol adoption depends on editor ecosystem support
Out of Scope
- Full file system access from editor
- Multi-editor collaboration session
Test Plan: ACPAgent Communication Protocol Protocol (IDEIntegrated Development Environment Integration)
Scope
Tests covering ACPAgent Communication Protocol adapter server, registry maintenance, editor protocol compatibility, and authentication.
Test Files
- tests/hermes_cli/test_copilot_*.py — Copilot/ACPAgent Communication Protocol integration tests (5+ files)
- tests/acp/ — ACPAgent Communication Protocol-specific test directory
- tests/acp_adapter/ — ACPAgent Communication Protocol adapter tests
- tests/agent/test_copilot_acp_client.py — ACPAgent Communication Protocol client tests
- tests/agent/test_copilot_acp_deprecation.py — ACPAgent Communication Protocol deprecation handling
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe ACPAgent Communication Protocol adapter shall provide an API endpoint for editors to connect to the agent (ACPAgent Communication Protocol adapter endpoint) | test_copilot_acp_client.py |
| FR-2MustThe ACPAgent Communication Protocol adapter shall support code-aware context (current file, cursor position, project structure) (code-aware context) | test_copilot_context.py |
| FR-3MustThe ACPAgent Communication Protocol registry shall maintain a catalog of available ACPAgent Communication Protocol servers (ACPAgent Communication Protocol registry) | test_release_acp_registry.py |
requirements
- Should ACP support multiple simultaneous editor connections?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Trajectory and Data Generation
Overview
Hermes includes a research-ready data generation pipeline for producing training trajectories from agent runs. The system comprises batch_runner.py for parallel agent execution, trajectory_compressor.py for compressing tool-calling trajectories, mini_swe_runner.py for SWE-bench style evaluation, and datagen-config-examples/ for configuration templates. This enables researchers to generate training data for tool-calling models at scale.
Stakeholders
| Stakeholder | Interest |
|---|---|
| AI researchers | Generate training trajectories for tool-calling model fine-tuning |
| Evaluators | Run SWE-bench-style evaluations on the agent |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe batch runner shall execute multiple agent instances in parallel across a dataset | Must | The batch runner shall execute multiple agent instances in parallel across a dataset |
| FR-2MustThe batch runner shall support checkpointing for resumable runs | Must | The batch runner shall support checkpointing for resumable runs |
| FR-3MustThe trajectory compressor shall compress tool-calling agent trajectories | Must | The trajectory compressor shall compress tool-calling agent trajectories |
| FR-4MustThe trajectory compressor shall support configurable compression strategies | Must | The trajectory compressor shall support configurable compression strategies |
| FR-5ShouldThe mini SWE runner shall execute SWE-bench style evaluations | Should | The mini SWE runner shall execute SWE-bench style evaluations |
| FR-6ShouldThe system shall provide configuration examples for common data generation setups | Should | The system shall provide configuration examples for common data generation setups |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustBatch runner shall scale to hundreds of parallel agent runs | Must | Performance | Batch runner shall scale to hundreds of parallel agent runs |
| NFR-2ShouldCheckpoint system shall survive process restarts | Should | Reliability | Checkpoint system shall survive process restarts |
Acceptance Criteria
- FR-1MustThe batch runner shall execute multiple agent instances in parallel across a dataset
- Given a dataset of prompts
- When batch_runner.py is invoked
- Then agents run in parallel across the dataset and results are collected
- FR-3MustThe trajectory compressor shall compress tool-calling agent trajectories
- Given a raw agent trajectory
- When trajectory_compressor.py processes it
- Then the compressed trajectory preserves essential tool-calling structure
Conflicts
None identified yet.
Open Questions
- Should compressed trajectories support round-trip reconstruction?
Specification: Trajectory and Data Generation
Architecture
Data Generation Pipeline
│
├── Batch Runner (batch_runner.py)
│ ├── Parallel agent execution
│ ├── Checkpoint system
│ └── Result collection
│
├── Trajectory Compressor (trajectory_compressor.py)
│ ├── Configurable compression levels
│ ├── Tool-call structure preservation
│ └── Token optimization
│
├── SWE-bench Runner (mini_swe_runner.py)
│ └── SWE-bench evaluation harness
│
└── Configuration (datagen-config-examples/)
└── Example configs for common setups
Data Models
Batch Config
| Field | Type | Description |
|---|---|---|
| dataset_path | string | Path to input dataset |
| model | string | Model to use for runs |
| max_concurrent | int | Parallelism limit |
| checkpoint_path | string | Resume checkpoint location |
| output_format | string | JSON, JSONL, or Parquet |
Compressed Trajectory
| Field | Type | Description |
|---|---|---|
| messages | array | Compressed message sequence |
| tool_calls | array | Extracted tool call data |
| metadata | object | Run config, duration, token counts |
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Compression | Tool-call-structure-aware | Preserves training-relevant structure while reducing token count |
| Checkpointing | Periodic state dump | Enables long-running batch jobs to survive crashes |
| Output format | JSONL | Standard for ML training pipelines |
Risks and Unknowns
- Batch runner with hundreds of parallel agents requires significant API budget
- Trajectory compression quality varies by conversation length and complexity
- SWE-bench evaluation requires code execution sandbox
Out of Scope
- Training model weights from generated data
- Dataset hosting or distribution
Test Plan: Trajectory and Data Generation
Scope
Tests covering batch runner, trajectory compression, and checkpointing functionality.
Test Files
- tests/test_batch_runner_checkpoint.py — Batch runner checkpointing
- tests/run_agent/test_codex_app_server_compaction.py — Trajectory compression
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe batch runner shall execute multiple agent instances in parallel across a dataset (batch execution) | test_batch_runner_checkpoint.py |
| FR-2MustThe batch runner shall support checkpointing for resumable runs (checkpointing) | test_batch_runner_checkpoint.py |
requirements
- Should compressed trajectories support round-trip reconstruction?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Internationalization
Overview
Hermes includes internationalization support with translation files in locales/ for multiple languages. The system provides localized strings for CLICommand-Line Interface output, error messages, and documentation. README translations exist in Spanish (README.es.md), Chinese (README.zh-CN.md), and Urdu (README.ur-pk.md).
Stakeholders
| Stakeholder | Interest |
|---|---|
| Non-English users | Use Hermes with CLICommand-Line Interface output and documentation in their preferred language |
| International contributors | Add and maintain translations for their language |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe system shall support locale-based string loading from the locales/ directory | Must | The system shall support locale-based string loading from the locales/ directory |
| FR-2ShouldCLICommand-Line Interface output shall respect the system locale setting | Should | CLICommand-Line Interface output shall respect the system locale setting |
| FR-3ShouldCore documentation (README) shall be available in multiple languages | Should | Core documentation (README) shall be available in multiple languages |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1ShouldAdding a new locale shall require only a new translation file, no code changes | Should | Maintainability | Adding a new locale shall require only a new translation file, no code changes |
Acceptance Criteria
- FR-1MustThe system shall support locale-based string loading from the locales/ directory
- Given the system locale is set to a supported language
- When the CLICommand-Line Interface displays a localized string
- Then the translated string is shown
Conflicts
None identified yet.
Open Questions
- Should skill SKILL.md files also be localized?
Specification: Internationalization
Architecture
Internationalization (locales/)
│
├── en/ — English (default)
├── es/ — Spanish
├── zh-CN/ — Chinese (Simplified)
└── <locale>/ — Future locales
Data Models
Locale file format
| Field | Type | Description |
|---|---|---|
| key | string | Translation key (dot-notation) |
| value | string | Translated string |
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Storage | Directory-based locale files | Simple, no dependencies, easy to add new locales |
| Default | English | Always fall back to English for untranslated keys |
| CLICommand-Line Interface locale detection | System locale or config setting | Respects user's environment |
Risks and Unknowns
- Maintainability of translations across rapid development — new strings may not be translated promptly
- Not all CLICommand-Line Interface output is currently internationalized (incremental adoption)
Out of Scope
- Runtime language switching (requires agent restart)
- Machine translation of missing strings
Test Plan: Internationalization
Scope
Tests covering locale string loading and locale-aware CLICommand-Line Interface output.
Test Files
- Tests for locale loading are integrated into CLICommand-Line Interface and config test suites
- No dedicated internationalization test module identified
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe system shall support locale-based string loading from the locales/ directory (locale-based string loading) | CLICommand-Line Interface integration tests |
requirements
- Should skill SKILL.md files also be localized?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers Multi-AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Work Queue
Overview
KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers is a durable, SQLite-backed multi-agent work queue that lets multiple Hermes profiles and workers collaborate on shared tasks. It provides a CLICommand-Line Interface (hermes kanban <verb>), a dedicated worker/orchestrator toolset (kanban_* tools) with zero schema footprint when idle, and a long-lived dispatcher that reclaims stale claims, promotes ready tasks, atomically claims them, and spawns assigned profiles. The dispatcher runs inside the gateway by default with a standalone daemon option. Boards are the hard isolation boundary; tenants are a soft namespace within a board.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Operators / multi-profile users | Coordinate multiple Hermes profiles on shared tasks with a persistent board they can inspect and drive from the CLICommand-Line Interface or dashboard |
| Orchestrator agents | Create and assign tasks via kanban_create, chain work through dependency links, and track progress |
| Worker agents | Claim, work, heartbeat, comment on, and complete tasks without seeing other boards |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe system shall provide a `hermes kanban` CLICommand-Line Interface with board, task, run, and board lifecycle verbs | Must | The system shall provide a hermes kanban CLICommand-Line Interface with board, task, run, and board lifecycle verbs |
| FR-2MustThe system shall persist boards and tasks in a SQLite database keyed by board directory | Must | The system shall persist boards and tasks in a SQLite database keyed by board directory |
| FR-3MustThe system shall support board creation, listing, switching, renaming, archiving (recoverable), and hard deletion | Must | The system shall support board creation, listing, switching, renaming, archiving (recoverable), and hard deletion |
| FR-4MustThe system shall support task creation (including idempotent dedup keys), listing, showing with comments/events, editing, assigning, blocking, unblocking, completing, and archiving | Must | The system shall support task creation (including idempotent dedup keys), listing, showing with comments/events, editing, assigning, blocking, unblocking, completing, and archiving |
| FR-5MustThe system shall support dependency links (parent->child) and task links/unlinks | Must | The system shall support dependency links (parent->child) and task links/unlinks |
| FR-6MustThe system shall support file attachments and attachment listing/removal | Must | The system shall support file attachments and attachment listing/removal |
| FR-7MustThe system shall support task comments with a durable event log | Must | The system shall support task comments with a durable event log |
| FR-8MustThe system shall expose a `kanban_*` toolset for worker/orchestrator agents (show, complete, block, heartbeat, comment, create, link, attach, attachments) | Must | The system shall expose a kanban_* toolset for worker/orchestrator agents (show, complete, block, heartbeat, comment, create, link, attach, attachments) |
| FR-9MustThe dispatcher shall reclaim stale claims, promote ready tasks, atomically claim tasks, and spawn assigned profiles | Must | The dispatcher shall reclaim stale claims, promote ready tasks, atomically claim tasks, and spawn assigned profiles |
| FR-10MustThe dispatcher shall run inside the gateway by default (`kanban.dispatch_in_gateway: true`) with a standalone `hermes kanban daemon` option | Must | The dispatcher shall run inside the gateway by default (kanban.dispatch_in_gateway: true) with a standalone hermes kanban daemon option |
| FR-11MustWorkers shall be isolated per board via a pinned `HERMES_KANBAN_BOARD` environment variable | Must | Workers shall be isolated per board via a pinned HERMES_KANBAN_BOARD environment variable |
| FR-12ShouldThe system shall auto-block a task after a configurable consecutive failure limit to prevent spin loops | Should | The system shall auto-block a task after a configurable consecutive failure limit to prevent spin loops |
| FR-13ShouldThe system shall support tenant namespaces within a board (workspace-path + memory-key isolation) | Should | The system shall support tenant namespaces within a board (workspace-path + memory-key isolation) |
| FR-14ShouldThe system shall provide a web dashboard plugin for visualizing boards and a systemd unit for standalone deployment | Should | The system shall provide a web dashboard plugin for visualizing boards and a systemd unit for standalone deployment |
| FR-15ShouldThe system shall support a swarm-style multi-agent pattern with dedicated worker, verifier, and synthesizer profiles | Should | The system shall support a swarm-style multi-agent pattern with dedicated worker, verifier, and synthesizer profiles |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustWorker agents must not see or modify boards other than the one pinned in their environment | Must | Isolation | Worker agents must not see or modify boards other than the one pinned in their environment |
| NFR-2MustTask state, comments, attachments, and run history shall survive process restarts (SQLite-backed) | Must | Durability | Task state, comments, attachments, and run history shall survive process restarts (SQLite-backed) |
| NFR-3MustAtomic claims shall prevent two workers from claiming the same task simultaneously | Must | Concurrency | Atomic claims shall prevent two workers from claiming the same task simultaneously |
| NFR-4ShouldThe dispatcher shall reclaim stale claims (default 60s tick) so abandoned work is not lost forever | Should | Availability | The dispatcher shall reclaim stale claims (default 60s tick) so abandoned work is not lost forever |
Constraints
- BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others is the hard boundary: workers are spawned with
HERMES_KANBAN_BOARDpinned in their env - Tenant is a soft namespace within a board
- After
kanban.failure_limitconsecutive non-success attempts (default 2), the dispatcher auto-blocks the task - The
kanbantoolset is only enabled for dispatcher-spawned workers unless the profile explicitly enables it
Acceptance Criteria
- FR-1MustThe system shall provide a `hermes kanban` CLICommand-Line Interface with board, task, run, and board lifecycle verbs
- Given the Hermes CLICommand-Line Interface
- When the user runs
hermes kanban --help - Then board, task, run, and lifecycle verbs are listed
- FR-4MustThe system shall support task creation (including idempotent dedup keys), listing, showing with comments/events, editing, assigning, blocking, unblocking, completing, and archiving
- Given an empty board
- When the user creates a task with a dedup key and creates it again with the same key
- Then the second call returns the existing task id instead of duplicating
- FR-9MustThe dispatcher shall reclaim stale claims, promote ready tasks, atomically claim tasks, and spawn assigned profiles
- Given a ready task assigned to a profile and a running dispatcher
- When the dispatch tick fires
- Then the task is atomically claimed and the assigned profile is spawned
- FR-11MustWorkers shall be isolated per board via a pinned `HERMES_KANBAN_BOARD` environment variable
- Given a worker spawned for board A
- When the worker lists boards
- Then only board A is visible
- FR-12ShouldThe system shall auto-block a task after a configurable consecutive failure limit to prevent spin loops
- Given a task that fails more than the failure limit times
- When the dispatcher processes it
- Then the task is auto-blocked to prevent a spin loop
Conflicts
None identified yet.
Open Questions
- Should the dispatcher support remote/standalone boards across machines, or is a single gateway host the supported topology?
- Should tenant isolation extend to per-tenant attachment storage?
Specification: KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers Multi-AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Work Queue
Overview
KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers is implemented as three cooperating layers: a CLICommand-Line Interface parser and SQLite-backed store (hermes_cli/kanban.py), a kanban_* toolset for agent workers (tools/kanban_tools.py), and a long-lived dispatcher embedded in the gateway (or run standalone via hermes kanban daemon). Boards live in a directory tree where each board has its own SQLite database, workspaces directory, and (when run standalone) dispatcher.
Architecture
User / orchestrator agent
│ kanban_create / kanban_link / kanban_comment ...
v
kanban_* tools (tools/kanban_tools.py) hermes kanban CLICommand-Line Interface (hermes_cli/kanban.py)
│ │
└───────────────► SQLite board store (per-board DB)
│
v
Dispatcher (embedded in gateway, default)
│ - reclaim stale claims (60s tick)
│ - promote ready tasks
│ - atomically claim + spawn assigned profile
│ - auto-block after failure_limit
│
└──► Worker agent (spawned, HERMES_KANBAN_BOARD pinned)
│ kanban_heartbeat / kanban_complete / kanban_comment
v
BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others DB (claim released, run history appended)
Data Models
BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others
| Field | Type | Constraints | Description |
|---|---|---|---|
| slug | text | immutable | Directory name; identifier for the board |
| name | string | — | Human-readable display name (renamable) |
| db_path | path | per-board | SQLite database path under the board directory |
| workspaces | path | per-board | Worker workspace directory for the board |
| dispatcher | process | optional | Standalone dispatcher process when not gateway-embedded |
Task
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | uuid | PK | Task identifier |
| title | text | not null | Task title |
| description | text | — | Free-form task body |
| status | enum | todo/in_progress/blocked/done/archived | Card status; blocked is explicit and skips brief running-to-blocked transition |
| priority | int | default 0 | Priority tiebreaker |
| assignee | string | nullable | Assigned profile |
| tenant | string | nullable | Tenant namespace within a board |
| dedup_key | text | unique | Idempotent create key (no duplicate task created on re-submission) |
| created_by | string | — | Creator/anchor profile |
| failure_count | int | default 0 | Consecutive non-success attempts |
API Contracts
The model-facing contract is the kanban_* toolset:
| Tool | Purpose |
|---|---|
| kanban_show | Show a task with comments and events |
| kanban_complete | Mark a task done |
| kanban_block | Block a task |
| kanban_heartbeat | Report worker liveness (extends the claim) |
| kanban_comment | Append a comment |
| kanban_create | Create a task (idempotent via dedup key) |
| kanban_link | Add a parent->child dependency |
| kanban_attach / kanban_attach_url | Attach a file/URL to a task |
| kanban_attachments | List a task's attachments |
Profiles that explicitly enable the kanban toolset outside a dispatcher-spawned task also get kanban_list and kanban_unblock for board routing.
Sequences
Dispatch tick (default 60s)
Dispatcher tick
→ reclaim stale claims (SIGTERM then SIGKILL runaway workers)
→ promote ready tasks (respect dependency links)
→ atomically claim a task
→ spawn the assigned profile (HERMES_KANBAN_BOARD pinned)
→ worker heartbeats keep the claim alive
→ worker completes → run history recorded → next promotion
Idempotent create (automation / webhooks)
kanban_create(dedup_key="K")
→ existing task with key K? → return its id (no duplicate)
→ otherwise create a new task with key K
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Storage | SQLite per board | Durable, zero-dependency, survives restarts |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others as hard boundary | HERMES_KANBAN_BOARD env pinned on workers | Prevents cross-board visibility without per-task ACLs |
| Dispatcher location | Embedded in gateway by default | No extra process to run; hermes kanban daemon --force for standalone |
| Failure handling | Auto-block after failure_limit | Prevents unbounded retry spin loops |
| Tenant isolation | Workspace-path + memory-key namespacing | One specialist fleet can serve multiple businesses on one board |
| Runaway workers | SIGTERM then SIGKILL on reclaim | Guarantees abandoned tasks are freed in bounded time |
Risks and Unknowns
- Single-host dispatcher limits multi-machine collaboration (out of scope for now)
- Auto-block heuristics may block a task a human could complete manually — operators can unblock
- Attachment storage lives in the board directory, so hard-deleting a board removes attachments
Out of Scope
- Cross-machine / distributed boards
- Task dependency DAG execution (links exist, but the dispatcher promotes ready tasks; complex DAG scheduling is future work)
- Fine-grained per-user ACLs beyond the board/tenant isolation model
Test Plan: KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers Multi-AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Work Queue
Scope
Tests covering the kanban CLICommand-Line Interface, the SQLite board store, the worker/orchestrator toolset, dispatcher behavior (claim/reclaim/promotion/spawn), board isolation, attachments, comment injection, model overrides, and dashboard integration.
Test Files
- tests/tools/test_kanban_tools.py — Worker/orchestrator
kanban_*toolset - tests/tools/test_kanban_redaction.py — Sensitive-data redaction in kanban tool output
- tests/tools/test_delegate_kanban_isolation.py — Subagent/worker board isolation
- tests/tools/test_kanban_comment_injection.py — Comment injection from worker environment
- tests/plugins/test_kanban_worker_runs.py — Worker run lifecycle through the dispatcher
- tests/plugins/test_kanban_board_project_api.py — BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others and project APIs
- tests/plugins/test_kanban_dashboard_plugin.py — Dashboard plugin wiring
- tests/plugins/test_kanban_attachments.py — File attachment lifecycle
- tests/plugins/test_kanban_estimate.py — Task effort estimation
- tests/plugins/test_kanban_model_override.py — Per-task model override propagation
Unit Tests
- BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others creation, listing, switching, renaming, archiving, and deletion
- Task create (including dedup-key idempotency), show, edit, assign, block, complete, archive
- Dependency link/unlink behavior
- Attachment add/list/remove
Integration Tests
- Worker spawned for board A cannot see board B (isolation via pinned env)
- Comment injection from the worker environment into a task
- Model override reaching the spawned worker
- Dashboard plugin loading against a real board store
Edge Cases and Failure Scenarios
| ID | Scenario | Expected Behavior |
|---|---|---|
| EC-1 | Duplicate create with same dedup key | Returns existing task id, no duplicate row |
| EC-2 | Task exceeding failure limit | Dispatcher auto-blocks it to prevent a spin loop |
| EC-3 | Worker heartbeat expires (stale claim) | Dispatcher reclaims and re-promotes the task |
| EC-4 | Runaway worker on reclaim | SIGTERM then SIGKILL frees the task |
| EC-5 | BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others hard-deleted with attachments | BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others directory removed; no recovery (documented) |
| EC-6 | Sensitive data in tool output | Redacted before returning to the agent |
Test Infrastructure
- Per-board SQLite fixtures in temp directories
- Mock gateway/dispatcher state for tick-driven tests
- Isolated
HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware)per test (no writes to~/.hermes/)
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe system shall provide a `hermes kanban` CLICommand-Line Interface with board, task, run, and board lifecycle verbs (kanban CLICommand-Line Interface) | test_kanban_board_project_api.py |
| FR-3MustThe system shall support board creation, listing, switching, renaming, archiving (recoverable), and hard deletion (board lifecycle) | test_kanban_board_project_api.py |
| FR-4MustThe system shall support task creation (including idempotent dedup keys), listing, showing with comments/events, editing, assigning, blocking, unblocking, completing, and archiving (task lifecycle + dedup) | test_kanban_tools.py, test_kanban_board_project_api.py |
| FR-6MustThe system shall support file attachments and attachment listing/removal (attachments) | test_kanban_attachments.py |
| FR-7MustThe system shall support task comments with a durable event log (comments) | test_kanban_comment_injection.py |
| FR-8MustThe system shall expose a `kanban_*` toolset for worker/orchestrator agents (show, complete, block, heartbeat, comment, create, link, attach, attachments) (kanban_* toolset) | test_kanban_tools.py |
| FR-9MustThe dispatcher shall reclaim stale claims, promote ready tasks, atomically claim tasks, and spawn assigned profiles/FR-10MustThe dispatcher shall run inside the gateway by default (`kanban.dispatch_in_gateway: true`) with a standalone `hermes kanban daemon` option (dispatcher) | test_kanban_worker_runs.py |
| FR-11MustWorkers shall be isolated per board via a pinned `HERMES_KANBAN_BOARD` environment variable (board isolation) | test_delegate_kanban_isolation.py |
| FR-12ShouldThe system shall auto-block a task after a configurable consecutive failure limit to prevent spin loops (auto-block) | test_kanban_worker_runs.py |
| FR-14ShouldThe system shall provide a web dashboard plugin for visualizing boards and a systemd unit for standalone deployment (dashboard) | test_kanban_dashboard_plugin.py |
| NFR-1MustWorker agents must not see or modify boards other than the one pinned in their environment (isolation) | test_delegate_kanban_isolation.py |
| NFR-3MustAtomic claims shall prevent two workers from claiming the same task simultaneously (atomic claims) | test_kanban_worker_runs.py |
requirements
- Should the dispatcher support remote/standalone boards across machines, or is a single gateway host the supported topology?
- Should tenant isolation extend to per-tenant attachment storage?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Observability
Overview
Hermes provides a backend-neutral observability layer that lets plugins reconstruct agent execution without changing runtime behavior. A documented observer-hook contract (docs/observability/) exposes stable lifecycle events with correlation IDs, sanitized payloads, timing, status, and error fields. Consumers include the Langfuse and NeMo Relay plugins, plus a Prometheus-format /v1/metrics export for gateway runtime health and a first-party NeMo Relay shared-metrics path that requires no plugin.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Operators | Monitor gateway health, platform up/down state, cron scheduler health, and agent execution traces |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles developers | Build trace/metric/audit/replay/export integrations (Langfuse, OpenTelemetry-style collectors, NeMo Relay) |
| Core maintainers | Keep observability backend-neutral so no single vendor is baked into the core |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe system shall expose observer hooks covering session, turn-scoped LLM, request-scoped API (pre/post/error), tool lifecycle, approval, and subagent lifecycle events | Must | The system shall expose observer hooks covering session, turn-scoped LLM, request-scoped API (pre/post/error), tool lifecycle, approval, and subagent lifecycle events |
| FR-2MustHook callbacks shall receive correlation IDs (session/turn/task/api_request) so events can be joined across a request | Must | Hook callbacks shall receive correlation IDs (session/turn/task/api_request) so events can be joined across a request |
| FR-3MustHook payloads shall be sanitized before delivery to remove sensitive data | Must | Hook payloads shall be sanitized before delivery to remove sensitive data |
| FR-4MustHooks shall be fail-open: a failing callback must not change runtime behavior or crash the agent | Must | Hooks shall be fail-open: a failing callback must not change runtime behavior or crash the agent |
| FR-5MustThe gateway shall export a Prometheus-format `/v1/metrics` endpoint with gateway, platform, and cron scheduler gauges | Must | The gateway shall export a Prometheus-format /v1/metrics endpoint with gateway, platform, and cron scheduler gauges |
| FR-6MustThe Langfuse plugin shall consume the observer contract to deliver traces | Must | The Langfuse plugin shall consume the observer contract to deliver traces |
| FR-7MustThe NeMo Relay plugin shall consume the observer contract and shared-metrics path | Must | The NeMo Relay plugin shall consume the observer contract and shared-metrics path |
| FR-8ShouldThe telemetry schema shall be versioned (`hermes.observer.v1`) for forward compatibility | Should | The telemetry schema shall be versioned (hermes.observer.v1) for forward compatibility |
| FR-9ShouldScripts/collectors under scripts/observability/ shall support OpenTelemetry-style capture | Should | Scripts/collectors under scripts/observability/ shall support OpenTelemetry-style capture |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustObservability must be read-only: it must not replace provider requests, tool arguments, or execution callbacks | Must | Safety | Observability must be read-only: it must not replace provider requests, tool arguments, or execution callbacks |
| NFR-2MustObserver callbacks must never block the agent's hot path (fail-open, no exceptions propagate) | Must | Reliability | Observer callbacks must never block the agent's hot path (fail-open, no exceptions propagate) |
| NFR-3MustPayloads must be sanitized so secrets and personal data are not exported | Must | Privacy | Payloads must be sanitized so secrets and personal data are not exported |
| NFR-4ShouldAdding observer fields must remain backward-compatible (callbacks accept `**kwargs`) | Should | Compatibility | Adding observer fields must remain backward-compatible (callbacks accept **kwargs) |
Constraints
- Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior are read-only and must not alter planner, provider, memory, tool, approval, CLICommand-Line Interface, gateway, or execution semantics
- Behavior-changing wrappers are outside the observer contract
- Payload sanitization happens before hooks fire
Acceptance Criteria
- FR-1MustThe system shall expose observer hooks covering session, turn-scoped LLM, request-scoped API (pre/post/error), tool lifecycle, approval, and subagent lifecycle events
- Given an agent turn with tool calls and an API request
- When the observer contract is active
- Then session, LLM, API, and tool lifecycle events are emitted with status and timing
- FR-2MustHook callbacks shall receive correlation IDs (session/turn/task/api_request) so events can be joined across a request
- Given events from one agent turn
- When events are inspected
- Then they share a correlation id (turn/task/api_request) that joins them
- FR-3MustHook payloads shall be sanitized before delivery to remove sensitive data
- Given a tool call that includes a secret value
- When the pre/post tool hook fires
- Then the payload contains no secret value
- FR-4MustHooks shall be fail-open: a failing callback must not change runtime behavior or crash the agent
- Given a plugin callback that raises
- When the hook fires
- Then the error is logged and the agent continues unchanged
- FR-5MustThe gateway shall export a Prometheus-format `/v1/metrics` endpoint with gateway, platform, and cron scheduler gauges
- Given a running gateway
- When
/v1/metricsis scraped - Then gateway, platform, and cron scheduler gauges are present
Conflicts
None identified yet.
Open Questions
- Should the first-party shared-metrics path be gated behind an opt-in config key, or is it acceptable as always-on for gateway operators?
Specification: Observability
Overview
Observability is delivered through three cooperating mechanisms: (1) the observer-hook contract, which plugins use to reconstruct execution; (2) a Prometheus-format /v1/metrics HTTP export for gateway runtime health; and (3) the Langfuse and NeMo Relay plugins plus shared-metrics scripts that consume both. The contract is backend-neutral and versioned, so any vendor can integrate without core changes.
Architecture
AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory / GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core runtime
│ emits lifecycle events (session, LLM, API, tool, approval, subagent)
v
Observer hook contract (docs/observability/README.md)
│ correlation IDs · sanitized payloads · timing/status/error · hermes.observer.v1
│
├──► plugins/observability/langfuse/ (traces)
├──► plugins/observability/nemo_relay/ (traces + shared metrics)
│
GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core runtime health
│ /v1/metrics (Prometheus text format)
v
scripts/observability/ (OpenTelemetry-style capture collectors, health export probe)
Data Models
Observer lifecycle events
| Event | Scope | Key fields |
|---|---|---|
| session_start / session_end | session | session_id, platform, profile |
| turn_llm | turn | turn_id, model, tokens, latency |
| pre_api_request / post_api_request / api_request_error | api_request | api_request_id, provider, status, duration |
| pre_tool_call / post_tool_call | tool | tool_name, status, result, duration |
| approval | — | action, decision |
| subagent | — | subagent_id, goal, status |
Every event carries correlation IDs (session/turn/task/api_request), a timestamp, status, timing, and sanitized payload. Callbacks accept **kwargs so new fields are additive and backward-compatible.
GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core metrics (/v1/metrics)
| Metric | Type | Description |
|---|---|---|
| gateway up/degraded | gauge | GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core runtime state |
| platform up/degraded | gauge | Per-platform adapter health |
| cron scheduler | gauge | Scheduler heartbeat / job state |
API Contracts
GET /v1/metrics
Response (200 OK): Prometheus text format (content-type text/plain). Body lists gateway gauges, per-platform up/degraded gauges, and cron scheduler gauges.
Error Responses: 401 when the metrics endpoint requires auth; otherwise standard HTTP errors.
Sequences
PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles trace flow
AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory turn
→ pre_api_request hook (api_request_id generated)
→ post_api_request hook (status, duration, sanitized body)
→ pre_tool_call / post_tool_call hooks
→ Langfuse / NeMo Relay plugin serializes to its backend
→ correlation ids join all events into one trace
GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core metrics scrape
Prometheus (or operator)
→ GET /v1/metrics
→ gateway emits runtime gauges
→ platform adapters report up/degraded
→ cron scheduler reports heartbeat
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Hook registration | ctx.register_hook(event, callback) in register(ctx) |
Reuses the existing plugin surface, no new core mechanism |
| Backend-neutrality | Contract, not bindings | Any vendor integrates; no vendor baked into core |
| Sanitization | Before hooks fire | Secrets never leave the process |
| Fail-open | Exceptions caught and logged | A broken observer plugin cannot break the agent |
| Correlation | session/turn/task/api_request ids | Cross-event joins for trace reconstruction |
| Metrics export | Prometheus text format on /v1/metrics | Standard scrape protocol, zero dependency |
Risks and Unknowns
- Payload sanitization must keep up with new sensitive fields (secrets, tokens, PII)
- OpenTelemetry-style collectors are scripts, not a maintained core integration — coverage may lag
/v1/metricsauthentication posture (who may scrape) is deployment-dependent
Out of Scope
- A built-in metrics database or dashboard UI (Langfuse/NeMo Relay/collectors fill this role)
- Behavior-changing instrumentation (observers report, they do not modify)
- Any single-vendor binding in the core tree
Test Plan: Observability
Scope
Tests covering the observer-hook contract events and correlation, payload sanitization, fail-open behavior, the /v1/metrics gateway export, and the Langfuse / NeMo Relay plugin consumers and shared-metrics scripts.
Test Files
- tests/plugins/test_langfuse_plugin.py — Langfuse plugin trace delivery against the observer contract
- tests/plugins/test_nemo_relay_plugin.py — NeMo Relay plugin trace + shared-metrics delivery
- tests/scripts/test_smoke_nemo_relay_shared_metrics.py — Shared-metrics path smoke test
Unit Tests
- Observer hook callback registration and invocation for each lifecycle event
- Correlation ID propagation across event types
- Payload sanitization before hook delivery
Integration Tests
- Langfuse plugin consuming real lifecycle events from an agent turn
- NeMo Relay plugin consuming the contract and the shared-metrics path
- GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core
/v1/metricsendpoint emitting runtime gauges
End-to-End Tests
- A full agent turn with API request + tool call produces a joinable trace through the Langfuse consumer
Edge Cases and Failure Scenarios
| ID | Scenario | Expected Behavior |
|---|---|---|
| EC-1 | Observer callback raises | Error logged; agent continues unchanged (fail-open) |
| EC-2 | Payload contains secret/token | Value removed before hook delivery |
| EC-3 | New observer field added | Callbacks accepting **kwargs remain compatible |
| EC-4 | Metrics endpoint scraped with no platforms | GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core + cron gauges present; platform gauges show down/absent, not error |
| EC-5 | /v1/metrics requested without auth (when enabled) | 401 returned |
Test Infrastructure
- Fake agent/turn fixtures emitting observer events
- Temp HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) isolation
- Mock Langfuse / NeMo Relay backends (no live network)
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe system shall expose observer hooks covering session, turn-scoped LLM, request-scoped API (pre/post/error), tool lifecycle, approval, and subagent lifecycle events (lifecycle events) | test_langfuse_plugin.py, test_nemo_relay_plugin.py |
| FR-2MustHook callbacks shall receive correlation IDs (session/turn/task/api_request) so events can be joined across a request (correlation IDs) | test_langfuse_plugin.py |
| FR-3MustHook payloads shall be sanitized before delivery to remove sensitive data (sanitization) | test_langfuse_plugin.py, test_nemo_relay_plugin.py |
| FR-4MustHooks shall be fail-open: a failing callback must not change runtime behavior or crash the agent (fail-open) | test_langfuse_plugin.py |
| FR-5MustThe gateway shall export a Prometheus-format `/v1/metrics` endpoint with gateway, platform, and cron scheduler gauges (/v1/metrics) | test_smoke_nemo_relay_shared_metrics.py |
| FR-6MustThe Langfuse plugin shall consume the observer contract to deliver traces (Langfuse plugin) | test_langfuse_plugin.py |
| FR-7MustThe NeMo Relay plugin shall consume the observer contract and shared-metrics path (NeMo Relay plugin) | test_nemo_relay_plugin.py |
| FR-9ShouldScripts/collectors under scripts/observability/ shall support OpenTelemetry-style capture (shared metrics scripts) | test_smoke_nemo_relay_shared_metrics.py |
requirements
- Should the first-party shared-metrics path be gated behind an opt-in config key, or is it acceptable as always-on for gateway operators?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Multi-Platform CLICommand-Line Interface
Overview
The HermesCLI class provides an interactive terminal experience with Rich-styled banners, prompt_toolkit input with autocomplete, a kawaii animated spinner, a data-driven skin/theme system, and a central slash command registry supporting ~70 commands across five categories. The CLICommand-Line Interface is the primary user-facing surface and also serves as the embedding target for the web dashboard via PTYPseudo-terminal bridge.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Power users | A rich, visually appealing interactive CLICommand-Line Interface with autocomplete, theming, and fast slash commands |
| Developers | Easy-to-add slash commands via the COMMAND_REGISTRY with automatic cross-surface dispatch |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe CLICommand-Line Interface shall support slash commands for session management (/new, /undo, /branch, /compress, /snapshot) | Must | The CLICommand-Line Interface shall support slash commands for session management (/new, /undo, /branch, /compress, /snapshot) |
| FR-2MustThe CLICommand-Line Interface shall support configuration commands (/model, /skin, /reasoning, /voice, /fast, /yolo) | Must | The CLICommand-Line Interface shall support configuration commands (/model, /skin, /reasoning, /voice, /fast, /yolo) |
| FR-3MustThe CLICommand-Line Interface shall support tools and skills management commands (/tools, /skills, /cron, /learn, /plugins, /kanban, /curator, /blueprint) | Must | The CLICommand-Line Interface shall support tools and skills management commands (/tools, /skills, /cron, /learn, /plugins, /kanban, /curator, /blueprint) |
| FR-4MustThe CLICommand-Line Interface shall support info commands (/help, /usage, /insights, /debug, /version) | Must | The CLICommand-Line Interface shall support info commands (/help, /usage, /insights, /debug, /version) |
| FR-5MustThe CLICommand-Line Interface shall support a skin/theme system with built-in skins and user-customizable YAML skins | Must | The CLICommand-Line Interface shall support a skin/theme system with built-in skins and user-customizable YAML skins |
| FR-6MustThe CLICommand-Line Interface shall provide Rich-styled banners and a kawaii animated spinner during API calls | Must | The CLICommand-Line Interface shall provide Rich-styled banners and a kawaii animated spinner during API calls |
| FR-7MustThe CLICommand-Line Interface shall support prompt_toolkit input with slash-command autocomplete | Must | The CLICommand-Line Interface shall support prompt_toolkit input with slash-command autocomplete |
| FR-8MustThe CLICommand-Line Interface shall support history across sessions | Must | The CLICommand-Line Interface shall support history across sessions |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustSlash command dispatch shall complete in under 100ms | Must | Performance | Slash command dispatch shall complete in under 100ms |
| NFR-2MustThe CLICommand-Line Interface shall work in tmux, screen, iTerm2, and standard terminals | Must | Compatibility | The CLICommand-Line Interface shall work in tmux, screen, iTerm2, and standard terminals |
Constraints
- The skin engine must be pure data — no code changes needed to add a skin
- Skin customization includes banner colors, spinner faces/verbs/wings, tool prefixes, per-tool emojis, and branding text
Acceptance Criteria
- FR-1MustThe CLICommand-Line Interface shall support slash commands for session management (/new, /undo, /branch, /compress, /snapshot)
- Given the CLICommand-Line Interface is running
- When the user types /new
- Then a new session is created and the conversation restarts
- FR-5MustThe CLICommand-Line Interface shall support a skin/theme system with built-in skins and user-customizable YAML skins
- Given the CLICommand-Line Interface is running
- When the user types /skin ares
- Then the banner colors and spinner change to the ares theme
- FR-7MustThe CLICommand-Line Interface shall support prompt_toolkit input with slash-command autocomplete
- Given the CLICommand-Line Interface is running
- When the user types /
- Then a dropdown of available slash commands appears
Conflicts
None identified yet.
Open Questions
- Should the classic prompt_toolkit CLICommand-Line Interface eventually be deprecated in favor of the TUITerminal User Interface?
Specification: Multi-Platform CLICommand-Line Interface
Overview
The CLICommand-Line Interface is built on prompt_toolkit for input with autocompletion and Rich for output rendering. Commands are defined centrally in the COMMAND_REGISTRY in hermes_cli/commands.py, which all downstream consumers (CLICommand-Line Interface dispatch, gateway dispatch, Telegram menu, Slack mapping, autocomplete) derive from automatically.
Architecture
prompt_toolkit REPL
│
├── text input ──→ process_text()
│ │
│ ┌────┴────────┐
│ │ Text input │→ AIAgent.chat()
│ │ │
│ │ Slash cmd │→ process_command()
│ └─────────────┘
│ │
│ resolve_command(name)
│ │
│ matched CommandDef
│ │
│ handler method
│
└── autocomplete ──→ SlashCommandCompleter
│
queries COMMAND_REGISTRY
Data Models
CommandDef
| Field | Type | Constraints | Description |
|---|---|---|---|
| name | string | PK, not null | Canonical command name without slash |
| description | string | not null | Human-readable description |
| category | string | SessionA single conversation history stored in SQLite with FTS5 search/Configuration/Tools & Skills/Info/Exit | Display category for help |
| aliases | tuple | optional | Alternative names |
| args_hint | string | optional | Argument placeholder shown in help |
| cli_only | bool | default false | Only available in interactive CLICommand-Line Interface |
| gateway_only | bool | default false | Only available in messaging platforms |
| gateway_config_gate | string | optional | Config dotpath that gates availability in gateway |
SkinConfig
| Field | Type | Description |
|---|---|---|
| name | string | Skin identifier |
| colors | dict | Banner border, title, accent, dim, text; response border |
| spinner | dict | Waiting faces, thinking faces, thinking verbs, optional wings |
| branding | dict | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory name, welcome message, response label, prompt symbol |
| tool_prefix | string | Prefix character for tool output |
| tool_emojis | dict | Per-tool emoji mapping |
API Contracts
No external API contracts. The CLICommand-Line Interface communicates with AIAgent through direct method calls.
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Skin engine | Pure data (YAML + defaults) | No code changes needed for new skins; users can create custom skins |
| Command registry | Centralized list | One definition drives CLICommand-Line Interface, gateway, autocomplete, help, Telegram BotCommands, and Slack mapping |
| Input framework | prompt_toolkit | Supports cross-platform input, autocomplete, history, Vi mode |
| Output rendering | Rich | Supports styled output, tables, panels, progress display |
Risks and Unknowns
- The classic CLICommand-Line Interface has grown to ~16k LOC — god-file refactoring is needed but risky for an active codebase
- prompt_toolkit's patch_stdout conflicts with ANSI escape codes used by the spinner
Out of Scope
- The TUITerminal User Interface (ui-tui/) is a separate surface, not part of the classic CLICommand-Line Interface
- GUI elements beyond terminal rendering
Test Plan: Multi-Platform CLICommand-Line Interface
Scope
Tests covering HermesCLI class, slash command registry and dispatch, skin/theme system, banner rendering, autocomplete, and CLICommand-Line Interface configuration.
Test Files
- tests/hermes_cli/ — 300+ test files covering all CLICommand-Line Interface subsystems
- tests/hermes_cli/test_commands.py — Slash command dispatch tests
- tests/hermes_cli/test_skin_engine.py — Skin/theme engine tests
- tests/hermes_cli/test_banner.py — Banner rendering tests
- tests/hermes_cli/test_completion.py — Autocomplete tests
- tests/hermes_cli/test_cli_output.py — CLICommand-Line Interface output formatting tests
- tests/hermes_cli/test_hooks_cli.py — CLICommand-Line Interface hook tests
- tests/hermes_cli/test_tools_config.py — Tool configuration tests
Unit Tests
- CommandDef registry and resolution
- Skin config loading and merging
- Banner rendering with skin colors
- Path completion logic
- Slash command argument parsing
Integration Tests
- Full CLICommand-Line Interface startup and command dispatch
- Skin switching via /skin command
- Configuration loading from config.yaml
- GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core command compatibility
End-to-End Tests
- test_cli_skin_integration.py — Skin engine integration
- test_cli_file_drop.py — File drop handling
Edge Cases and Failure Scenarios
| Scenario | Expected Behavior |
|---|---|
| Unknown slash command | Help message with available commands |
| Invalid skin name | Fall back to default skin |
| Config file missing | Use DEFAULT_CONFIG defaults |
| Terminal not supporting Rich features | Graceful degradation to plain text |
Test Infrastructure
- pytest with temp HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware)
- Mock stdin/stdout for CLICommand-Line Interface interaction testing
- Subprocess-per-test-file isolation
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe CLICommand-Line Interface shall support slash commands for session management (/new, /undo, /branch, /compress, /snapshot) (session commands) | test_commands.py |
| FR-2MustThe CLICommand-Line Interface shall support configuration commands (/model, /skin, /reasoning, /voice, /fast, /yolo) (configuration commands) | test_commands.py, test_config.py |
| FR-3MustThe CLICommand-Line Interface shall support tools and skills management commands (/tools, /skills, /cron, /learn, /plugins, /kanban, /curator, /blueprint) (tools/skills commands) | test_commands.py, test_tools_config.py |
| FR-4MustThe CLICommand-Line Interface shall support info commands (/help, /usage, /insights, /debug, /version) (info commands) | test_commands.py, test_debug.py |
| FR-5MustThe CLICommand-Line Interface shall support a skin/theme system with built-in skins and user-customizable YAML skins (skin/theme system) | test_skin_engine.py |
| FR-6MustThe CLICommand-Line Interface shall provide Rich-styled banners and a kawaii animated spinner during API calls (Rich banners and spinner) | test_banner.py, test_cli_output.py |
| FR-7MustThe CLICommand-Line Interface shall support prompt_toolkit input with slash-command autocomplete (prompt_toolkit autocomplete) | test_completion.py |
| NFR-1MustSlash command dispatch shall complete in under 100ms (100ms dispatch) | Implicit in command dispatch tests |
requirements
- Should the classic prompt_toolkit CLI eventually be deprecated in favor of the TUI?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Messaging GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core
Overview
The messaging gateway (gateway/run.py) is an asyncio-based service that runs the agent core across ~25 messaging platforms. Each platform has its own adapter (Telegram, Discord, Slack, Signal, WhatsApp, email, SMS, Matrix, Mattermost, WeChat, DingTalk, Feishu, QQ, IRC, Google Chat, Line, Teams, Simplex, and more) with consistent session lifecycle, slash command dispatch, approval flow, and restart/scale-to-zero support.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Messaging users | Interact with the agent from their preferred chat platform |
| Operators | Run the gateway as a persistent daemon; configure which platforms are active |
| Adapter developers | Easy-to-add platform adapters via a base class and minimal boilerplate |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe gateway shall support running the agent core across multiple messaging platforms simultaneously | Must | The gateway shall support running the agent core across multiple messaging platforms simultaneously |
| FR-2MustEach platform adapter shall handle platform-specific authentication, rate limiting, and message formatting | Must | Each platform adapter shall handle platform-specific authentication, rate limiting, and message formatting |
| FR-3MustThe gateway shall support slash commands (/stop, /new, /queue, /status, /approve, /deny) that bypass the running agent | Must | The gateway shall support slash commands (/stop, /new, /queue, /status, /approve, /deny) that bypass the running agent |
| FR-4MustThe gateway shall support approval flow for potentially destructive agent actions | Must | The gateway shall support approval flow for potentially destructive agent actions |
| FR-5MustThe gateway shall support session management per platform (create, resume, list sessions) | Must | The gateway shall support session management per platform (create, resume, list sessions) |
| FR-6ShouldThe gateway shall support stream dispatch for real-time message delivery | Should | The gateway shall support stream dispatch for real-time message delivery |
| FR-7ShouldThe gateway shall support auto-restart and scale-to-zero for serverless operation | Should | The gateway shall support auto-restart and scale-to-zero for serverless operation |
| FR-8ShouldThe gateway shall support message mirroring across platforms | Should | The gateway shall support message mirroring across platforms |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustThe gateway shall handle messages from multiple platforms concurrently | Must | Concurrency | The gateway shall handle messages from multiple platforms concurrently |
| NFR-2MustEach platform's session shall be isolated and not interfere with others | Must | Isolation | Each platform's session shall be isolated and not interfere with others |
| NFR-3ShouldThe gateway should recover from platform adapter crashes without affecting other platforms | Should | Availability | The gateway should recover from platform adapter crashes without affecting other platforms |
Constraints
- Token locks prevent two agent profiles from using the same credential
- GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core config is read from config.yaml (terminal.cwd for working directory, gateway settings)
Acceptance Criteria
- FR-1MustThe gateway shall support running the agent core across multiple messaging platforms simultaneously
- Given the gateway is running with Telegram and Discord adapters enabled
- When a user sends a message to the Telegram bot and another user sends a message to the Discord bot
- Then both messages are processed independently
- FR-2MustEach platform adapter shall handle platform-specific authentication, rate limiting, and message formatting
- Given a Telegram adapter is configured with a bot token
- When the gateway starts
- Then the Telegram bot connects and shows as online
- FR-3MustThe gateway shall support slash commands (/stop, /new, /queue, /status, /approve, /deny) that bypass the running agent
- Given the agent is processing a request
- When the user sends /stop
- Then the agent loop is interrupted and the user receives confirmation
Conflicts
None identified yet.
Open Questions
- Should there be a standard adapter template/scaffolding tool to reduce boilerplate for new platforms?
Specification: Messaging GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core
Overview
The gateway is an asyncio-based Python service that loads platform adapters, manages their lifecycle, and routes messages to and from the synchronous AIAgent. The architecture uses a base adapter class that each platform extends, with common functionality (session management, slash command dispatch, approval flow) in the gateway runner.
Architecture
GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core runner (gateway/run.py)
│
├── PlatformManager (start/stop/lifecycle)
├── SessionManager (session create/switch/list/resume)
├── SlashDispatcher (commands bypassing agent)
├── ApprovalFlow (prompt/inline + approve/deny)
└── StreamDispatcher (real-time streaming)
│
├── TelegramAdapter
├── DiscordAdapter
├── SlackAdapter
├── WhatsAppAdapter
├── SignalAdapter
├── ... (20+ adapters)
└── API Server Adapter
Data Models
No custom data models beyond standard messaging types (message ID, chat ID, user ID, text content). Sessions are tracked via session_key derived from platform + chat/user ID.
API Contracts
The gateway does not expose external HTTP APIs (except the API server adapter, which provides an OpenAI-compatible HTTP endpoint). Communication between adapters and the gateway runner is in-process method calls.
Sequences
Message processing flow
Platform → Adapter receives message
│
├── pre-processing (rate limiting, identity check)
│
├── known command? ──→ SlashDispatcher ──→ handler
│
└── agent message ──→ SessionManager
│
└── AIAgent.run_conversation()
│
└── Response → Adapter → Platform message
Approval flow
AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory → Dangerous action detected
→ ApprovalFlow → Adapter → User (inline buttons)
→ User approves/denies
→ ApprovalFlow → AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory (approve) or abort (deny)
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Framework | asyncio | Allows concurrent handling of multiple platforms while maintaining sequential processing per session |
| Base adapter | ABCAbstract Base Class in gateway/platforms/base.py | Shared session/approval/command logic; minimal per-adapter code |
| Platform lifecycle | Explicit start/stop/disconnect | Token locks prevent credential reuse across profiles |
| Rate limiting | Per-platform config | Each platform has different API limits and we respect them individually |
Risks and Unknowns
- Adapter count is ~25 and growing — maintenance burden increases with each new platform
- SessionA single conversation history stored in SQLite with FTS5 search lifecycle across restarts and scale-to-zero transitions can lose in-flight messages
- Approval flow requires tight coupling between the platform adapter and the gateway runner's interruption mechanism
Out of Scope
- Webhook adapter (for incoming webhooks from external services) is a separate tool
- The gateway does not provide a web UI for configuration
Test Plan: Messaging GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core
Scope
Tests covering gateway runner, platform adapters, session management, slash command dispatch, approval flow, rate limiting, and platform-specific functionality.
Test Files
- tests/gateway/ — 80+ test files covering all gateway subsystems
- tests/hermes_cli/test_gateway*.py — GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core CLICommand-Line Interface integration tests
- tests/plugins/platforms/ — Platform adapter-specific tests
- tests/hermes_cli/test_webhook_cli.py — Webhook adapter tests
- tests/hermes_cli/test_whatsapp_*.py — WhatsApp adapter tests
- tests/hermes_cli/test_dingtalk_auth.py — DingTalk auth tests
- tests/hermes_cli/test_slack_cli.py — Slack CLICommand-Line Interface tests
Unit Tests
- SessionA single conversation history stored in SQLite with FTS5 search management (create, resume, list, delete)
- Slash command dispatch resolution
- Approval flow state machine
- Token lock acquisition/release
- Rate limiting logic
Integration Tests
- Adapter connection lifecycle (connect/reconnect/disconnect)
- Message processing pipeline
- Approval prompt delivery and response
- SessionA single conversation history stored in SQLite with FTS5 search isolation across platforms
- GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core restart and recovery
End-to-End Tests
- test_approve_deny_commands.py — Approval command flow
- test_api_server.py — API server adapter
- test_background_command.py — Background command processing
- test_gateway_restart_loop.py — GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core restart resilience
- Platform-specific adapter tests
Edge Cases and Failure Scenarios
| Scenario | Expected Behavior |
|---|---|
| Platform adapter crashes | Other adapters continue unaffected |
| Rate limit exceeded | Queue messages with backoff |
| Duplicate message delivery | Deduplication before processing |
| Token lock conflict (two profiles) | Latter connection refused |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core restart mid-session | SessionA single conversation history stored in SQLite with FTS5 search state recovered or gracefully reset |
| Scale-to-zero wake | GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core resumes with session cleanup |
Test Infrastructure
- Mock platform adapters for deterministic testing
- Async test fixtures with event loop isolation
- Temp HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) per test
- In-memory session store for fast test execution
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe gateway shall support running the agent core across multiple messaging platforms simultaneously (multi-platform support) | Adapter lifecycle tests |
| FR-2MustEach platform adapter shall handle platform-specific authentication, rate limiting, and message formatting (platform auth, rate limiting) | Platform-specific auth tests |
| FR-3MustThe gateway shall support slash commands (/stop, /new, /queue, /status, /approve, /deny) that bypass the running agent (slash commands bypassing agent) | test_approve_deny_commands.py |
| FR-4MustThe gateway shall support approval flow for potentially destructive agent actions (approval flow) | test_approval_prompt_redaction.py |
| FR-5MustThe gateway shall support session management per platform (create, resume, list sessions) (session management) | test_async_session_db.py |
| NFR-1MustThe gateway shall handle messages from multiple platforms concurrently (concurrent messages) | Concurrent session tests |
| NFR-2MustEach platform's session shall be isolated and not interfere with others (platform isolation) | SessionA single conversation history stored in SQLite with FTS5 search isolation tests |
requirements
- Should there be a standard adapter template/scaffolding tool to reduce boilerplate for new platforms?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Terminal and Browser Automation
Overview
Hermes provides real terminal access through six backends (local, Docker, SSH, Modal, Daytona, Singularity) and full browser automation through Playwright-based CDPChrome DevTools Protocol control. These are the agent's primary environment interaction tools, enabling it to execute commands, run code, navigate websites, and interact with web applications.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Power users | Want the agent to perform real work on their system (install packages, run scripts, edit files) |
| Browser users | Want the agent to navigate websites, fill forms, and extract information |
| Developers | Need configurable remote execution environments (Docker, SSH, cloud) |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe agent shall execute shell commands in the user's terminal via local backend | Must | The agent shall execute shell commands in the user's terminal via local backend |
| FR-2MustThe agent shall support Docker, SSH, Modal, Daytona, and Singularity as alternative terminal backends | Must | The agent shall support Docker, SSH, Modal, Daytona, and Singularity as alternative terminal backends |
| FR-3MustThe agent shall support background terminal processes with completion notification | Must | The agent shall support background terminal processes with completion notification |
| FR-4MustThe agent shall navigate web pages, click elements, type text, scroll, and extract content via browser | Must | The agent shall navigate web pages, click elements, type text, scroll, and extract content via browser |
| FR-5MustThe agent shall take screenshots/snapshots of browser pages | Must | The agent shall take screenshots/snapshots of browser pages |
| FR-6MustThe agent shall support browser dialog handling (alert, confirm, prompt) | Must | The agent shall support browser dialog handling (alert, confirm, prompt) |
| FR-7ShouldThe agent shall support Chrome DevTools Protocol (CDPChrome DevTools Protocol) for advanced browser features | Should | The agent shall support Chrome DevTools Protocol (CDPChrome DevTools Protocol) for advanced browser features |
| FR-8ShouldThe agent shall support hold-click and alternative click methods for complex web apps | Should | The agent shall support hold-click and alternative click methods for complex web apps |
| FR-9ShouldThe agent shall support file sync between the host and remote backends | Should | The agent shall support file sync between the host and remote backends |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustTerminal commands must pass through security checks (dangerous command detection, path validation) | Must | Security | Terminal commands must pass through security checks (dangerous command detection, path validation) |
| NFR-2MustBrowser automation must connect to a sandboxed/containerized Chromium instance | Must | Security | Browser automation must connect to a sandboxed/containerized Chromium instance |
| NFR-3ShouldTerminal operations should timeout gracefully with configurable per-command timeouts | Should | Performance | Terminal operations should timeout gracefully with configurable per-command timeouts |
Constraints
- Browser automation requires Playwright and a Chromium binary
- Remote backends (SSH, Docker, Modal, Daytona, Singularity) require external credentials or infrastructure
- Background processes with notification require a watcher in the gateway
Acceptance Criteria
- FR-1MustThe agent shall execute shell commands in the user's terminal via local backend
- Given the agent is running
- When the user asks the agent to run ls
- Then the agent executes ls in the local terminal and returns the output
- FR-4MustThe agent shall navigate web pages, click elements, type text, scroll, and extract content via browser
- Given the agent is running with browser access
- When the user asks the agent to navigate to example.com
- Then the agent opens the browser, loads the page, and returns a snapshot
- FR-3MustThe agent shall support background terminal processes with completion notification
- Given the agent is running with background terminal support
- When the user asks the agent to run a long process in the background
- Then the process starts running and the agent is notified when it completes
Conflicts
None identified yet.
Open Questions
- Should we support headless-only browser mode? Currently requires a display/X environment for full mode.
Specification: Terminal and Browser Automation
Overview
Terminal execution uses a backend abstraction: each environment (local, Docker, SSH, Modal, Daytona, Singularity) implements the same interface for executing commands and transferring files. The browser tool uses Playwright to control a Chromium instance via CDPChrome DevTools Protocol.
Architecture
Terminal
Terminal Tool (tools/terminal_tool.py)
│
├── Environment ABCAbstract Base Class (tools/environments/)
│ ├── LocalEnvironment
│ ├── DockerEnvironment
│ ├── SSHEnvironment
│ ├── ModalEnvironment
│ ├── DaytonaEnvironment
│ └── SingularityEnvironment
│
├── Security layer (tools/path_security.py, threat patterns)
└── Background process watcher (notify_on_complete)
Browser
Browser Tool (tools/browser_tool.py)
│
├── Playwright controller
├── CDPChrome DevTools Protocol agent (tools/browser_cdp_tool.py)
├── Dialog handler (tools/browser_dialog_tool.py)
└── Supervisor (tools/browser_supervisor.py)
Data Models
No custom data models. Terminal returns stdout/stderr strings. Browser returns page snapshots (screenshot + DOM state).
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Environment abstraction | ABCAbstract Base Class with register_backend pattern | New backends can be added without modifying the terminal tool |
| Browser engine | Playwright | Cross-browser, reliable, well-maintained, supports CDPChrome DevTools Protocol |
| Browser connection | Live Chromium via CDPChrome DevTools Protocol | Full browser environment with DevTools access |
| Background processes | Subprocess with watcher thread | Simple, reliable, platform-independent |
| Security | Multi-layer gating | Command allow/block lists, path validation, threat pattern detection, YOLO mode bypass |
Sequences
Command execution
AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory → terminal_tool(command) → environment.execute(cmd, timeout)
→ security check
→ spawn process
→ stream output
→ return output
Browser navigation
AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory → browser_navigate(url)
→ Playwright navigation
→ snapshot (screenshot + DOM state)
→ return result with snapshot
Risks and Unknowns
- Remote backends (Modal, Daytona) introduce network dependency and latency
- Browser automation is fragile — page layout changes, dynamic content, and anti-bot measures can break selectors
- Background process watcher only works in gateway mode (needs asyncio event loop)
Out of Scope
- Remote desktop/VNC access
- Mobile browser automation
Test Plan: Terminal and Browser Automation
Scope
Tests covering terminal execution across six backends, browser automation via Playwright/CDPChrome DevTools Protocol, file operations, security gating, background processes, and remote environment management.
Test Files
- tests/tools/test_terminal_tool.py — Terminal tool execution
- tests/tools/test_terminal_*.py — Terminal behavior (timeout, cwd, encoding)
- tests/tools/test_browser_*.py — Browser automation (30+ test files)
- tests/tools/test_file_*.py — File operations (read, write, patch, search)
- tests/tools/test_docker_*.py — Docker environment
- tests/tools/test_ssh_environment.py — SSH environment
- tests/tools/test_local_*.py — Local environment
- tests/tools/test_threat_patterns.py — Security threat detection
- tests/tools/test_approval*.py — Command approval gating
- tests/tools/test_notify_on_complete.py — Background completion notification
- tests/tools/test_file_sync*.py — File sync with remote backends
Unit Tests
- Environment abstraction ABCAbstract Base Class contract
- Security check (allow/block lists, threat patterns)
- Browser navigation, click, extract, screenshot
- File read/write/patch operations
- Path resolution and traversal guards
Integration Tests
- Full command execution pipeline through each backend
- Browser page interaction sequences
- Background process with completion notification
- File sync between host and remote backends
- Docker container lifecycle
Edge Cases and Failure Scenarios
| Scenario | Expected Behavior |
|---|---|
| Command timeout | Graceful timeout with partial output |
| Remote backend unreachable | Configurable retry or fallback |
| Browser dialog (alert/confirm) | Handled via dialog handler |
| Dangerous command detected | Blocked by security layer or approval prompt |
| File write to restricted path | Rejected with clear error |
| Background process in non-gateway mode | Watcher unavailable, process still runs |
| Browser anti-bot detection | CDPChrome DevTools Protocol bypass or fallback strategy |
Test Infrastructure
- Mock environments for deterministic testing
- Headless Chromium for browser tests (when available)
- Temp directories for file operation tests
- Process isolation for terminal tests
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe agent shall execute shell commands in the user's terminal via local backend (local terminal) | test_terminal_tool.py |
| FR-2MustThe agent shall support Docker, SSH, Modal, Daytona, and Singularity as alternative terminal backends (remote backends) | test_docker_*, test_ssh_environment.py |
| FR-3MustThe agent shall support background terminal processes with completion notification (background processes) | test_notify_on_complete.py |
| FR-4MustThe agent shall navigate web pages, click elements, type text, scroll, and extract content via browser (browser navigation) | test_browser_supervisor.py |
| FR-5MustThe agent shall take screenshots/snapshots of browser pages (browser screenshots) | test_browser_supervisor.py |
| FR-6MustThe agent shall support browser dialog handling (alert, confirm, prompt) (browser dialogs) | test_browser_camofox*.py |
| NFR-1MustTerminal commands must pass through security checks (dangerous command detection, path validation) (security checks) | test_threat_patterns.py, test_approval*.py |
requirements
- Should we support headless-only browser mode? Currently requires a display/X environment for full mode.
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles System
Overview
Hermes has two plugin surfaces: general plugins (hooks, tools, CLICommand-Line Interface subcommands via PluginManager) and provider plugins (model providers, memory providers, context engines, image gen, TTSText-to-Speech, transcription, web search, video gen). Plugins can ship in-tree under plugins/ or out-of-tree in ~/.hermes/plugins/ and pip entry points. The plugin system is the primary way to extend Hermes without modifying core files.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Third-party developers | Want to extend Hermes with custom tools, backends, or hooks without modifying core code |
| Power users | Want to install community plugins for additional capabilities |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustPlugins shall be discoverable from ~/.hermes/plugins/, ./.hermes/plugins/, and pip entry points | Must | Plugins shall be discoverable from ~/.hermes/plugins/, ./.hermes/plugins/, and pip entry points |
| FR-2MustPlugins shall support lifecycle hooks: pre_tool_call, post_tool_call, pre_llm_call, post_llm_call, on_session_start, on_session_end | Must | Plugins shall support lifecycle hooks: pre_tool_call, post_tool_call, pre_llm_call, post_llm_call, on_session_start, on_session_end |
| FR-3MustPlugins shall be able to register new tools via ctx.register_tool() | Must | Plugins shall be able to register new tools via ctx.register_tool() |
| FR-4MustPlugins shall be able to register CLICommand-Line Interface subcommands via ctx.register_cli_command() | Must | Plugins shall be able to register CLICommand-Line Interface subcommands via ctx.register_cli_command() |
| FR-5MustModel provider plugins shall use a separate lazy discovery system | Must | Model provider plugins shall use a separate lazy discovery system |
| FR-6MustMemory provider plugins shall implement the MemoryProvider ABCAbstract Base Class | Must | Memory provider plugins shall implement the MemoryProvider ABCAbstract Base Class |
| FR-7ShouldPluginManager should support enabling/disabling plugins | Should | PluginManager should support enabling/disabling plugins |
| FR-8ShouldPluginManager should support plugin dependency resolution | Should | PluginManager should support plugin dependency resolution |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustPlugins must not modify core files (run_agent.py, cli.py, gateway/run.py, etc.) | Must | Isolation | Plugins must not modify core files (run_agent.py, cli.py, gateway/run.py, etc.) |
| NFR-2MustA failing plugin hook must not crash the agent | Must | Safety | A failing plugin hook must not crash the agent |
| NFR-3ShouldPluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles discovery should complete in under 1 second | Should | Performance | PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles discovery should complete in under 1 second |
Constraints
- Plugins register with a
register(ctx)function called at discovery time - Model provider plugins must NOT be imported by the general PluginManager (would double-instantiate ProviderProfile)
- New in-tree memory providers and third-party product plugins are not accepted (policy)
Acceptance Criteria
- FR-1MustPlugins shall be discoverable from ~/.hermes/plugins/, ./.hermes/plugins/, and pip entry points
- Given a plugin installed in ~/.hermes/plugins/myplugin/
- When the agent starts
- Then the plugin is discovered and its register() function is called
- FR-2MustPlugins shall support lifecycle hooks: pre_tool_call, post_tool_call, pre_llm_call, post_llm_call, on_session_start, on_session_end
- Given a plugin that registers a pre_tool_call hook
- When any tool is about to be called
- Then the hook is invoked before the tool handler
- FR-3MustPlugins shall be able to register new tools via ctx.register_tool()
- Given a plugin that registers a new tool
- When agent's tool schemas are collected
- Then the plugin's tool schema appears in the tool definitions
- NFR-1MustPlugins must not modify core files (run_agent.py, cli.py, gateway/run.py, etc.)
- Given a plugin that attempts to modify cli.py
- When the plugin is loaded
- Then it must use ctx methods instead, and core files remain unchanged
Conflicts
None identified yet.
Open Questions
- Should there be a plugin marketplace or catalog beyond the current discovery paths?
Specification: PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles System
Overview
The PluginManager discovers plugins from multiple sources and provides a context (ctx) object through which plugins register hooks, tools, and CLICommand-Line Interface commands. A separate lazy discovery system handles model provider plugins, memory provider plugins, and other provider-type plugins.
Architecture
PluginManager (hermes_cli/plugins.py)
│
├── Discovery sources:
│ ├── ~/.hermes/plugins/<name>/
│ ├── ./.hermes/plugins/<name>/
│ ├── pip entry points (hermes_plugins)
│ └── Plugins/<name>/ (in-tree)
│
└── Each plugin provides register(ctx):
├── ctx.register_tool(name, schema, handler, ...)
├── ctx.register_cli_command(subparser)
├── ctx.register_hook(event, callback)
└── ctx.register_provider(profile) (for model providers)
Provider registries (separate lazy discovery):
├── Model providers (plugins/model-providers/<name>/)
│ └── providers.register_provider(ProviderProfile(...))
├── Memory providers (plugins/memory/<name>/)
│ └── MemoryProvider ABCAbstract Base Class implementation
├── Context engines (plugins/context_engine/<name>/)
├── Image gen providers (plugins/image_gen/<name>/)
├── TTSText-to-Speech providers
├── Transcription providers
└── Web search providers
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Discovery timing | Lazy for providers, eager for general plugins | Provider registries are only scanned on first get/list, avoiding imports for unconfigured providers |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles isolation | No core file modification | Prevents conflicts and simplifies upgrades |
| Hook calling | Sequential, wrapped in try/except | A single failing hook should not block subsequent hooks or crash the agent |
| Model providers | Last-writer-wins | User plugins of the same name override bundled ones without patching the repo |
Risks and Unknowns
- General PluginManager and model-provider discovery systems are separate — plugins marked as kind: model-provider are discovered but not imported by PluginManager, which could lead to registration gaps
- No versioning or compatibility checks for plugins (a plugin written for an older Hermes version may fail silently)
- No plugin sandboxing outside of hook try/except wrapping
Out of Scope
- PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles marketplace/server
- PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles version resolution and dependency management
- Sandboxed plugin execution
Test Plan: PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles System
Scope
Tests covering PluginManager discovery, plugin lifecycle hooks, tool registration, CLICommand-Line Interface subcommand registration, model provider lazy discovery, and memory provider ABCAbstract Base Class conformance.
Test Files
- tests/hermes_cli/test_plugins.py — PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles discovery and registration
- tests/hermes_cli/test_plugins_cmd*.py — PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles CLICommand-Line Interface commands
- tests/hermes_cli/test_plugin_scanner_recursion.py — PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles scanner depth
- tests/hermes_cli/test_plugin_runtime_disable_gate.py — Runtime disable gating
- tests/hermes_cli/test_plugin_auxiliary_tasks.py — Auxiliary plugin tasks
- tests/hermes_cli/test_plugin_cli_registration.py — CLICommand-Line Interface subcommand registration
- tests/plugins/ — 15+ plugin-specific test directories
- tests/tools/test_mcp_*.py — MCPModel Context Protocol plugin integration tests (30+ files)
- tests/hermes_cli/test_memory_providers.py — Memory provider registration
- tests/hermes_cli/test_startup_plugin_gating.py — PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles gating at startup
Unit Tests
- PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles discovery from filesystem and entry points
- Hook registration and invocation order
- Tool schema collection from registered plugins
- CLICommand-Line Interface subcommand tree wiring
- Provider profile registration (last-writer-wins)
Integration Tests
- Full plugin lifecycle: discover → register → hook → tool call
- Model provider lazy discovery via providers.register_provider()
- Memory provider ABCAbstract Base Class conformance testing
- PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles hook failure isolation (try/except wrapping)
- PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles CLICommand-Line Interface subcommand discovery and dispatch
Edge Cases and Failure Scenarios
| Scenario | Expected Behavior |
|---|---|
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles with missing register() | Skipped with warning |
| Hook callback crashes | Error logged, other hooks and agent continue |
| Duplicate plugin name | Last-writer-wins merge |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles modifies core file | No mechanism to prevent (policy relies on convention) |
| Circular plugin dependency | Unresolved (no dependency manager yet) |
Test Infrastructure
- Temp plugin directories for discovery testing
- Mock plugin packages with controlled hooks
- Isolated import scope per test
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustPlugins shall be discoverable from ~/.hermes/plugins/, ./.hermes/plugins/, and pip entry points (discovery from sources) | test_plugins.py |
| FR-2MustPlugins shall support lifecycle hooks: pre_tool_call, post_tool_call, pre_llm_call, post_llm_call, on_session_start, on_session_end (lifecycle hooks) | test_plugins.py hook tests |
| FR-3MustPlugins shall be able to register new tools via ctx.register_tool() (register_tool) | test_plugins.py tool registration tests |
| FR-4MustPlugins shall be able to register CLICommand-Line Interface subcommands via ctx.register_cli_command() (register_cli_command) | test_plugin_cli_registration.py |
| FR-5MustModel provider plugins shall use a separate lazy discovery system (lazy provider discovery) | Model provider tests |
| FR-6MustMemory provider plugins shall implement the MemoryProvider ABCAbstract Base Class (MemoryProvider ABCAbstract Base Class) | test_memory_providers.py |
| NFR-1MustPlugins must not modify core files (run_agent.py, cli.py, gateway/run.py, etc.) (no core file modification) | PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles policy enforcement tests |
requirements
- Should there be a plugin marketplace or catalog beyond the current discovery paths?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow System
Overview
Skills are markdown documents (SKILL.md) that guide the agent on how to perform specific tasks. Hermes ships ~18 categories of built-in skills and ~20 categories of optional skills (loaded only on demand). The agent can autonomously create and improve skills from its own experience via the learning graph and curator system. Skills provide specialized instructions and workflows that are injected into the system prompt per-session.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Users | Want the agent to be able to perform specialized tasks (GitHub workflows, DevOps, creative writing, etc.) |
| Agents (self) | The agent creates skills autonomously from its own experience and improves them over time |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow authors | Want to write and share skills that guide the agent through domain-specific tasks |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustBuilt-in skills shall be loadable by default and injected into the system prompt | Must | Built-in skills shall be loadable by default and injected into the system prompt |
| FR-2MustOptional skills shall be installable via hermes skills install command | Must | Optional skills shall be installable via hermes skills install command |
| FR-3MustThe agent shall be able to create skills from its own experience (learning graph) | Must | The agent shall be able to create skills from its own experience (learning graph) |
| FR-4MustThe curator shall track skill usage and auto-archive stale agent-created skills | Must | The curator shall track skill usage and auto-archive stale agent-created skills |
| FR-5MustThe agent shall have tools to list, view, create, edit, and delete skills | Must | The agent shall have tools to list, view, create, edit, and delete skills |
| FR-6ShouldSkills shall be organized by category in the file system | Should | Skills shall be organized by category in the file system |
| FR-7ShouldPinned skills shall be exempt from curator auto-archiving | Should | Pinned skills shall be exempt from curator auto-archiving |
| FR-8WeatherSkills should support a hub mechanism for community distribution | Weather | Skills should support a hub mechanism for community distribution |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustLoading many skills shall not significantly increase system prompt size (skills are stored as references, not inline content) | Must | Performance | Loading many skills shall not significantly increase system prompt size (skills are stored as references, not inline content) |
| NFR-2MustAgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory-created skills must be reviewed before activation (optional guard) | Must | Safety | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory-created skills must be reviewed before activation (optional guard) |
Constraints
- Skills must follow the SKILL.md format with standardized frontmatter (name, description, version, platforms, etc.)
- SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow descriptions are limited to 60 characters
- Curator only touches skills with created_by: agent provenance — bundled and hub-installed skills are off-limits
Acceptance Criteria
- FR-1MustBuilt-in skills shall be loadable by default and injected into the system prompt
- Given a built-in skill exists in skills/github/
- When the agent loads
- Then the skill is available and its instructions are injected into the system prompt
- FR-3MustThe agent shall be able to create skills from its own experience (learning graph)
- Given the agent has performed a multi-step task
- When the agent decides to create a skill from the procedure
- Then a new SKILL.md is created in the skills directory with the extracted steps
- FR-4MustThe curator shall track skill usage and auto-archive stale agent-created skills
- Given an agent-created skill has not been used for stale_after_days
- When the curator runs
- Then the skill is archived to ~/.hermes/skills/.archive/
Conflicts
None identified yet.
Open Questions
- How should skill versioning work for agent-created skills that get improved over time?
Specification: SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow System
Overview
Skills are loaded from two parallel surface directories: skills/ (built-in, loadable by default) and optional-skills/ (shipped but inactive, installed via hermes skills install). AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory-created skills live under ~/.hermes/skills/. The curator monitors usage and auto-archives stale skills.
Architecture
SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow loading:
├── skills/ (built-in, ~18 categories)
├── optional-skills/ (optional, ~20 categories)
├── ~/.hermes/skills/ (agent-created)
│ └── .archive/ (curator-archived)
└── Skills Hub (community distribution via tools/skills_hub.py)
Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills:
AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory creates skill → active → ...usage tracked...
└── stale? → curator archives (never deletes)
└── pinned? → curator exempt
SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow injection:
skill_commands.py scans skills/ → generates user message injected at session start
└── NOT system prompt (preserves prompt caching)
Data Models
SKILL.md Frontmatter
| Field | Type | Description |
|---|---|---|
| name | string | SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow name |
| description | string | ≤60 characters, one sentence, ends with period |
| version | string | Semantic version |
| author | string | Human contributor first |
| license | string | License identifier |
| platforms | list | OS-gating list (macos, linux, windows) |
| metadata.hermes.tags | list | Search tags |
| metadata.hermes.category | string | Category name |
| metadata.hermes.related_skills | list | Cross-references |
SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow Usage (sidecar JSON)
| Field | Type | Description |
|---|---|---|
| use_count | int | How many times the skill was invoked |
| view_count | int | How many times the skill was viewed |
| patch_count | int | How many times the skill was edited |
| last_activity_at | ISO date | Most recent activity |
| state | string | active / stale / archived |
| pinned | bool | Exempt from auto-transitions |
API Contracts
No API contracts. Skills interact with the agent through the system prompt injection mechanism and the skill_tool's skill_manager_tool() functions.
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Injection method | User message, not system prompt | Preserves prompt caching — system prompt is byte-stable per conversation |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow loading | Slash command scans skills/ at session start | Adds a user message with skill instructions, not a system prompt modification |
| Curator | Background process with LLM review | Automates skill lifecycle management without user intervention |
| Archives | Near for safe recovery | Never deletes skills — moves to .archive/ for restoration |
Risks and Unknowns
- Large numbers of loaded skills could dilute model attention
- AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory-created skills may have variable quality — the curator's LLM review pass attempts to address this
- SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow = user message pattern means skills are subject to the model's context window, not the system prompt cache
Out of Scope
- SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow marketplace or community hub (the Skills Hub is a basic distribution mechanism)
- Automated skill testing or validation
Test Plan: SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow System
Scope
Tests covering skill loading, SKILL.md parsing, skill tools (list, view, create, edit, delete), curator lifecycle, skills hub, and skill usage tracking.
Test Files
- tests/tools/test_skill_*.py — SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow tool operations (7+ test files)
- tests/tools/test_skills_tool.py — Core skill management tool
- tests/tools/test_skills_hub.py — Skills hub download/install
- tests/tools/test_skill_manager_tool.py — SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow manager tool
- tests/tools/test_skill_usage.py — SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow usage tracking
- tests/tools/test_skill_bundle_provenance.py — SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow provenance
- tests/hermes_cli/test_skills_*.py — SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow CLICommand-Line Interface commands
- tests/hermes_cli/test_curator_*.py — Curator lifecycle tests
- tests/hermes_cli/test_skills_hub.py — Hub CLICommand-Line Interface integration
- tests/tools/test_skills_ast_audit.py — SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow AST audit
- tests/skills/ — SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow-specific functional tests
Unit Tests
- SKILL.md frontmatter parsing
- SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow loading from filesystem paths
- SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow tool CRUD operations
- Curator state transitions (active → stale → archived)
- SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow usage tracking (increment, persist)
Integration Tests
- Full skill lifecycle: create → use → archive → restore
- Skills hub install from remote source
- SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow injection into agent context
- Curator run with LLM review pass
- SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow discovery and listing across directories
Edge Cases and Failure Scenarios
| Scenario | Expected Behavior |
|---|---|
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow with invalid frontmatter | Skipped with warning |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow exceeds description length limit | Truncation or rejection |
| Curator tries to archive pinned skill | Skipped (pinned exempt) |
| Skills hub URL unreachable | Graceful failure with cached fallback |
| Duplicate skill name across directories | Last-loaded wins with dedup |
Test Infrastructure
- Temp skill directories with controlled SKILL.md content
- Mock curator LLM review for deterministic testing
- Isolated HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) per test
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustBuilt-in skills shall be loadable by default and injected into the system prompt (built-in skill loading) | test_skills_tool.py, test_skills_config.py |
| FR-2MustOptional skills shall be installable via hermes skills install command (optional skill install) | test_skills_hub.py |
| FR-3MustThe agent shall be able to create skills from its own experience (learning graph) (agent skill creation) | test_skill_manager_tool.py |
| FR-4MustThe curator shall track skill usage and auto-archive stale agent-created skills (curator lifecycle) | test_curator_run.py, test_curator_archive_prune.py |
| FR-5MustThe agent shall have tools to list, view, create, edit, and delete skills (skill tools) | test_skills_tool.py, test_skill_* |
| NFR-1MustLoading many skills shall not significantly increase system prompt size (skills are stored as references, not inline content) (system prompt size) | SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow injection via user message, not system prompt |
requirements
- How should skill versioning work for agent-created skills that get improved over time?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Memory and Cross-SessionA single conversation history stored in SQLite with FTS5 search Knowledge
Overview
Hermes maintains persistent knowledge across sessions through two systems: pluggable memory providers (Honcho, Mem0, Supermemory, Byterover, Hindsight, Holographic, OpenViking, RetainDB) and the learning graph (for extracting and persisting skill-like procedures from user interactions). The session store (SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history) provides full-text search across past conversations.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Users | The agent remembers relevant context across sessions — preferences, ongoing projects, facts learned |
| Developers | Pluggable backends mean users can choose their preferred memory storage (local, cloud, 3rd-party) |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe system shall persist conversation history in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history full-text search | Must | The system shall persist conversation history in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history full-text search |
| FR-2MustThe system shall support pluggable memory providers via the MemoryProvider ABCAbstract Base Class | Must | The system shall support pluggable memory providers via the MemoryProvider ABCAbstract Base Class |
| FR-3MustMemory providers shall sync turn data via sync_turn(turn_messages) after each conversational turn | Must | Memory providers shall sync turn data via sync_turn(turn_messages) after each conversational turn |
| FR-4MustThe system shall support query-based memory prefetch (prefetch(query)) during session start | Must | The system shall support query-based memory prefetch (prefetch(query)) during session start |
| FR-5ShouldThe system shall support learning graph extraction — converting user interactions into reusable skills | Should | The system shall support learning graph extraction — converting user interactions into reusable skills |
| FR-6ShouldThe learning system shall extract procedures from conversations, directories, URLs, notes, and chat history | Should | The learning system shall extract procedures from conversations, directories, URLs, notes, and chat history |
| FR-7ShouldThe system shall support session search across all past conversations with summarization | Should | The system shall support session search across all past conversations with summarization |
| FR-8ShouldThe system shall automatically generate session titles via LLM | Should | The system shall automatically generate session titles via LLM |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustSessionA single conversation history stored in SQLite with FTS5 search search should return results in under 2 seconds | Must | Performance | SessionA single conversation history stored in SQLite with FTS5 search search should return results in under 2 seconds |
| NFR-2MustMemory provider choice should be user-configurable (local vs cloud) | Must | Privacy | Memory provider choice should be user-configurable (local vs cloud) |
Constraints
- No new in-tree memory providers (policy) — new providers must ship as standalone plugin repos
- Cron sessions pass skip_memory=True by default — memory providers intentionally do not run during cron
Acceptance Criteria
- FR-1MustThe system shall persist conversation history in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history full-text search
- Given a conversation has completed
- When the user sends a new message in a different session
- Then the agent can find the previous conversation via session search
- FR-2MustThe system shall support pluggable memory providers via the MemoryProvider ABCAbstract Base Class
- Given the user has configured a memory provider
- When a conversation turn completes
- Then sync_turn() is called with the turn messages
- FR-5ShouldThe system shall support learning graph extraction — converting user interactions into reusable skills
- Given the user has completed a multi-step operation
- When the learning graph processes the session
- Then a skill can be extracted and saved
Conflicts
None identified yet.
Open Questions
- Should there be a built-in (zero-dependency) memory provider option?
Specification: Memory and Cross-SessionA single conversation history stored in SQLite with FTS5 search Knowledge
Overview
Memory is orchestrated by agent/memory_manager.py, which manages a set of MemoryProvider implementations. The session store (hermes_state.py) provides local FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search. The learning graph (agent/learning_graph.py) provides skill extraction from user interactions.
Architecture
SessionA single conversation history stored in SQLite with FTS5 search Store (hermes_state.py)
└── SQLite DB with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history
└── SessionA single conversation history stored in SQLite with FTS5 search listing, filtering, export (HTML/MD)
└── Automatic title generation (LLM)
Memory Manager (agent/memory_manager.py)
└── MemoryProvider ABCAbstract Base Class (agent/memory_provider.py)
├── Honcho (plugins/memory/honcho/)
├── Mem0 (plugins/memory/mem0/)
├── Supermemory (plugins/memory/supermemory/)
├── Byterover (plugins/memory/byterover/)
├── Hindsight (plugins/memory/hindsight/)
├── Holographic (plugins/memory/holographic/)
├── OpenViking (plugins/memory/openviking/)
└── RetainDB (plugins/memory/retaindb/)
Learning Graph (agent/learning_graph.py)
└── Extracts procedures from user interactions
└── Sources: conversations, directories, URLs, notes, chat history
└── Output: SKILL.md files with extracted procedures
└── Timeline/journey view (agent/learning_graph_render.py)
Data Models
SessionA single conversation history stored in SQLite with FTS5 search record (SQLite)
| Field | Type | Description |
|---|---|---|
| session_id | TEXT | UUID |
| title | TEXT | Auto-generated by LLM |
| created_at | DATETIME | Creation time |
| updated_at | DATETIME | Last activity |
| message_count | INTEGER | Total messages in session |
MemoryProvider ABCAbstract Base Class
| Method | Return | Description |
|---|---|---|
| sync_turn(turn_messages) | None | Process a turn for storage |
| prefetch(query) | list | Retrieve relevant memories before session start |
| shutdown() | None | Cleanup on agent shutdown |
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Memory system | Optional pluggable providers | Users choose the storage backend that fits their privacy/scale needs |
| SessionA single conversation history stored in SQLite with FTS5 search search | SQLite FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Zero-dependency, fast, supports advanced queries |
| Learning graph | Custom extraction engine | More flexible than skill-based approaches; extracts procedures from any interaction |
| Title generation | LLM call post-turn | Lighter than requiring manual session naming |
Risks and Unknowns
- Memory providers that make network calls (Honcho, Mem0, Supermemory) introduce latency and reliability concerns
- Learning graph quality depends on the extraction prompts — may produce low-quality or duplicated skills
- SessionA single conversation history stored in SQLite with FTS5 search title generation is an extra LLM call per session — cost accumulates for frequent sessions
Out of Scope
- Memory provider plugin discovery from third-party repos (policy: out-of-tree)
- Automatic memory deduplication across providers
Test Plan: Memory and Cross-SessionA single conversation history stored in SQLite with FTS5 search Knowledge
Scope
Tests covering session store (SQLite FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history), memory provider integration, learning graph, session search, title generation, and cross-session recall.
Test Files
- tests/hermes_state/ — SessionA single conversation history stored in SQLite with FTS5 search store tests
- tests/tools/test_memory_tool.py — Memory tool operations
- tests/tools/test_memory_tool_schema.py — Memory tool schema
- tests/tools/test_session_search.py — SessionA single conversation history stored in SQLite with FTS5 search search
- tests/hermes_cli/test_memory_*.py — Memory provider setup and config
- tests/hermes_cli/test_session_*.py — SessionA single conversation history stored in SQLite with FTS5 search browsing, export, filters
- tests/hermes_cli/test_journey_render.py — Learning graph journey render
- tests/plugins/memory/ — Memory provider-specific tests (honcho, retaindb, hindsight)
- tests/agent/test_memory_provider_init.py — Memory provider initialization
- tests/agent/test_memory_sync_interrupted.py — Memory sync interruption
Unit Tests
- SessionA single conversation history stored in SQLite with FTS5 search CRUD (create, read, update, delete, list)
- FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history full-text search query parsing and execution
- MemoryProvider ABCAbstract Base Class method signatures
- Learning graph extraction logic
- Title generation prompt construction
Integration Tests
- Memory sync_turn() after each agent turn
- Prefetch() query during session start
- Cross-session search and recall
- Memory provider initialization from config
- SessionA single conversation history stored in SQLite with FTS5 search export in HTML and Markdown formats
Edge Cases and Failure Scenarios
| Scenario | Expected Behavior |
|---|---|
| Memory provider network call fails | Error logged, agent continues without memory |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search with special characters | Properly escaped query |
| Empty session (no messages) | Graceful handling, no sync |
| Learning graph extracts no procedures | No skill created, no error |
| SessionA single conversation history stored in SQLite with FTS5 search title generation fails | Placeholder title used |
| Memory provider init fails | Fall back to no-memory mode |
Test Infrastructure
- In-memory SQLite for fast session store tests
- Mock memory providers for ABCAbstract Base Class conformance
- Temp HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) with controlled session data
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe system shall persist conversation history in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history full-text search (SQLite FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history session store) | test_hermes_state.py, test_async_session_store.py |
| FR-2MustThe system shall support pluggable memory providers via the MemoryProvider ABCAbstract Base Class (pluggable memory providers) | test_memory_providers.py |
| FR-3MustMemory providers shall sync turn data via sync_turn(turn_messages) after each conversational turn (sync_turn) | test_memory_tool.py |
| FR-4MustThe system shall support query-based memory prefetch (prefetch(query)) during session start (prefetch) | test_memory_provider_init.py |
| FR-7ShouldThe system shall support session search across all past conversations with summarization (session search) | test_session_search.py, test_web_server_session_search.py |
| FR-8ShouldThe system shall automatically generate session titles via LLM (title generation) | Tested via session auto-title |
requirements
- Should there be a built-in (zero-dependency) memory provider option?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Cron Scheduling and Subagent Delegation
Overview
Hermes provides two systems for work that extends beyond a single conversation turn: a cron scheduler for recurring and one-shot jobs, and a subagent delegation system for spawning isolated child agents. The cron system supports multiple schedule formats, per-job skill/model overrides, chaining, and multi-platform delivery. Delegation supports both single-task and batch (parallel) execution with configurable concurrency.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Power users | Want scheduled reports, reminders, and automated workflows delivered to their messaging platform |
| Operators | Need parallel task execution to speed up complex operations |
| Developers | Want to integrate cron jobs into their workflows |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe cron system shall support duration-based schedules (30m, 2h, 1d) | Must | The cron system shall support duration-based schedules (30m, 2h, 1d) |
| FR-2MustThe cron system shall support cron expressions (0 9 * * *) | Must | The cron system shall support cron expressions (0 9 * * *) |
| FR-3MustThe cron system shall support every-phrase schedules (every 2h, every monday 9am) | Must | The cron system shall support every-phrase schedules (every 2h, every monday 9am) |
| FR-4MustThe cron system shall support ISO timestamp one-shot jobs | Must | The cron system shall support ISO timestamp one-shot jobs |
| FR-5MustThe cron system shall support per-job skill loading, model/provider overrides, and workdir | Must | The cron system shall support per-job skill loading, model/provider overrides, and workdir |
| FR-6MustThe cron system shall support multi-platform delivery of results | Must | The cron system shall support multi-platform delivery of results |
| FR-7MustThe delegation system shall support spawning subagents with isolated context and terminal | Must | The delegation system shall support spawning subagents with isolated context and terminal |
| FR-8MustThe delegation system shall support both blocking (wait for summary) and background (fire and forget) modes | Must | The delegation system shall support both blocking (wait for summary) and background (fire and forget) modes |
| FR-9MustThe delegation system shall support concurrent batch execution | Must | The delegation system shall support concurrent batch execution |
| FR-10ShouldThe delegation system shall support role levels (leaf and orchestrator) | Should | The delegation system shall support role levels (leaf and orchestrator) |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustCron jobs shall have a 3-minute hard interrupt to prevent runaway sessions | Must | Reliability | Cron jobs shall have a 3-minute hard interrupt to prevent runaway sessions |
| NFR-2MustFile lock prevents duplicate cron ticks across processes | Must | Safety | File lock prevents duplicate cron ticks across processes |
| NFR-3ShouldDelegation concurrency shall be capped (default 3) by max_concurrent_children | Should | Performance | Delegation concurrency shall be capped (default 3) by max_concurrent_children |
Acceptance Criteria
- FR-1MustThe cron system shall support duration-based schedules (30m, 2h, 1d)
- Given a cron job with schedule "30m"
- When 30 minutes pass
- Then the job fires and executes its prompt
- FR-7MustThe delegation system shall support spawning subagents with isolated context and terminal
- Given a user asks to delegate a task
- When the agent calls delegate_task
- Then a subagent is spawned with an isolated session and terminal
- FR-9MustThe delegation system shall support concurrent batch execution
- Given a batch of 5 tasks with max_concurrent_children=3
- When the agent calls delegate_task with tasks=[5 items]
- Then 3 tasks run concurrently, then the remaining 2
Conflicts
None identified yet.
Open Questions
- Should cron jobs support retry policies or only the current one-shot + scheduled patterns?
Specification: Cron Scheduling and Subagent Delegation
Overview
Cron uses a SQLite-backed job store (cron/jobs.py) and a tick loop scheduler (cron/scheduler.py). Delegation spawns child AIAgent instances with isolated context via tools/delegate_tool.py.
Architecture
Cron
Cron (cron/)
├── jobs.py — SQLite job store
├── scheduler.py — tick loop
├── lifecycle_guard.py — 3-minute hard interrupt
└── suggestions.py — automated schedule suggestions
Delegation
Delegation (tools/delegate_tool.py)
├── Single: task(goal, context, toolsets)
├── Batch: tasks([...]) — concurrent parallelism
├── Role: leaf (default, cannot delegate further)
└── Role: orchestrator (can spawn sub-workers)
Data Models
Cron Job
| Field | Type | Description |
|---|---|---|
| id | TEXT | UUID |
| schedule | TEXT | Duration, every-phrase, cron expression, or ISO timestamp |
| prompt | TEXT | Job prompt |
| skills | list | Skills to load during job execution |
| model | string | Override model |
| script | string | Pre-run data collection script |
| context_from | string | Chain from another job's output |
| workdir | string | Working directory with AGENTS.md |
| platform | string | Delivery platform |
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Cron storage | SQLite | Zero-dependency, simple, supports concurrent access |
| Tick loop | File lock | Prevents duplicate ticks across processes without a coordinator |
| Hard interrupt | 3-minute timeout | Prevents runaway agent loops from monopolizing the scheduler |
| Delegation | Subprocess with shared budget | Inherits parent's iteration budget, ensures total work is bounded |
| Multi-agent safety | Role: leaf | Leaf agents cannot spawn further agents, preventing cascading delegation |
| Async completion | Queue-based | Background tasks return their result to a queue that the parent checks later |
Risks and Unknowns
- Cron sessions skip memory (skip_memory=True) by default — long-running cron tasks lose context across job runs
- Delegation with background=true is process-local — does not survive process restart (unlike cron)
- The 3-minute hard interrupt may be too short for complex batch tasks
Out of Scope
- Distributed execution across machines
- Cron job dependency graph (only chaining is supported, not DAG)
Test Plan: Cron Scheduling and Subagent Delegation
Scope
Tests covering cron job store, scheduler tick loop, schedule parsing (duration, cron expression, every-phrase, ISO timestamp), per-job overrides, multi-platform delivery, delegation (single and batch), and subagent lifecycle.
Test Files
- tests/cron/ — 28+ test files covering all cron subsystems
- tests/cron/test_jobs.py — Job store CRUD operations
- tests/cron/test_scheduler.py — Scheduler tick loop
- tests/cron/test_compute_next_run_last_run_at.py — Schedule computation
- tests/cron/test_cron_script.py — Pre-run data collection scripts
- tests/cron/test_cron_workdir.py — Per-job working directory
- tests/cron/test_cron_prompt_injection_skill.py — SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow loading per job
- tests/cron/test_cron_context_from.py — Job chaining
- tests/cron/test_cron_provider_pin.py — Provider overrides
- tests/tools/test_delegate.py — Subagent delegation
- tests/tools/test_delegate_*.py — Delegation edge cases
- tests/tools/test_cronjob_tools.py — Cronjob tool schema
- tests/tools/test_cronjob_run_immediate.py — Immediate job execution
- tests/hermes_cli/test_cron*.py — Cron CLICommand-Line Interface commands
Unit Tests
- Schedule format parsing (duration, cron, every-phrase, ISO)
- Job CRUD (create, edit, list, pause, resume, remove)
- Tick loop state machine
- Delegate task argument validation
- Subagent role enforcement (leaf vs orchestrator)
Integration Tests
- Full job lifecycle: create → schedule → fire → deliver
- Batch delegation with max_concurrent_children enforcement
- Background task completion notification
- File lock prevention of duplicate ticks
- 3-minute hard interrupt on runaway jobs
- SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow loading during cron execution
Edge Cases and Failure Scenarios
| Scenario | Expected Behavior |
|---|---|
| Job fire time missed (catchup) | Catchup window clamped to 120s–2h |
| Runaway agent loop in cron | 3-minute hard interrupt |
| Duplicate tick across processes | File lock prevents duplicate |
| Delegate batch with failed subtasks | Other subtasks continue |
| Background delegation after restart | Lost (process-local, use cron instead) |
| Job with no_agent=True script failure | Script error reported, no agent invocation |
Test Infrastructure
- In-memory job store for deterministic testing
- Mock scheduler tick for precise timing tests
- Temp filesystem for workdir tests
- Subprocess delegation testing
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe cron system shall support duration-based schedules (30m, 2h, 1d) (duration schedules) | test_compute_next_run_last_run_at.py |
| FR-2MustThe cron system shall support cron expressions (0 9 * * *) (cron expressions) | test_compute_next_run_last_run_at.py |
| FR-3MustThe cron system shall support every-phrase schedules (every 2h, every monday 9am) (every-phrase schedules) | test_compute_next_run_last_run_at.py |
| FR-4MustThe cron system shall support ISO timestamp one-shot jobs (ISO timestamps) | test_compute_next_run_last_run_at.py |
| FR-5MustThe cron system shall support per-job skill loading, model/provider overrides, and workdir (per-job overrides) | test_cron_script.py, test_cron_workdir.py |
| FR-6MustThe cron system shall support multi-platform delivery of results (multi-platform delivery) | Cron delivery tests |
| FR-7MustThe delegation system shall support spawning subagents with isolated context and terminal (subagent delegation) | test_delegate.py |
| FR-8MustThe delegation system shall support both blocking (wait for summary) and background (fire and forget) modes (blocking + background) | test_delegate.py |
| FR-9MustThe delegation system shall support concurrent batch execution (concurrent batch) | test_delegate.py |
| NFR-1MustCron jobs shall have a 3-minute hard interrupt to prevent runaway sessions (3-minute hard interrupt) | test_scheduler.py |
requirements
- Should cron jobs support retry policies or only the current one-shot + scheduled patterns?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |
Pipeline Progress ?⚪ not started not yet begun✏️ draft initial version🔍 in review under review🚧 in progress actively worked on⛔ blocked waiting on dependency✅ done completed⏭️ skipped not applicable
Requirements: Multi-Surface TUITerminal User Interface and Desktop
Overview
Hermes provides three additional user surfaces beyond the classic CLICommand-Line Interface: a Terminal UI (TUITerminal User Interface) built with InkA React renderer for terminals, used for the TUI/React and a Python JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend backend, an Electron desktop application with its own React frontend, and a web dashboard that embeds the real TUITerminal User Interface via xterm.js PTYPseudo-terminal bridge. These surfaces share the same agent core and gateway backend.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Terminal users | Want a richer terminal experience than the classic CLICommand-Line Interface with session picker and streaming output |
| Desktop users | Want a standalone app with proper window management, notifications, and native feel |
| Dashboard users | Want browser-based access to the agent via web UI |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-1MustThe TUITerminal User Interface shall provide chat streaming with real-time tool activity display | Must | The TUITerminal User Interface shall provide chat streaming with real-time tool activity display |
| FR-2MustThe TUITerminal User Interface shall provide a session picker for switching between conversations | Must | The TUITerminal User Interface shall provide a session picker for switching between conversations |
| FR-3MustThe TUITerminal User Interface shall support approval prompts, clarifying questions, and masked input (sudo/secret) | Must | The TUITerminal User Interface shall support approval prompts, clarifying questions, and masked input (sudo/secret) |
| FR-4MustThe TUITerminal User Interface shall support slash commands with completions | Must | The TUITerminal User Interface shall support slash commands with completions |
| FR-5MustThe TUITerminal User Interface shall support file path autocompletion | Must | The TUITerminal User Interface shall support file path autocompletion |
| FR-6MustThe desktop app shall provide its own composer, transcript, and slash-command pipeline | Must | The desktop app shall provide its own composer, transcript, and slash-command pipeline |
| FR-7MustThe desktop app shall communicate with a headless hermes serve backend over WebSocket/JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | Must | The desktop app shall communicate with a headless hermes serve backend over WebSocket/JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend |
| FR-8MustThe web dashboard shall embed the real TUITerminal User Interface (not a rewrite) via xterm.js | Must | The web dashboard shall embed the real TUITerminal User Interface (not a rewrite) via xterm.js |
| FR-9ShouldThe TUITerminal User Interface shall support skimming (theming) via the same skin data as the CLICommand-Line Interface | Should | The TUITerminal User Interface shall support skimming (theming) via the same skin data as the CLICommand-Line Interface |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-1MustTUITerminal User Interface input latency shall be under 50ms | Must | Performance | TUITerminal User Interface input latency shall be under 50ms |
| NFR-2ShouldThe web dashboard shall support modern browsers (Chrome, Firefox, Safari, Edge) | Should | Compatibility | The web dashboard shall support modern browsers (Chrome, Firefox, Safari, Edge) |
Constraints
- The web dashboard MUST embed the real hermes --tui via PTYPseudo-terminal bridge — not reimplement the chat experience in React
- The desktop app is a completely separate surface from the TUITerminal User Interface (its own pipeline, not an embedded TUITerminal User Interface)
- TypeScript frontends use nanostores for shared state
Acceptance Criteria
- FR-1MustThe TUITerminal User Interface shall provide chat streaming with real-time tool activity display
- Given the TUITerminal User Interface is running
- When the agent responds
- Then the response streams character-by-character through message.delta events
- FR-8MustThe web dashboard shall embed the real TUITerminal User Interface (not a rewrite) via xterm.js
- Given the dashboard is running
- When a user navigates to /chat
- Then the page shows the real hermes --tui embedded via xterm.js
- FR-6MustThe desktop app shall provide its own composer, transcript, and slash-command pipeline
- Given the desktop app is running
- When the user types a message
- Then it is sent to the backend and the response appears in the desktop transcript
Conflicts
None identified yet.
Open Questions
- Eventually the TUITerminal User Interface could replace the classic CLICommand-Line Interface entirely — what is the migration path?
Specification: Multi-Surface TUITerminal User Interface and Desktop
Overview
The TUITerminal User Interface is an InkA React renderer for terminals, used for the TUI (React for terminal) frontend communicating with a Python JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend backend over stdio. The desktop app is a separate Electron application using React + nanostores talking to a headless hermes serve backend. The dashboard embeds the real hermes --tui process through a PTYPseudo-terminal bridge.
Architecture
TUITerminal User Interface (hermes --tui):
InkA React renderer for terminals, used for the TUI frontend (ui-tui/src/) ← stdio JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend → tui_gateway (Python backend)
│ │
│ UI Components: ├── AIAgent wrapper
│ ├── app.tsx (main composer) ├── SlashWorker (subprocess)
│ ├── messageLine.tsx (streaming) ├── Transport (stdio)
│ ├── thinking.tsx (tool activity) └── GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core client
│ ├── prompts.tsx (approvals)
│ ├── sessionPicker.tsx
│ └── theme.ts / branding.tsx
Desktop (hermes serve --headless):
Electron app (apps/desktop/) ← WebSocket/JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend → AIAgent + gateway
│
├── apps/desktop/src/lib/desktop-slash-commands.ts
├── app/composer/hooks/use-slash-completions.ts
└── app/session/hooks/use-prompt-actions.ts (runSlash)
Dashboard (hermes dashboard):
Browser (web/) ───WebSocket/PTYPseudo-terminal─── hermes --tui (headless)
│
├── chat page with xterm.js
├── sidebar widgets (optional React UI)
└── REST API for session browse, model switching, tool config
Data Models
JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend Methods
| Method | Direction | Description |
|---|---|---|
| prompt.submit | Request → | User submits a message |
| message.delta | Event → UI | Response stream chunk |
| message.complete | Event → UI | Response complete |
| tool.start | Event → UI | Tool execution started |
| tool.progress | Event → UI | Tool progress update |
| tool.complete | Event → UI | Tool execution complete |
| approval.request | Event → UI | Dangerous action needs approval |
| approval.respond | Request → | User approves/denies |
| session.list | Request → | List available sessions |
| slash.exec | Request → | Execute slash command |
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| TUITerminal User Interface frontend | InkA React renderer for terminals, used for the TUI (React) | Familiar React patterns with terminal rendering |
| TUITerminal User Interface transport | stdio JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | Simple, no network dependency, reliable |
| Desktop backend | hermes serve (headless) | Same agent core, no terminal UI overhead |
| Dashboard PTYPseudo-terminal | ptyprocess | Embeds real TUITerminal User Interface without re-implementation |
| Desktop state | nanostores | Lightweight, colocated, subscription-based |
Risks and Unknowns
- The TUITerminal User Interface and classic CLICommand-Line Interface are separate implementations — feature parity requires maintaining both
- The dashboard's PTYPseudo-terminal bridge adds latency and a failure point (terminal process crash)
- Desktop app's slash command pipeline curates commands client-side — skill commands may be hidden if the curation is too aggressive
Out of Scope
- Mobile native app (React Native / Swift / Kotlin)
- Voice-only interface
Test Plan: Multi-Surface TUITerminal User Interface and Desktop
Scope
Tests covering InkA React renderer for terminals, used for the TUI/React TUITerminal User Interface (ui-tui/), JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend backend (tui_gateway/), Electron desktop app (apps/desktop/), web dashboard PTYPseudo-terminal bridge (web/), and dashboard SPASingle-Page Application.
Test Files
- tests/hermes_cli/test_tui_*.py — TUITerminal User Interface backend tests
- tests/hermes_cli/test_dashboard_*.py — Dashboard endpoint tests
- tests/hermes_cli/test_web_server_*.py — Web server tests (20+ files)
- tests/hermes_cli/test_pty_bridge.py — PTYPseudo-terminal bridge tests
- tests/hermes_cli/test_tui_bundled.py — Bundled TUITerminal User Interface tests
- tests/hermes_cli/test_dashboard_auth*.py — Dashboard auth tests
- tests/hermes_cli/test_dashboard_lifecycle_flags.py — Dashboard lifecycle
JavaScript/TypeScript Tests
- ui-tui/ — Tests use vitest (npm test in ui-tui)
- apps/desktop/ — Vitest for desktop unit tests
- apps/shared/ — Vitest for shared package
- web/ — Vitest for web dashboard
Unit Tests
- JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend method/event serialization
- GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core client connection management
- SessionA single conversation history stored in SQLite with FTS5 search picker state management
- Slash command completion logic
- Theme/skin data application
Integration Tests
- Full TUITerminal User Interface startup via hermes --tui
- Dashboard server boot and health check
- WebSocket PTYPseudo-terminal bridge connection lifecycle
- API server session browse and search
- Dashboard auth flow (login, token, cookies)
- Dashboard TUITerminal User Interface back-compat mode
Edge Cases and Failure Scenarios
| Scenario | Expected Behavior |
|---|---|
| TUITerminal User Interface backend crashes | InkA React renderer for terminals, used for the TUI frontend shows error and offers restart |
| PTYPseudo-terminal bridge process dies | Dashboard shows disconnected state |
| Desktop app backend unresponsive | Reconnection with exponential backoff |
| WebSocket disconnection mid-stream | Reconnect and resume |
| Dashboard auth token expired | Redirect to login with return URL |
Test Infrastructure
- JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend mock gateway for TUITerminal User Interface backend tests
- Flask/FastAPI test client for web server
- Headless browser for dashboard SPASingle-Page Application (when available)
- Temp ports for web server tests
Coverage Matrix
| Requirement | Test Cases |
|---|---|
| FR-1MustThe TUITerminal User Interface shall provide chat streaming with real-time tool activity display (TUITerminal User Interface chat streaming) | test_tui_resume_flow.py |
| FR-2MustThe TUITerminal User Interface shall provide a session picker for switching between conversations (TUITerminal User Interface session picker) | SessionA single conversation history stored in SQLite with FTS5 search picker tests |
| FR-3MustThe TUITerminal User Interface shall support approval prompts, clarifying questions, and masked input (sudo/secret) (TUITerminal User Interface approvals) | Approval integration tests |
| FR-4MustThe TUITerminal User Interface shall support slash commands with completions (TUITerminal User Interface slash commands) | Slash command tests |
| FR-5MustThe TUITerminal User Interface shall support file path autocompletion (TUITerminal User Interface path completion) | Path completion tests |
| FR-7MustThe desktop app shall communicate with a headless hermes serve backend over WebSocket/JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend (desktop WebSocket backend) | Web server tests |
| FR-8MustThe web dashboard shall embed the real TUITerminal User Interface (not a rewrite) via xterm.js (dashboard PTYPseudo-terminal bridge) | test_pty_bridge.py |
| NFR-1MustTUITerminal User Interface input latency shall be under 50ms (50ms input latency) | Performance measurement tests |
requirements
- Eventually the TUI could replace the classic CLI entirely — what is the migration path?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory | The AI runtime (AIAgent class) that drives conversation, tool calling, and memory |
| SkillA markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow | A markdown document (SKILL.md) that guides the agent on how to perform a specific task or workflow |
| PluginA Python package that extends the agent via hooks, tools, CLI subcommands, or provider profiles | A Python package that extends the agent via hooks, tools, CLICommand-Line Interface subcommands, or provider profiles |
| ToolsetA named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) | A named grouping of tools that can be enabled/disabled per platform (e.g., hermes-telegram, web, browser) |
| ProfileAn isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ | An isolated agent instance with its own config, credentials, skills, and sessions, stored under ~/.hermes/profiles/ |
| GatewayThe asyncio-based service that manages messaging platform adapters and routes messages to the agent core | The asyncio-based service that manages messaging platform adapters and routes messages to the agent core |
| SessionA single conversation history stored in SQLite with FTS5 search | A single conversation history stored in SQLite with FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history search |
| Skill lifecycleThe curator system that tracks agent-created skill usage and auto-archives stale skills | The curator system that tracks agent-created skill usage and auto-archives stale skills |
| Prompt cacheA cached system prompt reused across conversation turns — invalidating it mid-conversation is costly | A cached system prompt reused across conversation turns — invalidating it mid-conversation is costly |
| KanbanA durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers | A durable multi-agent work queue (SQLite-backed board) for distributing tasks across profiles/workers |
| BoardThe hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others | The hard isolation boundary of the kanban system — workers are spawned with a pinned board and cannot see others |
Technical Terms
| Term | Definition |
|---|---|
| MCPModel Context Protocol | Model Context Protocol — an open protocol for connecting LLMs with external tools and data sources |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol — a protocol for agent-to-editor integration (VS Code, Zed, JetBrains) |
| FTS5Full-Text Search version 5 — SQLite extension for full-text search across session history | Full-Text Search version 5 — SQLite extension for full-text search across session history |
| JSON-RPCA remote procedure call protocol encoded in JSON, used between the TUI frontend and Python backend | A remote procedure call protocol encoded in JSON, used between the TUITerminal User Interface frontend and Python backend |
| InkA React renderer for terminals, used for the TUI | A React renderer for terminals, used for the TUITerminal User Interface |
| Prompt_toolkitA Python library for building interactive command-line applications, used by the classic CLI | A Python library for building interactive command-line applications, used by the classic CLICommand-Line Interface |
| MoAMixture of Agents | Mixture of Agents — running a prompt through an ensemble of models |
| Footprint LadderThe ranked hierarchy for where to add new capability: extend code > CLI + skill > service-gated tool > plugin > MCP server > new core tool (last resort) | The ranked hierarchy for where to add new capability: extend code > CLICommand-Line Interface + skill > service-gated tool > plugin > MCPModel Context Protocol server > new core tool (last resort) |
| check_fnA callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) | A callable on a tool registration that gates tool availability based on prerequisites (e.g., API key presence) |
| HERMES_HOMEThe base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) | The base directory for an agent instance's config, state, skills, logs, etc. (profile-aware) |
| Observer hooksBackend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior | Backend-neutral telemetry callbacks (pre/post API request, tool call) reconstructing execution without changing runtime behavior |
| NeMo Relay / LangfuseObservability backends consuming the observer-hook contract for traces and metrics | Observability backends consuming the observer-hook contract for traces and metrics |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| MCPModel Context Protocol | Model Context Protocol |
| ACPAgent Communication Protocol | AgentThe AI runtime (AIAgent class) that drives conversation, tool calling, and memory Communication Protocol |
| FTSFull-Text Search | Full-Text Search |
| TUITerminal User Interface | Terminal User Interface |
| CLICommand-Line Interface | Command-Line Interface |
| STTSpeech-to-Text | Speech-to-Text |
| TTSText-to-Speech | Text-to-Speech |
| MoAMixture of Agents | Mixture of Agents |
| CDPChrome DevTools Protocol | Chrome DevTools Protocol |
| ABCAbstract Base Class | Abstract Base Class |
| IDEIntegrated Development Environment | Integrated Development Environment |
| VPSVirtual Private Server | Virtual Private Server |
| PTYPseudo-terminal | Pseudo-terminal |
| SPASingle-Page Application | Single-Page Application |