NousResearch/hermes-agent
The agent that grows with you
Mixed signals — read the receipts
- ✓Last commit today
- ✓5 active contributors
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
- ⚠Small team — 5 top contributors
- ⚠Concentrated ownership — top contributor handles 54% of commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Embed this verdict
[](https://repopilot.app/r/nousresearch/hermes-agent)Paste into your README — the badge live-updates from the latest cached analysis.
Onboarding doc
Onboarding: NousResearch/hermes-agent
Generated by RepoPilot · 2026-05-05 · Source
Verdict
WAIT — Mixed signals — read the receipts
- Last commit today
- 5 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Small team — 5 top contributors
- ⚠ Concentrated ownership — top contributor handles 54% of commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
TL;DR
Hermes Agent is a self-improving AI agent framework built by Nous Research that runs a persistent, learning agent across CLI, Telegram, Discord, Slack, WhatsApp, and Signal from a single process. Its core differentiator is a closed learning loop: it autonomously creates and refines Python 'skills' from experience, maintains cross-session memory via FTS5-indexed conversation search, builds a user model via Honcho dialectic modeling, and supports any OpenAI-compatible model endpoint via a unified interface. It can spawn parallel subagents, run cron-scheduled automations, and expose itself as an ACP (Agent Communication Protocol) server via the acp_adapter/ module. The repo is a Python-first monolith: the main agent logic lives at the top level alongside acp_adapter/ (an ACP protocol server with its own __main__.py, auth, permissions, events, and session modules) and acp_registry/agent.json (the published ACP agent manifest). Platform gateways (Telegram, Discord, etc.), skill storage, scheduler, memory/FTS5 search, and the TUI are all sub-systems of the core Python package, with TypeScript (2.5M bytes) powering a documentation/web layer and potentially the docs site deployed via .github/workflows/deploy-site.yml.
Who it's for
AI engineers and power users who want a self-hosted, model-agnostic agent that learns and improves over time without being locked to a specific cloud provider or model. Secondary audience is developers contributing skills, platform integrations (messaging gateways), or ACP-compatible tool adapters who want to extend the agent's capabilities.
Maturity & risk
The repo has a rich release history from v0.2.0 through v0.12.0 with detailed changelogs (RELEASE_v*.md files), a CI pipeline covering tests, Docker publishing, Nix builds, skills indexing, supply-chain auditing, and contributor checks — indicating serious production intent. The presence of .plans/ documents (openai-api-server.md, streaming-support.md) and an AGENTS.md suggests active, structured development. Verdict: actively developed with production-grade infrastructure, but the learning-loop and ACP features are still evolving.
The ACP adapter (acp_adapter/) includes auth, permissions, and session management — security-sensitive code that is relatively new and not yet battle-tested. The project integrates with many external services (Telegram, Discord, Slack, Honcho, OpenRouter, NVIDIA NIM, etc.), so upstream API changes are a persistent risk. The large Python codebase (27M bytes) with a single organizational maintainer (Nous Research) creates bus-factor risk if core contributors churn.
Active areas of work
Active plans are captured in .plans/openai-api-server.md and .plans/streaming-support.md, indicating streaming tool output and an OpenAI-compatible API server are next milestones. The ACP adapter (acp_adapter/) appears recently added given its isolated structure and separate __main__.py. The GitHub Actions include a skills-index.yml workflow suggesting ongoing automation of the agentskills.io skill registry integration.
Get running
git clone https://github.com/NousResearch/hermes-agent.git cd hermes-agent cp .env.example .env # Fill in your API keys pip install -e . # Installs the Python package in editable mode hermes model # Select your model endpoint hermes # Launch the TUI
OR with Nix:
nix develop # Enter the dev shell (uses .envrc / direnv)
Daily commands:
CLI (after install)
hermes
ACP adapter server
python -m acp_adapter
Docker
docker build -t hermes-agent . docker run --env-file .env hermes-agent
Nix
nix run
Map of the codebase
agent/__init__.py— Core agent entrypoint that wires together the main conversation loop, tool dispatch, model adapters, and memory systems — the central nervous system of the entire codebase.agent/prompt_builder.py— Constructs the full system prompt and message context sent to the LLM, encoding all agent capabilities, memory, and skill knowledge — changing this affects every model interaction.agent/context_engine.py— Manages conversation context window, truncation, and compression decisions; directly impacts what the LLM sees and controls memory/token budgets.agent/memory_manager.py— Implements the persistent memory and skill storage layer that gives the agent its self-improvement loop across sessions — the core differentiating feature.agent/transports/base.py— Defines the abstract transport interface that all LLM backend adapters (Anthropic, Bedrock, Gemini, etc.) must implement, making it the contract for adding new model providers.agent/skill_commands.py— Handles creation, retrieval, and execution of learned skills — central to the agent's self-improvement and knowledge persistence capabilities.acp_adapter/server.py— ACP protocol server adapter exposing the agent as a standardized agent service, critical for understanding external API surface and integration points.
How to make changes
Add a new LLM provider transport
- Define the abstract interface methods your provider must implement by studying the base class contract (
agent/transports/base.py) - Create a new transport module implementing the base class with your provider's API client, request serialization, and streaming support (
agent/transports/chat_completions.py) - Create a higher-level adapter module handling provider-specific auth, schema translation, and error normalization (
agent/anthropic_adapter.py) - Register the new provider's model IDs, context window sizes, and capability flags so routing and pricing work correctly (
agent/model_metadata.py)
Add a new persistent skill or agent capability
- Define the skill's structure, validation logic, and preprocessing rules following existing skill conventions (
agent/skill_preprocessing.py) - Add CRUD command handlers for the new skill type so the agent can create, update, delete, and retrieve it (
agent/skill_commands.py) - Add curation logic to quality-control and prune the new skill type during the learning loop (
agent/curator.py) - Inject skill context into the prompt builder so the LLM knows about available skills at inference time (
agent/prompt_builder.py)
Add a new ACP-compatible tool or action
- Define the tool's input/output schema and permission requirements following ACP tool conventions (
acp_adapter/tools.py) - Add permission checks for the new tool to ensure it respects the ACP permission model (
acp_adapter/permissions.py) - Register the tool with guardrail rules to prevent unsafe invocations (
agent/tool_guardrails.py) - Wire the tool into the ACP server so it is advertised in the agent's capability manifest (
acp_adapter/server.py)
Add a new image generation provider
- Implement the image generation provider interface following existing provider patterns (
agent/image_gen_provider.py) - Register the new provider in the image generation registry with its model IDs and capabilities (
agent/image_gen_registry.py) - Update image routing logic to include the new provider in model selection decisions (
agent/image_routing.py)
Why these technologies
- Python (core language) — Dominant language in the LLM/AI ecosystem with first-class SDKs from Anthropic, OpenAI, and Google, enabling rapid integration with all major model providers.
- ACP (Agent Communication Protocol) — Standardized protocol for agent interoperability allows Hermes to be composed with other agents and embedded in larger multi-agent pipelines without tight coupling.
- Multi-provider transport abstraction — Provider-agnostic design prevents vendor lock-in, allowing users to switch between Anthropic, Bedrock, Gemini, and OpenAI-compatible endpoints without code changes.
- Persistent file-based skill/memory storage — Simple, portable, zero-infrastructure memory backend that works on a $5 VPS without requiring a database, matching the stated deployment target.
- Docker — Ensures reproducible deployments across environments from local laptops to cloud VMs, critical for an agent that manages system state.
Trade-offs already made
- File-based memory persistence over a vector database
- Why: Keeps infrastructure requirements minimal (runs on a single VPS with no external services) and simpl
- Consequence: undefined
Traps & gotchas
- The
.env.examplemust be fully populated — missing API keys for your chosen model provider will cause silent or cryptic failures at runtime, not install time. 2) The ACP adapter (python -m acp_adapter) requires a running agent session and likely specific env vars for auth tokens — checkacp_adapter/auth.pyfor required variables before testing ACP. 3) Nix is the preferred reproducible build path; without it, Python dependency pinning may differ across environments, especially for the FTS5/SQLite version. 4) TheMANIFEST.insuggests the PyPI package and the dev checkout differ in what files are included — skills or assets may be missing in apip install hermes-agentinstall vs. a git clone. 5) The.gitmodulesfile indicates submodules exist — rungit submodule update --init --recursiveafter cloning or files will be missing.
Architecture
Concepts to learn
- Agent Communication Protocol (ACP) — The acp_adapter/ module implements ACP — understanding the protocol is essential for extending Hermes' interoperability with other agents and orchestrators.
- SQLite FTS5 (Full-Text Search) — Hermes uses FTS5 to index and search past conversations across sessions — understanding FTS5 trigram/BM25 ranking explains how cross-session recall works.
- Dialectic User Modeling — Hermes uses Honcho's dialectic approach to build a model of who you are by treating the user model as a hypothesis tested through conversation — core to the 'agent that grows with you' premise.
- Skill-based Agent Learning Loop — Hermes autonomously creates Python 'skills' from complex task solutions and refines them during reuse — understanding skill lifecycle (creation, indexing, retrieval, improvement) is central to contributing to the learning subsystem.
- OpenAI-compatible API abstraction — Hermes routes all model calls through an OpenAI-compatible interface, enabling any compliant provider to be swapped in — understanding this API shape is required for adding new model providers.
- Nix Flakes (reproducible builds) — The repo uses Nix flakes (.envrc, nix.yml CI, nix-setup action) as the canonical reproducible build system — developers unfamiliar with Nix will struggle with the dev environment setup.
- Cron expression scheduling — Hermes has a built-in cron scheduler for unattended automations defined in natural language — understanding how cron expressions map to the scheduler internals is needed to extend or debug scheduled tasks.
Related repos
plastic-labs/honcho— Hermes Agent directly integrates Honcho for dialectic user modeling across sessions — a core dependency of the learning loop.AgentCommunicationProtocol/acp— Hermes implements the ACP protocol in its acp_adapter/ module; this is the spec repo for that protocol.openai/openai-agents-python— Close alternative in the same ecosystem: OpenAI's own agent framework using the same OpenAI-compatible API surface that Hermes abstracts over.microsoft/autogen— Alternative self-improving multi-agent framework solving similar parallel subagent and skill-learning problems in Python.agentskills-io/agentskills— The open standard for agent skill storage that Hermes implements — skills created by Hermes are compatible with this registry.
PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add unit tests for agent/credential_pool.py and agent/credential_sources.py
Credential management is security-critical code. The file structure shows agent/credential_pool.py and agent/credential_sources.py exist but there is no corresponding test file visible (e.g., tests/test_credential_pool.py). Given that this agent likely handles API keys for multiple providers (Anthropic, Bedrock, Gemini, Codex, Copilot), untested credential rotation/pooling logic is a high-risk gap. A contributor can add focused unit tests covering pool exhaustion, credential rotation, and invalid credential handling.
- [ ] Inspect agent/credential_pool.py and agent/credential_sources.py to map all public methods and classes
- [ ] Create tests/test_credential_pool.py with unit tests for pool initialization, credential checkout/checkin, pool exhaustion fallback, and thread-safety if applicable
- [ ] Create tests/test_credential_sources.py covering each credential source type (env var, file, etc.) and error paths for missing/malformed credentials
- [ ] Mock external secrets/env vars so tests are hermetic and safe for CI
- [ ] Ensure the new tests are picked up by the existing .github/workflows/tests.yml workflow
Add unit tests for acp_adapter/auth.py and acp_adapter/permissions.py
The acp_adapter/ package exposes an ACP server (acp_adapter/server.py) with auth and permissions layers. These two files are the security boundary between external callers and the agent's capabilities. No test files for the acp_adapter package are visible in the file listing. Adding tests here directly improves security posture and makes it safer for contributors to extend the adapter without regressions.
- [ ] Read acp_adapter/auth.py to enumerate authentication strategies (token validation, header parsing, rejection paths)
- [ ] Read acp_adapter/permissions.py to enumerate permission checks and their expected outcomes
- [ ] Create tests/test_acp_auth.py with parameterized tests for valid tokens, expired tokens, missing headers, and malformed credentials
- [ ] Create tests/test_acp_permissions.py covering allowed/denied permission combinations and edge cases (empty permission set, wildcard grants)
- [ ] Add a test fixture or factory that instantiates a minimal acp_adapter/server.py using httpx's AsyncClient or similar so auth/permission middleware can be tested end-to-end without a real network
- [ ] Verify tests run under .github/workflows/tests.yml
Refactor agent/context_engine.py by splitting context compression and reference logic into dedicated modules
The file listing shows agent/context_engine.py alongside separate agent/context_compressor.py and agent/context_references.py, which suggests that compression and reference-resolution concerns were partially extracted but the engine file likely still contains entangled logic or duplicate responsibilities. Completing this separation improves testability (each module can be unit-tested independently), makes the context pipeline easier to understand for new contributors, and reduces merge-conflict surface area as the codebase grows.
- [ ] Audit agent/context_engine.py and identify any compression logic that duplicates or should delegate to agent/context_compressor.py
- [ ] Audit agent/context_engine.py and identify any reference-resolution logic that duplicates or should delegate to agent/context_references.py
- [ ] Move duplicated/misplaced logic to the correct module, updating imports in agent/context_engine.py to use the extracted modules
- [ ] Ensure agent/context_engine.py becomes a thin orchestrator that composes context_compressor and context_references rather than implementing their logic directly
- [ ] Add or update unit tests in tests/test_context_engine.py, tests/test_context_compressor.py, and tests/test_context_references.py to cover the newly clarified boundaries
- [ ] Run the full test suite via .github/workflows/tests.yml and confirm no regressions
Good first issues
- Add unit tests for
acp_adapter/permissions.py— the permissions logic is security-critical but the file structure suggests tests may not yet exist for edge cases like overlapping permission grants. 2) Document theacp_adapter/events.pyevent schema inacp_registry/agent.jsonor a dedicated doc page — the ACP event types are currently only defined in code. 3) Add a--dry-runflag to the cron scheduler so users can preview what automations would fire without executing them — the.plans/files suggest scheduler UX is still being refined.
Top contributors
- @teknium1 — 25 commits
- @briandevans — 12 commits
- @vominh1919 — 4 commits
- @kshitijk4poor — 3 commits
- @Yoimex — 2 commits
Recent commits
8fabef9— fix(docs): register cron-script-only guide in sidebar (#19893) (teknium1)81cd678— fix(google-workspace): restore required_credential_files in SKILL.md (#16452) (briandevans)60b143e— fix(tui_gateway): guard sys.path against local package shadowing (#15989) (briandevans)645a2f4— fix(cli): fix shortcut config conflict in hermes_cli (0xharryriddle)a919269— fix(skills/email/himalaya): document v1.2.0 folder.aliases syntax (stevenchanin)9cda237— docs(cron): lead with agent-driven setup for no-agent mode (#19871) (teknium1)eadf346— fix(models): strip :cloud/-cloud suffix from models.dev Ollama Cloud IDs (briandevans)c050ee6— fix(file_ops): resolve search_files path/line collision for hyphenated numeric filenames (Yoimex)fbc477d— fix(run_agent): acquire lock in IterationBudget.used property (Ricardo-M-L)64ad7de— fix(file-ops): allow file search in hidden roots (ClawdIA)
Security observations
- High · Secrets Potentially Exposed via .env File Committed to Repository —
.env.example, .envrc. The repository contains a .env.example file and references to a .env file with API keys (OPENROUTER_API_KEY, Google AI Studio keys, etc.). If the actual .env file (not just the example) is accidentally committed, all API credentials would be exposed. The .gitignore and .dockerignore presence is positive, but the pattern of storing keys in .env files near the repo root is risky, especially in a project that may be cloned widely. Fix: Ensure .env is listed in .gitignore and .dockerignore. Use a secrets manager (e.g., HashiCorp Vault, AWS Secrets Manager) or environment injection at runtime rather than file-based secrets. Audit git history to confirm .env was never committed. Consider using pre-commit hooks (e.g., detect-secrets, git-secrets) to prevent accidental secret commits. - High · Credential Pool and Credential Sources Modules Indicate Broad Credential Handling Attack Surface —
agent/credential_pool.py, agent/credential_sources.py. Files agent/credential_pool.py and agent/credential_sources.py suggest the agent manages and rotates multiple sets of API credentials at runtime. If these modules load credentials from environment variables or files without strict input validation, or if they expose credentials through logs, error messages, or API responses, an attacker or a compromised LLM prompt could exfiltrate credentials. This is a high-risk attack surface in an AI agent context where prompt injection is a real threat. Fix: Ensure credentials are never logged or included in error messages. Apply principle of least privilege — only load credentials needed for current operation. Implement memory sanitization so credentials are not retained longer than necessary. Add prompt-injection guards to prevent LLM-driven credential exfiltration. - High · Prompt Injection Risk via LLM-Driven Tool Execution —
acp_adapter/tools.py, agent/file_safety.py, agent/context_engine.py. The agent uses tools (acp_adapter/tools.py, agent/file_safety.py) and executes actions based on LLM outputs. An adversarial prompt in user input or external data (e.g., a malicious file being read) could manipulate the LLM into invoking dangerous tools, exfiltrating data, or bypassing approval workflows. The presence of agent/file_safety.py suggests this risk is partially acknowledged but may not be fully mitigated. Fix: Implement strict tool allowlisting and input sanitization before tool execution. Enforce human-in-the-loop approval for high-risk operations (file writes, shell commands, network requests). Use a separate sandboxed LLM call for parsing external/untrusted content. Log all tool invocations with full parameters for audit trails. - High · ACP Adapter Server Lacks Visible Authentication Enforcement —
acp_adapter/server.py, acp_adapter/auth.py, acp_adapter/permissions.py. The file acp_adapter/auth.py exists alongside acp_adapter/server.py, suggesting an HTTP/API server is exposed. If authentication middleware is not enforced on all routes, unauthenticated callers could invoke agent capabilities. The presence of acp_adapter/permissions.py is encouraging but its actual enforcement cannot be confirmed from static structure alone. Fix: Audit every route in server.py to confirm auth middleware is applied. Implement authentication by default (deny-by-default policy). Use token-based authentication (e.g., Bearer tokens) with expiry. Add integration tests that verify unauthenticated requests are rejected with 401/403. - Medium · Docker Image Runs with Gosu (Privilege Escalation Vector) —
Dockerfile. The Dockerfile uses tianon/gosu for privilege switching. While gosu is a common pattern to drop from root to a non-root user, if the entrypoint script is misconfigured or gosu is used to switch to root at runtime, it becomes a privilege escalation vector. The Dockerfile does not visibly define a non-root USER instruction in the snippet provided. Fix: Explicitly define a non-root USER in the Dockerfile after all setup steps. Verify gosu is only used to switch from root to a lower-privilege user, never the reverse. Use Docker's --security-opt=no-new-privileges flag at runtime. Consider replacing gosu with su-exec or native USER instruction where possible. - Medium · Docker Image Inst —
undefined. undefined Fix: undefined
LLM-derived; treat as a starting point, not a security audit.
Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.