chat-agent-loops-2

chat-agent-loops fix is broken: .chat-2 dispatched 458 times in autohaiku/workgraph — cycle reactivation still firing for chat-loop tagged tasks

Metadata

Statusdone
Assignedagent-675
Agent identityf51439356729d112a6c404803d88015d5b44832c6c584c62b96732b63c2b0c7e
Created2026-04-27T13:11:47.011376005+00:00
Started2026-04-27T13:12:12.524912498+00:00
Completed2026-04-27T13:36:17.468271063+00:00
Tagseval-scheduled
Eval score0.92
└ blocking impact0.90
└ completeness0.98
└ constraint fidelity0.85
└ coordination overhead0.85
└ correctness0.95
└ downstream usability0.90
└ efficiency0.85
└ intent fidelity0.81
└ style adherence0.92

Description

Description

chat-agent-loops shipped (commit 704ed26f8 by agent-228) but does NOT actually prevent the chat-loop thrashing. Live evidence in /home/erik/workgraph just now:

[dispatcher] Priority dispatch order: [.chat-2:50(d458)]
[dispatcher] Spawning agent for: .chat-2 - Chat 2 (executor: claude)

.chat-2 was dispatched 458 times. 5+ agents alive on it simultaneously, more spawning every tick. Until I manually archived it (wg service archive-chat 2), it was burning tokens nonstop.

Likely cause

The merged fix probably touched a different code path than the actual cycle-reactivation trigger. The right fix is in src/graph.rs evaluate_all_cycle_iterations: skip cycles whose config-owner task has tag chat-loop or coordinator-loop. I made this exact change locally during a prior session, but it got overwritten when other commits landed (and I didn't commit my version).

Required fix (same as my prior local bandaid)

In src/graph.rs (look for pub fn evaluate_all_cycle_iterations):

let Some((config_owner_id, cycle_config)) = found else {
    continue;
};

// Chat-loop tasks are event-driven (wake on inbox), NOT polled by
// cycle reactivation. Skip them — otherwise the chat agent gets
// re-spawned on every dispatcher tick when its inbox is empty.
if let Some(owner_task) = graph.get_task(&config_owner_id)
    && owner_task.tags.iter().any(|t| t == "chat-loop" || t == "coordinator-loop")
{
    continue;
}

let reactivated = reactivate_cycle(...);

This is the bandaid until wg-chat-as (chat as first-class entity, no graph involvement at all) lands.

Hard gate

Before claiming done:

  1. Create a fresh chat (wg service create-chat --name foo)
  2. Don't send any messages
  3. Wait 5 minutes
  4. Daemon log MUST show ZERO 'Spawning agent for: .chat-N' lines after the initial spawn
  5. wg agents --alive MUST show at most 1 supervisor for the chat (not 5+)
  6. Dispatch count for the chat task must be 1 (not climbing)

Lessons learned (smoke-gate-is should catch this)

The chat-agent-loops 'done' was a false positive — the agent claimed done without verifying the user-visible spam pattern actually stopped. Same verification-gap class as tui-agent-activity → tui-log-view, agency-picks-claude → agency-still-picks → STILL needed local-providers fix from me. Document this as another scenario in the smoke manifest.

Depends on

Required by

Log