diff --git a/AGENTS.md b/AGENTS.md index 7c324f5033..9ba8f75b45 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -830,10 +830,11 @@ kanban task. `unlink`, `comment`, `complete`, `block`, `unblock`, `archive`, `tail`, plus less-commonly-used `watch`, `stats`, `runs`, `log`, `assignees`, `heartbeat`, `notify-*`, `dispatch`, `daemon`, `gc`. -- **Worker toolset:** `tools/kanban_tools.py` exposes `kanban_show`, - `kanban_complete`, `kanban_block`, `kanban_heartbeat`, `kanban_comment`, - `kanban_create`, `kanban_link` — gated by `HERMES_KANBAN_TASK` so - the schema only appears for processes actually running as a worker. +- **Worker/orchestrator toolset:** `tools/kanban_tools.py` exposes + `kanban_show`, `kanban_complete`, `kanban_block`, `kanban_heartbeat`, + `kanban_comment`, `kanban_create`, `kanban_link`; profiles that + explicitly enable the `kanban` toolset outside a dispatcher-spawned + task also get `kanban_list` and `kanban_unblock` for board routing. - **Dispatcher:** long-lived loop that (default every 60s) reclaims stale claims, promotes ready tasks, atomically claims, and spawns assigned profiles. Runs **inside the gateway** by default via @@ -849,8 +850,9 @@ Isolation model: - **Tenant** is a soft namespace *within* a board — one specialist fleet can serve multiple businesses with workspace-path + memory-key isolation. -- After ~5 consecutive spawn failures on the same task the dispatcher - auto-blocks it to prevent spin loops. +- After `kanban.failure_limit` consecutive non-success attempts on the + same task (default: 2), the dispatcher auto-blocks it to prevent spin + loops. Full user-facing docs: `website/docs/user-guide/features/kanban.md`. diff --git a/skills/autonomous-ai-agents/hermes-agent/SKILL.md b/skills/autonomous-ai-agents/hermes-agent/SKILL.md index e0e7a50ea4..63924c81f7 100644 --- a/skills/autonomous-ai-agents/hermes-agent/SKILL.md +++ b/skills/autonomous-ai-agents/hermes-agent/SKILL.md @@ -680,15 +680,19 @@ User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curato Durable SQLite board for multi-profile / multi-worker collaboration. Users drive it via `hermes kanban `; dispatcher-spawned workers -see a focused `kanban_*` toolset gated by `HERMES_KANBAN_TASK` so the -schema footprint is zero outside worker processes. +see a focused `kanban_*` toolset gated by `HERMES_KANBAN_TASK`, and +orchestrator profiles can opt into the broader `kanban` toolset. Normal +sessions still have zero `kanban_*` schema footprint unless configured. - **CLI verbs (common):** `init`, `create`, `list` (alias `ls`), `show`, `assign`, `link`, `unlink`, `comment`, `complete`, `block`, `unblock`, `archive`, `tail`. Less common: `watch`, `stats`, `runs`, `log`, `dispatch`, `daemon`, `gc`. -- **Worker toolset:** `kanban_show`, `kanban_complete`, `kanban_block`, - `kanban_heartbeat`, `kanban_comment`, `kanban_create`, `kanban_link`. +- **Worker/orchestrator toolset:** `kanban_show`, `kanban_complete`, + `kanban_block`, `kanban_heartbeat`, `kanban_comment`, `kanban_create`, + `kanban_link`; profiles that explicitly enable the `kanban` toolset + outside a dispatcher-spawned task also get `kanban_list` and + `kanban_unblock` for board routing. - **Dispatcher** runs inside the gateway by default (`kanban.dispatch_in_gateway: true`) — reclaims stale claims, promotes ready tasks, atomically claims, spawns assigned profiles. diff --git a/tests/plugins/test_kanban_dashboard_plugin.py b/tests/plugins/test_kanban_dashboard_plugin.py index 708f9084d9..9fa23226af 100644 --- a/tests/plugins/test_kanban_dashboard_plugin.py +++ b/tests/plugins/test_kanban_dashboard_plugin.py @@ -1898,10 +1898,11 @@ def test_diagnostics_endpoint_severity_filter(client): # requires ``t_[a-f0-9]{8,}``. p1 = kb.create_task(conn, title="prose", assignee="a") kb.complete_task(conn, p1, summary="mentioned t_deadbeef1234") - # An error-severity diagnostic (spawn failures) on another + # An error-severity diagnostic (spawn failures) on another. + # Keep this below critical severity (failure_threshold * 2). p2 = kb.create_task(conn, title="spawn", assignee="b") conn.execute( - "UPDATE tasks SET consecutive_failures=5, last_failure_error='x' WHERE id=?", + "UPDATE tasks SET consecutive_failures=2, last_failure_error='x' WHERE id=?", (p2,), ) conn.commit() diff --git a/tests/stress/test_subprocess_e2e.py b/tests/stress/test_subprocess_e2e.py index 5dd27f25ee..ea05123000 100644 --- a/tests/stress/test_subprocess_e2e.py +++ b/tests/stress/test_subprocess_e2e.py @@ -12,6 +12,7 @@ This validates the IPC + lifecycle story that mocks can't: import json import os +from pathlib import Path import subprocess import sys import tempfile @@ -81,7 +82,7 @@ exec {PY} -m hermes_cli.main "$@" tids = [] for i in range(3): tid = kb.create_task( - conn, title=f"real-e2e-{i}", assignee="worker", + conn, title=f"real-e2e-{i}", assignee="default", ) tids.append(tid) @@ -145,7 +146,7 @@ exec {PY} -m hermes_cli.main "$@" print("=" * 60) crash_tid = kb.create_task( - conn, title="crash-e2e", assignee="worker", + conn, title="crash-e2e", assignee="default", ) # Spawn a worker that sleeps long enough for us to kill it. diff --git a/tools/kanban_tools.py b/tools/kanban_tools.py index e23d86b8e9..43982b0949 100644 --- a/tools/kanban_tools.py +++ b/tools/kanban_tools.py @@ -1,8 +1,10 @@ """Kanban tools — structured tool-call surface for worker + orchestrator agents. -These tools are only registered into the model's schema when the agent is -running under the dispatcher (env var ``HERMES_KANBAN_TASK`` set). A -normal ``hermes chat`` session sees **zero** kanban tools in its schema. +These tools are registered into the model's schema when the agent is +running under the dispatcher (env var ``HERMES_KANBAN_TASK`` set) or when +the active profile explicitly enables the ``kanban`` toolset for +orchestrator work. A normal ``hermes chat`` session still sees **zero** +kanban tools in its schema unless configured. Why tools instead of just shelling out to ``hermes kanban``? @@ -20,8 +22,9 @@ Why tools instead of just shelling out to ``hermes kanban``? Humans continue to use the CLI (``hermes kanban …``), the dashboard (``hermes dashboard``), and the slash command (``/kanban …``) — all -three bypass the agent entirely. The tools are ONLY for the worker -agent's handoff back to the kernel. +three bypass the agent entirely. The tools are for dispatcher-spawned +worker handoffs and for configured orchestrator profiles that route work +through the board. """ from __future__ import annotations diff --git a/website/docs/reference/cli-commands.md b/website/docs/reference/cli-commands.md index c6850e1c17..cf10585829 100644 --- a/website/docs/reference/cli-commands.md +++ b/website/docs/reference/cli-commands.md @@ -384,7 +384,7 @@ Multi-profile, multi-project collaboration board. Each install can host many boa |------|---------| | `--board ` | Operate on a specific board. Defaults to the current board (set via `hermes kanban boards switch`, the `HERMES_KANBAN_BOARD` env var, or `default`). | -**This is the human / scripting surface.** Agent workers spawned by the dispatcher drive the board through a dedicated `kanban_*` [toolset](/docs/user-guide/features/kanban#how-workers-interact-with-the-board) (`kanban_show`, `kanban_complete`, `kanban_block`, `kanban_create`, `kanban_link`, `kanban_comment`, `kanban_heartbeat`) instead of shelling to `hermes kanban`. Workers have `HERMES_KANBAN_BOARD` pinned in their env so they physically cannot see other boards. +**This is the human / scripting surface.** Agent workers spawned by the dispatcher drive the board through a dedicated `kanban_*` [toolset](/docs/user-guide/features/kanban#how-workers-interact-with-the-board) (`kanban_show`, `kanban_complete`, `kanban_block`, `kanban_create`, `kanban_link`, `kanban_comment`, `kanban_heartbeat`; orchestrator profiles also get `kanban_list` and `kanban_unblock`) instead of shelling to `hermes kanban`. Workers have `HERMES_KANBAN_BOARD` pinned in their env so they physically cannot see other boards. | Action | Purpose | |--------|---------| diff --git a/website/docs/reference/tools-reference.md b/website/docs/reference/tools-reference.md index db8a8102b6..7da736713d 100644 --- a/website/docs/reference/tools-reference.md +++ b/website/docs/reference/tools-reference.md @@ -118,17 +118,19 @@ Scoped to the Feishu document-comment handler. Drives comment read/write operati ## `kanban` toolset -Registered only when the agent is spawned by the kanban dispatcher (`HERMES_KANBAN_TASK` env set). Lets workers mark tasks done with structured handoffs, block for human input, heartbeat during long ops, comment on threads, and (for orchestrators) fan out into child tasks. See [Kanban Multi-Agent](/docs/user-guide/features/kanban) for the full workflow. +Registered when the agent is either (a) spawned by the kanban dispatcher (`HERMES_KANBAN_TASK` env set) or (b) running in a profile that explicitly enables the `kanban` toolset. Task-scoped workers use lifecycle tools for their assigned task; orchestrator profiles additionally get board-routing tools like `kanban_list` and `kanban_unblock`. See [Kanban Multi-Agent](/docs/user-guide/features/kanban) for the full workflow. | Tool | Description | Requires environment | |------|-------------|----------------------| -| `kanban_show` | Show the active kanban task assigned to this worker (title, description, comments, dependencies). | `HERMES_KANBAN_TASK` | -| `kanban_complete` | Mark the current task done with a structured handoff payload (results, artifacts, follow-ups). | `HERMES_KANBAN_TASK` | -| `kanban_block` | Block the current task on a question for the user — the dispatcher pauses, surfaces the question, and resumes once a human replies. | `HERMES_KANBAN_TASK` | -| `kanban_heartbeat` | Send a progress heartbeat during a long-running operation so the dispatcher knows the worker is still alive. | `HERMES_KANBAN_TASK` | -| `kanban_comment` | Add a comment to the task thread without changing its state — useful for surfacing intermediate findings. | `HERMES_KANBAN_TASK` | -| `kanban_create` | (Orchestrator only) Fan out child tasks from the current task. | `HERMES_KANBAN_TASK` + orchestrator role | -| `kanban_link` | (Orchestrator only) Link related tasks together (blocks/blocked-by/related). | `HERMES_KANBAN_TASK` + orchestrator role | +| `kanban_show` | Show the active kanban task assigned to this worker (title, description, comments, dependencies). | `HERMES_KANBAN_TASK` or `kanban` toolset | +| `kanban_list` | List board tasks with filters. Orchestrator-only; hidden from dispatcher-spawned task workers. | profile with `kanban` toolset | +| `kanban_complete` | Mark the current task done with a structured handoff payload (results, artifacts, follow-ups). | `HERMES_KANBAN_TASK` or `kanban` toolset | +| `kanban_block` | Block the current task on a question for the user — the dispatcher pauses, surfaces the question, and resumes once a human replies. | `HERMES_KANBAN_TASK` or `kanban` toolset | +| `kanban_heartbeat` | Send a progress heartbeat during a long-running operation so the dispatcher knows the worker is still alive. | `HERMES_KANBAN_TASK` or `kanban` toolset | +| `kanban_comment` | Add a comment to the task thread without changing its state — useful for surfacing intermediate findings. | `HERMES_KANBAN_TASK` or `kanban` toolset | +| `kanban_create` | Fan out child tasks from the current task. Used by orchestrators and follow-up-spawning workers. | `HERMES_KANBAN_TASK` or `kanban` toolset | +| `kanban_link` | Link tasks with a parent → child dependency edge. | `HERMES_KANBAN_TASK` or `kanban` toolset | +| `kanban_unblock` | Return a blocked task to `ready`. Orchestrator-only; hidden from dispatcher-spawned task workers. | profile with `kanban` toolset | ## `memory` toolset diff --git a/website/docs/reference/toolsets-reference.md b/website/docs/reference/toolsets-reference.md index 61b51e4e30..a9c3d6b8d8 100644 --- a/website/docs/reference/toolsets-reference.md +++ b/website/docs/reference/toolsets-reference.md @@ -67,7 +67,7 @@ Or in-session: | `computer_use` | `computer_use` | Background macOS desktop control via cua-driver — does not steal cursor/focus. Works with any tool-capable model. macOS only; requires `cua-driver` on `$PATH`. | | `image_gen` | `image_generate` | Text-to-image generation via FAL.ai (with opt-in OpenAI / xAI backends). | | `video_gen` | `video_generate` | Text-to-video and image-to-video via plugin-registered backends (xAI Grok-Imagine, FAL.ai Veo 3.1 / Pixverse v6 / Kling O3). Pass `image_url` to animate an image; omit it for text-to-video. | -| `kanban` | `kanban_block`, `kanban_comment`, `kanban_complete`, `kanban_create`, `kanban_heartbeat`, `kanban_link`, `kanban_show` | Multi-agent coordination tools — only registered when the agent is spawned by the kanban dispatcher (`HERMES_KANBAN_TASK` env set). Lets workers mark tasks done with structured handoffs, block for human input, heartbeat during long ops, comment on threads, and (for orchestrators) fan out into child tasks. | +| `kanban` | `kanban_block`, `kanban_comment`, `kanban_complete`, `kanban_create`, `kanban_heartbeat`, `kanban_link`, `kanban_list`, `kanban_show`, `kanban_unblock` | Multi-agent coordination tools. Registered for dispatcher-spawned task workers (`HERMES_KANBAN_TASK`) and for profiles that explicitly enable the `kanban` toolset. Workers mark tasks done, block, heartbeat, comment, and create/link follow-up tasks; orchestrator profiles additionally get board-routing tools like list/unblock. | | `memory` | `memory` | Persistent cross-session memory management. | | `messaging` | `send_message` | Send messages to other platforms (Telegram, Discord, etc.) from within a session. | | `moa` | `mixture_of_agents` | Multi-model consensus via Mixture of Agents. | diff --git a/website/docs/user-guide/features/kanban-tutorial.md b/website/docs/user-guide/features/kanban-tutorial.md index 88a0f9cf5e..94a01fc36b 100644 --- a/website/docs/user-guide/features/kanban-tutorial.md +++ b/website/docs/user-guide/features/kanban-tutorial.md @@ -236,10 +236,11 @@ A deploy task that can't spawn its worker because `AWS_ACCESS_KEY_ID` isn't set ```bash hermes kanban create "Deploy to staging (missing creds)" \ - --assignee deploy-bot --tenant ops + --assignee deploy-bot --tenant ops \ + --max-retries 3 ``` -The dispatcher tries to spawn the worker. Spawn fails (`RuntimeError: AWS_ACCESS_KEY_ID not set`). The dispatcher releases the claim, increments a failure counter, and tries again next tick. After three consecutive failures (the default `failure_limit`), the circuit trips: the task goes to `blocked` with outcome `gave_up`. No more retries until a human unblocks it. +The dispatcher tries to spawn the worker. Spawn fails (`RuntimeError: AWS_ACCESS_KEY_ID not set`). The dispatcher releases the claim, increments a failure counter, and tries again next tick. Because this example sets `--max-retries 3`, the circuit trips after three consecutive failures: the task goes to `blocked` with outcome `gave_up`. If you omit the flag, Hermes uses `kanban.failure_limit` (default: 2). No more retries until a human unblocks it. Click the blocked task: diff --git a/website/docs/user-guide/features/kanban.md b/website/docs/user-guide/features/kanban.md index 3bd1b3eeea..2f81b621e0 100644 --- a/website/docs/user-guide/features/kanban.md +++ b/website/docs/user-guide/features/kanban.md @@ -290,7 +290,7 @@ Three reasons: 2. **No shell-quoting fragility.** Passing `--metadata '{"files": [...]}'` through shlex + argparse is a latent footgun. Structured tool args skip it entirely. 3. **Better errors.** Tool results are structured JSON the model can reason about, not stderr strings it has to parse. -**Zero schema footprint on normal sessions.** A regular `hermes chat` session has zero `kanban_*` tools in its schema. The `check_fn` on each tool only returns True when `HERMES_KANBAN_TASK` is set, which only happens when the dispatcher spawned this process. No tool bloat for users who never touch kanban. +**Zero schema footprint on normal sessions.** A regular `hermes chat` session has zero `kanban_*` tools in its schema unless the active profile explicitly enables the `kanban` toolset for orchestrator work. Dispatcher-spawned task workers get task-scoped tools because `HERMES_KANBAN_TASK` is set; orchestrator profiles get the broader routing surface through config. No tool bloat for users who never touch kanban. The `kanban-worker` and `kanban-orchestrator` skills teach the model which tool to call when and in what order. diff --git a/website/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent.md b/website/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent.md index ec0a4a9250..f954be2822 100644 --- a/website/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent.md +++ b/website/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent.md @@ -697,19 +697,24 @@ User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curato Durable SQLite board for multi-profile / multi-worker collaboration. Users drive it via `hermes kanban `; dispatcher-spawned workers -see a focused `kanban_*` toolset gated by `HERMES_KANBAN_TASK` so the -schema footprint is zero outside worker processes. +see a focused `kanban_*` toolset gated by `HERMES_KANBAN_TASK`, and +orchestrator profiles can opt into the broader `kanban` toolset. Normal +sessions still have zero `kanban_*` schema footprint unless configured. - **CLI verbs (common):** `init`, `create`, `list` (alias `ls`), `show`, `assign`, `link`, `unlink`, `comment`, `complete`, `block`, `unblock`, `archive`, `tail`. Less common: `watch`, `stats`, `runs`, `log`, `dispatch`, `daemon`, `gc`. -- **Worker toolset:** `kanban_show`, `kanban_complete`, `kanban_block`, - `kanban_heartbeat`, `kanban_comment`, `kanban_create`, `kanban_link`. +- **Worker/orchestrator toolset:** `kanban_show`, `kanban_complete`, + `kanban_block`, `kanban_heartbeat`, `kanban_comment`, `kanban_create`, + `kanban_link`; profiles that explicitly enable the `kanban` toolset + outside a dispatcher-spawned task also get `kanban_list` and + `kanban_unblock` for board routing. - **Dispatcher** runs inside the gateway by default (`kanban.dispatch_in_gateway: true`) — reclaims stale claims, promotes ready tasks, atomically claims, spawns assigned profiles. - Auto-blocks a task after ~5 consecutive spawn failures. + Auto-blocks a task after the configured `kanban.failure_limit` + consecutive non-success attempts (default: 2). - **Isolation:** board is the hard boundary (workers get `HERMES_KANBAN_BOARD` pinned in env); tenant is a soft namespace within a board for workspace-path + memory-key isolation.