Skip to content

[Feature]: Add kanban_list, kanban_unblock, kanban_assign, kanban_archive tools for orchestrator profiles #20048

@curiouscleo

Description

@curiouscleo

Problem or Use Case

Orchestrator profiles need to read and steer the board, but the kanban toolset is shaped for workers — single-task, single-row operations. After issue #18968 made the existing 7 tools (kanban_show, _complete, _block, _heartbeat, _comment, _create, _link) visible to orchestrators with toolsets: [kanban], a real orchestration session immediately bumps into the gap:

> /goal Drive the space board: triage triage-status items, unblock spillover
  tasks where work is already shipped, advance P1 items by decomposing
  where needed.

Stopped. I can't actually drive the board — the space-orchestrator profile
is missing the enumeration tools.

What I have: kanban_show (needs an ID), create, link, comment, complete,
block, heartbeat.
What I'm missing: kanban_list (to see triage/blocked/P1 columns),
kanban_unblock, kanban_assign.

Without list, I can't:
- See what's in triage-status
- Find spillover blocked items with commit refs
- Enumerate P1 backlog

The orchestrator can kanban_show(t_abc) if it knows the ID, but it can't discover IDs. It can kanban_block(...) but not unblock. It can kanban_create(...) with an assignee but can't reassign. There's no clean tool path for the most natural orchestrator turn:

"Look at every blocked task, find the ones whose block reason references a shipped commit, unblock them, and complete them with that SHA as the result."

Today the only fixes are:

  1. Give the orchestrator profile the terminal toolset so it can shell out to harness kanban list --json. Works, but defeats the toolset isolation that makes orchestrators safe (no terminal/file/browser was the whole point).
  2. Have the human paste board state into chat every turn. Defeats the autonomy.
  3. Pre-create child tasks for every possible ID and let the worker figure it out. Doesn't scale.

The ergonomic right answer is: kanban tools should include enumeration + orchestrator-mutation verbs, just like the CLI does.

Proposed Solution

Add four new entries in tools/kanban_tools.py that mirror existing CLI verbs. Each goes through the same kanban_db layer the CLI uses, so behavior is consistent across surfaces:

Tool CLI equivalent Behavior
kanban_list harness kanban list [--status …] [--assignee …] [--tenant …] Returns array of task summaries (id, title, status, assignee, priority, parents, children counts). Supports the same filters as the CLI.
kanban_unblock harness kanban unblock <id> Transitions blocked → ready. Reuses the existing CLI handler.
kanban_assign harness kanban assign <id> <profile> Reassigns a task. Accepts none to unassign.
kanban_archive harness kanban archive <id> Removes the task from active columns. Already used by orchestrators sweeping stale items.

All four are gated by the same _check_kanban_mode() check the existing tools use, so they appear only for workers (HERMES_KANBAN_TASK set) or orchestrator profiles (kanban in toolsets).

kanban_unblock and kanban_assign should respect _enforce_worker_task_ownership() for workers — those mutations on a foreign task ID don't make sense from a worker context, and orchestrators (no HERMES_KANBAN_TASK) bypass that check by design.

A reasonable also-nice-to-have:

  • kanban_link already exists. Add kanban_unlink(parent_id, child_id) for symmetry — orchestrators sometimes need to break dependency chains (e.g., the circular-dep recovery I hit in this session: parent awaiting visual on child, child blocked by parent's visual ACs).

Alternatives Considered

Just shell out via the terminal tool. This is what I'm doing today as a workaround. Two reasons it's not the right answer:

  1. Backend portability. Workers running on Docker / Modal / Singularity terminal backends don't have harness on $PATH inside the container, so shelling fails. Tools run in the agent's own Python process and reach kanban.db regardless of backend (this is exactly the rationale already documented in the kanban docs for why the existing 7 tools aren't shell wrappers).

  2. Toolset isolation. Granting terminal to an orchestrator profile lets the agent run arbitrary shell commands. Orchestrator personas typically encode a "no code, only board ops" rule, but that's a soft guardrail. A native kanban_list tool removes the temptation entirely.

kanban_show against an "all" magic ID. Considered making kanban_show() accept a status filter and return a list when no specific ID is given. Hacky overload, worse ergonomics. Better to add a sibling kanban_list than overload _show.

Shell out only to specific safe commands via a kanban-cli toolset wrapper. A new toolset that wraps harness kanban * subcommands as Python tools. More work than just registering 4 new tools in kanban_tools.py and accomplishes the same thing.

Feature Type

New tool

Scope

Small (single file, < 50 lines)

The handlers are 5-15 lines each — they call into kanban_db.list_tasks(), kanban_db.unblock_task(), etc., serialize the result to JSON, and return. The tools/kanban_tools.py module already has the patterns to copy from the existing 7 tools.

Test coverage in tests/cli/test_kanban_tools.py (or wherever the existing tool tests live) — one happy-path test per new tool, plus one orchestrator-vs-worker gating test.

Contribution

I'd be happy to put up a PR for this if it sounds aligned with the project's direction. Following the same shape as #18968 (which fixed the visibility gate) — small, focused, with tests covering the orchestrator and worker paths.

Pinging this for direction first because the design choice matters: kanban_list's schema (filter args, return shape) is the kind of thing where a quick "yes, looks right" or "no, do it like X" from a maintainer saves a wasted PR.

Discovered while building an autonomous orchestrator profile against a real Kanban board (32 migrated tasks, 5 specialist worker profiles) on the v0.12.0 release.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low — cosmetic, nice to havecomp/toolsTool registry, model_tools, toolsetstype/featureNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions