Skip to content

Feat/per task model override plus kanban - #46128

Closed
ipecxx wants to merge 4 commits into
NousResearch:mainfrom
ipecxx:feat/per-task-model-override-plus-kanban
Closed

ipecxx wants to merge 4 commits into
NousResearch:mainfrom
ipecxx:feat/per-task-model-override-plus-kanban

Conversation

@ipecxx

@ipecxx ipecxx commented Jun 14, 2026

Copy link
Copy Markdown

feat(delegate+kanban): per-task model_override end-to-end

Closes the v0.16.0 gap where per-task model on delegate_task was silently
dropped (subagents always inherited the parent's model) and where kanban's
tasks.model_override column existed in the schema but was unreachable from
the public write API.

What this PR does

  • tools/delegate_tool.py — accept and propagate per-task and top-level
    model on every leaf / orchestrator child (the symptom in issue Feature: Per-task model override for delegate_task #41814).
  • hermes_cli/kanban_db.pycreate_task() now accepts model_override;
    dispatcher passes -m <model> to the spawned worker when the column is
    set; schema migration already present for older DBs.
  • hermes_cli/kanban.py — public spawn_worker helper extracted for the
    4-profile orchestration pipeline.
  • Operator-actionable last_failure_error via kb._classify_worker_error()
    (HTTP 429 / 401 / 400 / 413 / 404 / 410 → rate_limited / auth_failed /
    context_overflow / model_unavailable); consistent 2-strike rule
    applied uniformly across the failure matrix.

Why now

Local testing on v0.16.0 confirmed that all four delegate_task call sites
ignore model, forcing every subagent to use the parent's model. The
kanban-side model_override column was a read-only dead end. This PR makes
both paths work end-to-end and makes the dispatcher error readable in one
glance.

How it was validated

  • kpi_test_per_task_model.py and kpi_test_per_task_model_live.py — verify
    the patched delegate_task propagates model to the child subprocess.
  • kpi_test_kanban_failure_handling.py — 11/11 pass, exercises
    _classify_worker_error() against the full HTTP-error matrix.
  • kpi_test_scenario_dashboard.py — 7-subagent / 4-model dashboard DAG
    (minimax-m3 / kimi-k2.7-code / glm-5.1 / deepseek-v4) on Ollama Cloud.

Open questions / follow-ups

Commits

38782c621 fix(kanban): operator-actionable last_failure_error + consistent 2-strike
a6434e211 kanban: add 4-profile pipeline + public spawn helper
441fb3eea feat(kanban): expose per-task model_override on the write side
178fb4d6f fix(delegate): honor per-task and top-level model override on delegate_task

Test plan for reviewers

  1. python C:\Users\andre\kpi_test_per_task_model_live.py — exit 0.
  2. python C:\Users\andre\kpi_test_kanban_failure_handling.py — 11/11 PASS.
  3. python C:\Users\andre\kpi_test_scenario_dashboard.py — 4-model DAG runs.

Andre and others added 4 commits June 14, 2026 13:02
…e_task

Cherry-picks PR NousResearch#41865 (michaelversluis) to fix the bug where the
`model` field on `delegate_task` was silently dropped.

Changes:
- tools/delegate_tool.py:
  - Add `model: Optional[str] = None` to `delegate_task` signature.
  - Per-task `model` (in `tasks[]`) beats top-level `model`,
    which beats config-resolved `delegation.model`. Whitespace-only
    strings are treated as omitted so they don't clobber a real value.
  - Expose `model` in DELEGATE_TASK_SCHEMA at top level AND per-task.
- run_agent.py:
  - Forward `model` from function_call args to `delegate_task`.
- tests/tools/test_delegate.py:
  - 5 regression tests covering schema exposure, top-level
    forwarding, per-task precedence, config-fallback, and the
    whitespace guard.

Refs: NousResearch#41814, NousResearch#41865
The dispatcher has been honouring tasks.model_override since
f01ee0b (May 2026, hongchen1993) — when the column is set, it
appends '-m <model>' to the spawned hermes worker. The column is
also surfaced in 'hermes kanban show' (79f6654). But the WRITE
side was never added: there was no way to set model_override
through the public API.

This commit closes that gap so callers can route individual tasks
to a specific model without spinning up a new profile.

  - kb.create_task() gains model_override: Optional[str] (with
    empty-string → None normalisation, matching the forgiving
    pattern used by --max-retries etc.).
  - 'hermes kanban create --model M' exposes it on the CLI; the
    value flows into create_task.
  - SwarmWorkerSpec gains model: Optional[str] so per-worker
    overrides are first-class on the swarm surface too.
  - 'hermes kanban swarm --worker profile:title@kimi-k2.7-code'
    parses the @model tail.
  - _task_to_dict now echoes model_override in 'hermes kanban
    create --json' and 'hermes kanban show --json' so the
    override is visible without reading SQLite directly.

Verified by C:\Users\andre\kpi_test_kanban_per_task_model.py
(KPI-K, 6/6 PASS). The pre-existing delegate_task patch
(ec6c2bb0c) and its KPI test are unaffected.

Builds on: f01ee0b feat: per-task model override for kanban workers
           79f6654 feat(kanban): surface per-task model_override in show + tool output
Wires the validated 4-profile orchestration pattern (coder/reviewer/
researcher/analyst) into the kanban dispatcher so any new multi-role
job can reuse it. Two new modules + one new CLI subcommand:

  - hermes_cli/spawn_worker.py
    Public build_spawn_cmd(profile, prompt, *, model=None, skills=None)
    returns the canonical argv list. The dispatcher's _default_spawn
    now calls this helper, so a future change to the spawn shape lands
    in one place.

  - hermes_cli/kanban_pipeline.py
    Preset-based pipeline helper. create_pipeline(conn, goal, preset,
    overrides) creates 1 planning root (auto-completed to act as the
    shared blackboard) and 4 child cards in parallel, each with the
    role's validated model_override + skills. 4-profile preset is
    the only one today, but the registry is open for 2/3/6-profile
    additions without code changes to the helper.

  - hermes_cli/kanban.py
    Adds 'hermes kanban pipeline <goal> [--preset 4-profile]
    [--coder-model ... --reviewer-model ... --researcher-model ...
    --analyst-model ...] [--json]' subcommand.

Validated by kpi_test_pipeline.py (7 KPIs: --help, create+assignee+
model, link+status, spawn helper import+shape, max_concurrent
regression, existing-tasks regression, preset auto-fill).

Closes kanban task t_9283c577.
…rike

User observed 4 blocked tasks under the gateway dashboard with
'last_failure_error=pid X not alive' — operator-actionable? No.
The dispatcher just knew the worker PID was gone; the actual cause
(HTTP 429 from Ollama Cloud, HTTP 401, context overflow, etc) was
buried in <board>/logs/<task>.log.

Two fixes in this commit:

1) K1 — last_failure_error now carries the HTTP error class.
   New _classify_worker_error(log_path) helper reads the tail
   of the worker's log (last 16 KiB, cheap) and extracts one of:
     - 'rate_limited' (HTTP 429 / quota / throttling)
     - 'auth_failed' (HTTP 401/403 / bad credentials)
     - 'context_overflow' (HTTP 400/413 / token limit)
     - 'model_unavailable' (HTTP 404/410 / model not found)
     - 'unknown' (no log, empty log, no recognizable pattern)
   The dispatcher now writes the prefixed message as
   last_failure_error so the dashboard reads e.g.
   rate_limited: HTTP 429: Error code: 429 - {'error': 'extra
   usage auto reload monthly max reached...'} instead of the
   useless 'pid 12345 not alive'. The full log is still under
   <board>/logs/<task>.log for the operator who needs more.

2) K2 — consistent 2-strike policy for ALL crash types.
   Removed the 1-strike shortcuts that used to block protocol
   violations and systemic (3+ same-fingerprint) crashes on the
   FIRST occurrence. Now every crash type takes the same path
   through _record_task_failure with failure_limit=None,
   which falls through to DEFAULT_FAILURE_LIMIT=2. The first
   crash is forgiven (status=ready, counter=1); the second
   trips the breaker. Per-task max_retries override still
   wins (e.g. hermes kanban create --max-retries 1 blocks on
   first failure — that path is preserved).

Side-effect fixes from the same pass:
  - The 62c85118d refactor left a dangling reference to
    worker_toolsets in the dispatcher (the var was removed when
    the spawn was factored into spawn_worker.build_spawn_cmd).
    Re-added the local resolution so dispatch works.
  - spawn_worker.build_spawn_cmd was silently dropping
    'kanban-worker' from the user's skills list, with no
    replacement downstream. Removed the filter; the dispatcher's
    'auto-inject kanban-worker if not in user skills' logic is now
    the single source of truth.
  - kanban-worker is now inserted as the FIRST --skills
    flag (before any user-supplied per-task skills), matching the
    test expectation 'kanban-worker first (built-in)'.

Tests:
  - tests/hermes_cli/test_kanban_db.py::test_detect_crashed_workers_systemic_failure_fast_block
    updated to verify the new 2-strike policy (4 tasks with the
    same crash each go to ready, counter=1, NOT blocked).
  - tests/hermes_cli/test_kanban_core_functionality.py::test_detect_crashed_workers_protocol_violation_auto_blocks
    updated to verify protocol violations now also follow
    2-strike (ready, counter=1) instead of auto-blocking.

New KPI test:
  - C:\Users\andre\kpi_test_kanban_failure_handling.py
    9 in-process + 2 regression checks (KPI-K, KPI-P).
    All 11 PASS. Tests the new policy on synthetic tasks and
    verifies the HTTP-class extraction on 4 different log shapes
    (429, 401, 400-context, missing/empty log).

Regression: all 3 KPI suites green (KPI-F 11/11, KPI-K 6/6,
KPI-P 7/7). 417 of 430 hermes_cli kanban tests pass; the 13
failing are all pre-existing Windows pid-bookkeeping flakes
(pid reaping, hermes path shim, zombie cleanup, profile
enumeration) that were failing before this commit.

Builds on: 62c85118d kanban: add 4-profile pipeline + public spawn helper
           af06a7f5a feat(kanban): expose per-task model_override on the write side
           ec6c2bb0c fix(delegate): honor per-task and top-level model override on delegate_task
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cron Cron scheduler and job management tool/delegate Subagent delegation comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint labels Jun 14, 2026
@teknium1

teknium1 commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

We do not want this

@teknium1 teknium1 closed this Jul 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cron Cron scheduler and job management P3 Low — cosmetic, nice to have tool/delegate Subagent delegation type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants