{"repo":"NousResearch/hermes-agent","public_id":"19101","display_label":"AGENTS.md documentation audit and updates","summary":"These issues and pull requests focus on identifying and correcting stale, incomplete, or inaccurate content in AGENTS.md, including missing sections on curator, cron, delegation, plugins, and toolsets. Multiple rounds of auditing and proposed corrections are represented across the group.","subsystem":"docs","counts":{"members":3,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":2,"merged_prs":1,"attempt_prs":0},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":20226,"merged_at":"2026-05-05T14:56:30+00:00"},"resolution":{"state":"partially_resolved","by":"pr-20226"},"freshness":{"state":"verified","last_verified_at":"2026-05-05T14:56:30+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_PARTIAL","link_density":0.4533333333333333},"fix_edges":[{"issue_number":19101,"pr_number":20226,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true,"pr_merged_at":"2026-05-05T14:56:30+00:00"}],"members":[{"kind":"issue","number":19101,"title":"AGENTS.md is stale: missing curator, incomplete cron/delegate docs, wrong test numbers, missing plugins","url":null,"state":"closed"},{"kind":"issue","number":19107,"title":"[continuing #19101] AGENTS.md gaps round 2: missing auxiliary config, unverified --now flag, stale PR refs, more","url":null,"state":"closed"},{"kind":"pr","number":20226,"title":"docs(AGENTS.md): add curator/cron/delegation/toolsets, fix plugin tree","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["AGENTS.md"],"fix_hunks":[{"file":"AGENTS.md","hunks":["@@ -37,12 +37,17 @@ hermes-agent/\n │   ├── platforms/        # Adapter per platform (telegram, discord, slack, whatsapp,\n │   │                     #   homeassistant, signal, matrix, mattermost, email, sms,\n │   │                     #   dingtalk, wecom, weixin, feishu, qqbot, bluebubbles,\n-│   │                     #   webhook, api_server, ...). See ADDING_A_PLATFORM.md.\n+│   │                     #   yuanbao, webhook, api_server, ...). See ADDING_A_PLATFORM.md.\n │   └── builtin_hooks/    # Extension point for always-registered gateway hooks (none shipped)\n ├── plugins/              # Plugin system (see \"Plugins\" section below)\n │   ├── memory/           # Memory-provider plugins (honcho, mem0, supermemory, ...)\n │   ├── context_engine/   # Context-engine plugins\n-│   └── <others>/         # Dashboard, image-gen, disk-cleanup, examples, ...\n+│   ├── kanban/           # Multi-agent board dispatcher + worker plugin\n+│   ├── hermes-achievements/  # Gamified achievement tracking\n+│   ├── observability/    # Metrics / traces / logs plugin\n+│   ├── image_gen/        # Image-generation providers\n+│   └── <others>/         # disk-cleanup, example-dashboard, google_meet, platforms,\n+│                         #   spotify, strike-freedom-cockpit, ...\n ├── optional-skills/      # Heavier/niche skills shipped but NOT active by default\n ├── skills/               # Built-in skills bundled with the repo\n ├── ui-tui/               # Ink (React) terminal UI — `hermes --tui`","@@ -53,7 +58,7 @@ hermes-agent/\n ├── environments/         # RL training environments (Atropos)\n ├── scripts/              # run_tests.sh, release.py, auxiliary scripts\n ├── website/              # Docusaurus docs site\n-└── tests/                # Pytest suite (~15k tests across ~700 files as of Apr 2026)\n+└── tests/                # Pytest suite (~17k tests across ~900 files as of May 2026)\n ```\n \n **User config:** `~/.hermes/config.yaml` (settings), `~/.hermes/.env` (API keys only).","@@ -289,9 +294,9 @@ registry.register(\n )\n ```\n \n-**2. Add to `toolsets.py`** — either `_HERMES_CORE_TOOLS` (all platforms) or a new toolset.\n+**2. Add to `toolsets.py`** — either `_HERMES_CORE_TOOLS` (all platforms) or a new toolset. **This step is required:** auto-discovery imports the tool and registers its schema, but the tool is only *exposed to an agent* if its name appears in a toolset. `_HERMES_CORE_TOOLS` is not dead code — it's the default bundle every platform's base toolset inherits from.\n \n-Auto-discovery: any `tools/*.py` file with a top-level `registry.register()` call is imported automatically — no manual import list to maintain.\n+Auto-discovery: any `tools/*.py` file with a top-level `registry.register()` call is imported automatically — no manual import list to maintain. Wiring into a toolset is still a deliberate, manual step.\n \n The registry handles schema collection, dispatch, availability checking, and error wrapping. All handlers MUST return a JSON string.\n ","@@ -313,6 +318,22 @@ The registry handles schema collection, dispatch, availability checking, and err\n    section is handled automatically by the deep-merge and does NOT require\n    a version bump.\n \n+### Top-level `config.yaml` sections (non-exhaustive):\n+\n+`model`, `agent`, `terminal`, `compression`, `display`, `stt`, `tts`,\n+`memory`, `security`, `delegation`, `smart_model_routing`, `checkpoints`,\n+`auxiliary`, `curator`, `skills`, `gateway`, `logging`, `cron`, `profiles`,\n+`plugins`, `honcho`.\n+\n+`auxiliary` holds per-task overrides for side-LLM work (curator, vision,\n+embedding, title generation, session_search, etc.) — each task can pin\n+its own provider/model/base_url/max_tokens/reasoning_effort. See\n+`agent/auxiliary_client.py::_resolve_auto` for resolution order.\n+\n+`curator` holds the background skill-maintenance config —\n+`enabled`, `interval_hours`, `min_idle_hours`, `stale_after_days`,\n+`archive_after_days`, `backup` (nested).\n+\n ### .env variables (SECRETS ONLY — API keys, tokens, passwords):\n 1. Add to `OPTIONAL_ENV_VARS` in `hermes_cli/config.py` with metadata:\n ```python","@@ -519,11 +540,176 @@ niche skills belong in `optional-skills/`.\n \n ### SKILL.md frontmatter\n \n-Standard fields: `name`, `description`, `version`, `platforms`\n-(OS-gating list: `[macos]`, `[linux, macos]`, ...),\n+Standard fields: `name`, `description`, `version`, `author`, `license`,\n+`platforms` (OS-gating list: `[macos]`, `[linux, macos]`, ...),\n `metadata.hermes.tags`, `metadata.hermes.category`,\n-`metadata.hermes.config` (config.yaml settings the skill needs — stored\n-under `skills.config.<key>`, prompted during setup, injected at load time).\n+`metadata.hermes.related_skills`, `metadata.hermes.config` (config.yaml\n+settings the skill needs — stored under `skills.config.<key>`, prompted\n+during setup, injected at load time).\n+\n+Top-level `tags:` and `category:` are also accepted and mirrored from\n+`metadata.hermes.*` by the loader.\n+\n+---\n+\n+## Toolsets\n+\n+All toolsets are defined in `toolsets.py` as a single `TOOLSETS` dict.\n+Each platform's adapter picks a base toolset (e.g. Telegram uses\n+`\"messaging\"`); `_HERMES_CORE_TOOLS` is the default bundle most\n+platforms inherit from.\n+\n+Current toolset keys: `browser`, `clarify`, `code_execution`, `cronjob`,\n+`debugging`, `delegation`, `discord`, `discord_admin`, `feishu_doc`,\n+`feishu_drive`, `file`, `homeassistant`, `image_gen`, `kanban`, `memory`,\n+`messaging`, `moa`, `rl`, `safe`, `search`, `session_search`, `skills`,\n+`spotify`, `terminal`, `todo`, `tts`, `video`, `vision`, `web`, `yuanbao`.\n+\n+Enable/disable per platform via `hermes tools` (the curses UI) or the\n+`tools.<platform>.enabled` / `tools.<platform>.disabled` lists in\n+`config.yaml`.\n+\n+---\n+\n+## Delegation (`delegate_task`)\n+\n+`tools/delegate_tool.py` spawns a subagent with an isolated\n+context + terminal session. Synchronous: the parent waits for the\n+child's summary before continuing its own loop — if the parent is\n+interrupted, the child is cancelled.\n+\n+Two shapes:\n+\n+- **Single:** pass `goal` (+ optional `context`, `toolsets`).\n+- **Batch (parallel):** pass `tasks: [...]` — each gets its own subagent\n+  running concurrently. Concurrency is capped by\n+  `delegation.max_concurrent_children` (default 3).\n+\n+Roles:\n+\n+- `role=\"leaf\"` (default) — focused worker. Cannot call `delegate_task`,\n+  `clarify`, `memory`, `send_message`, `execute_code`.\n+- `role=\"orchestrator\"` — retains `delegate_task` so it can spawn its\n+  own workers. Gated by `delegation.orchestrator_enabled` (default true)\n+  and bounded by `delegation.max_spawn_depth` (default 2).\n+\n+Key config knobs (under `delegation:` in `config.yaml`):\n+`max_concurrent_children`, `max_spawn_depth`, `child_timeout_seconds`,\n+`orchestrator_enabled`, `subagent_auto_approve`, `inherit_mcp_toolsets`,\n+`max_iterations`.\n+\n+Synchronicity rule: delegate_task is **not** durable. For long-running\n+work that must outlive the current turn, use `cronjob` or\n+`terminal(background=True, notify_on_complete=True)` instead.\n+\n+---\n+\n+## Curator (skill lifecycle)\n+\n+Background skill-maintenance system that tracks usage on agent-created\n+skills and auto-archives stale ones. Users never lose skills; archives\n+go to `~/.hermes/skills/.archive/` and are restorable.\n+\n+- **Core:** `agent/curator.py` (review loop, auto-transitions, LLM review\n+  prompt) + `agent/curator_backup.py` (pre-run tar.gz snapshots).\n+- **CLI:** `hermes_cli/curator.py` wires `hermes curator <verb>` where\n+  verbs are: `status`, `run`, `pause`, `resume`, `pin`, `unpin`,\n+  `archive`, `restore`, `prune`, `backup`, `rollback`.\n+- **Telemetry:** `tools/skill_usage.py` owns the sidecar\n+  `~/.hermes/skills/.usage.json` — per-skill `use_count`, `view_count`,\n+  `patch_count`, `last_activity_at`, `state` (active / stale /\n+  archived), `pinned`.\n+\n+Invariants:\n+- Curator only touches skills with `created_by: \"agent\"` provenance —\n+  bundled + hub-installed skills are off-limits.\n+- Never deletes; max destructive action is archive.\n+- Pinned skills are exempt from every auto-transition and from the\n+  LLM review pass.\n+- `skill_manage(action=\"delete\")` refuses pinned skills; patch/edit/\n+  write_file/remove_file go through so the agent can keep improving\n+  pinned skills.\n+\n+Config section (`curator:` in `config.yaml`):\n+`enabled`, `interval_hours`, `min_idle_hours`, `stale_after_days`,\n+`archive_after_days`, `backup.*`.\n+\n+Full user-facing docs: `website/docs/user-guide/features/curator.md`.\n+\n+---\n+\n+## Cron (scheduled jobs)\n+\n+`cron/jobs.py` (job store) + `cron/scheduler.py` (tick loop). Agents\n+schedule jobs via the `cronjob` tool; users via `hermes cron <verb>`\n+(`list`, `add`, `edit`, `pause`, `resume`, `run`, `remove`) or the\n+`/cron` slash command.\n+\n+Supported schedule formats:\n+- Duration: `\"30m\"`, `\"2h\"`, `\"1d\"`\n+- \"every\" phrase: `\"every 2h\"`, `\"every monday 9am\"`\n+- 5-field cron expression: `\"0 9 * * *\"`\n+- ISO timestamp (one-shot): `\"2026-06-01T09:00:00Z\"`\n+\n+Per-job fields include `skills` (load specific skills), `model` /\n+`provider` overrides, `script` (pre-run data-collection script whose\n+stdout is injected into the prompt; `no_agent=True` turns the script\n+into the entire job), `context_from` (chain job A's last output into\n+job B's prompt), `workdir` (run in a specific directory with its\n+`AGENTS.md`/`CLAUDE.md` loaded), and multi-platform delivery.\n+\n+Hardening invariants:\n+- **3-minute hard interrupt** on cron sessions — runaway agent loops\n+  cannot monopolize the scheduler.\n+- Catchup window: half the job's period, clamped to 120s–2h.\n+- Grace window: 120s for one-shot jobs whose fire time was missed.\n+- File lock at `~/.hermes/cron/.tick.lock` prevents duplicate ticks\n+  across processes.\n+- Cron sessions pass `skip_memory=True` by default; memory providers\n+  intentionally do not run during cron.\n+\n+Cron deliveries are **not** mirrored into the target gateway session —\n+they land in their own cron session with a header/footer frame so the\n+main conversation's message-role alternation stays intact.\n+\n+---\n+\n+## Kanban (multi-agent work queue)\n+\n+Durable SQLite-backed board that lets multiple profiles / workers\n+collaborate on shared tasks. Users drive it via `hermes kanban <verb>`;\n+workers spawned by the dispatcher drive it via a dedicated `kanban_*`\n+toolset so their schema footprint is zero when they're not inside a\n+kanban task.\n+\n+- **CLI:** `hermes_cli/kanban.py` wires `hermes kanban` with verbs\n+  `init`, `create`, `list` (alias `ls`), `show`, `assign`, `link`,\n+  `unlink`, `comment`, `complete`, `block`, `unblock`, `archive`,\n+  `tail`, plus less-commonly-used `watch`, `stats`, `runs`, `log`,\n+  `assignees`, `heartbeat`, `notify-*`, `dispatch`, `daemon`, `gc`.\n+- **Worker toolset:** `tools/kanban_tools.py` exposes `kanban_show`,\n+  `kanban_complete`, `kanban_block`, `kanban_heartbeat`, `kanban_comment`,\n+  `kanban_create`, `kanban_link` — gated by `HERMES_KANBAN_TASK` so\n+  the schema only appears for processes actually running as a worker.\n+- **Dispatcher:** long-lived loop that (default every 60s) reclaims\n+  stale claims, promotes ready tasks, atomically claims, and spawns\n+  assigned profiles. Runs **inside the gateway** by default via\n+  `kanban.dispatch_in_gateway: true`.\n+- **Plugin assets:** `plugins/kanban/dashboard/` (web UI) +\n+  `plugins/kanban/systemd/` (`hermes-kanban-dispatcher.service` for\n+  standalone dispatcher deployment).\n+\n+Isolation model:\n+- **Board** is the hard boundary — workers are spawned with\n+  `HERMES_KANBAN_BOARD` pinned in their env so they can't see other\n+  boards.\n+- **Tenant** is a soft namespace *within* a board — one specialist\n+  fleet can serve multiple businesses with workspace-path + memory-key\n+  isolation.\n+- After ~5 consecutive spawn failures on the same task the dispatcher\n+  auto-blocks it to prevent spin loops.\n+\n+Full user-facing docs: `website/docs/user-guide/features/kanban.md`.\n \n ---\n \n"]}]}],"trust":{"default_tier":"verified","includes_suggested":false}}