Stalled indicators (Agent Teams model):
- TeammateIdle event received but no completion message or blocker was sent via
SendMessage - Task status in
TaskListshowsin_progressbut noSendMessageactivity from the teammate - Teammate process terminated without sending a completion message or blocker via
SendMessage
Detection is event-driven: check at signal monitoring points (after dispatch, on TeammateIdle events, on SendMessage receipt). If a teammate goes idle without sending a completion message or blocker, treat as
stalled immediately — UNLESS the idle plausibly postdates a wake-signal you just
sent or the task carries a live intentional_wait: those idles are
delivery-ordering artifacts, not stalls. Apply the one-redundant-confirm rule in
pact-completion-authority.md
and escalate to stall diagnosis only on task-file-mtime plus sustained-silence
evidence.
Relationship to agent state model: Stall detection is the binary endpoint (active vs. stalled). For finer-grained mid-execution assessment (converging/exploring/stuck), see the agent state model in pact-variety.md. An agent assessed as "stuck" via progress signals may stall if not intervened upon.
- Check the teammate's
TaskListstatus and any partial task metadata orSendMessageoutput for context on what happened - Mark the stalled agent task as
completedwithmetadata={"stalled": true, "reason": "{what happened}"} - Assess: Is the work partially done? Can it be continued from where it stopped?
- Create a new agent task and spawn a new teammate to retry or continue the work, passing any partial output as context
- If stall persists after 1 retry, emit an ALERT algedonic signal (META-BLOCK category)
Include in agent prompts: "If you encounter an error that prevents completion, send a message via SendMessage describing what you completed and store a partial HANDOFF in task metadata rather than silently failing."
When an agent cannot complete normally (stall, failure, or unresolvable blocker), mark its task as completed with descriptive metadata:
Metadata: {"stalled": true, "reason": "..."} | {"failed": true, "reason": "..."} | {"blocked": true, "blocker_task": "..."}
Convention: All non-happy-path terminations use completed with metadata — no failed status exists. This preserves the pending → in_progress → completed lifecycle.