Summary
My core workflow is orchestrator-style: the main agent plans and breaks work into tasks, then delegates each large modification to a subagent rather than doing the work itself. The TaskCreate → TaskExecute → subagent-per-task flow is exactly the mechanism I want, and the README advertises it. In practice the main agent almost never reaches that path, even with both @tintinweb/pi-subagents (v0.14.2) and @tintinweb/pi-tasks (v0.7.2) loaded and the RPC handshake succeeding. The mechanics work — the model gets steered away from them.
I verified the spawn path end-to-end: protocol versions match (both v2), subagents:ready ↔ checkSubagentsVersion sets subagentsAvailable = true, and TaskExecute → spawnSubagent() → subagents:rpc:spawn → manager.spawn() completes. So this is not an RPC/version bug. It's three interacting prompt-injection/friction points that funnel the model into a stuck loop instead of the delegation flow.
Environment
@tintinweb/pi-tasks 0.7.2
@tintinweb/pi-subagents 0.14.2
- pi host: 0.80.x
The three friction points
1. The system-reminder pushes "do it yourself," not "delegate."
buildSystemReminder() (src/index.ts:95) emits, every 2–4 turns (REMINDER_INTERVAL = 4, ACTIVE_REMINDER_INTERVAL = 2):
"Continue on with the tasks at hand if applicable."
For a workflow whose entire purpose is delegation to subagents, this nudges the main agent to execute the work itself — the opposite of what TaskExecute is for.
2. `agentType` is optional on `TaskCreate` and the reminder never mentions it.
TaskCreate declares agentType as Type.Optional (src/index.ts:578). The every-turn reminder lists task contents but never surfaces agentType. So the main agent routinely creates tasks without agentType, then TaskExecute refuses (src/index.ts:1035):
"#X: no agentType set — create with agentType parameter or update metadata"
The agent then loops trying to repair the task metadata instead of delegating.
3. `TaskExecute.promptGuidelines` blocks the fallback to the `Agent` tool.
src/index.ts:1006-1008:
"Never use the Agent tool for tasks launched via TaskExecute — agents are already running."
Once the model enters the task flow, it over-generalizes this and won't fall back to the plain Agent tool even when TaskExecute refused to spawn. There's no escape hatch.
Net effect
Main agent → steered toward TaskCreate (friction #1) → creates tasks without agentType (friction #2) → TaskExecute refuses (no agentType) → can't fall back (friction #3) → stuck. The intended cool flow is reachable but reliably missed.
Suggested fixes (any one materially helps)
- Default
agentType on TaskCreate — e.g. default to "general-purpose" when omitted. A task without an agentType is currently a dead-end for TaskExecute; defaulting removes the most common refusal. (Or surface agentType in the reminder so the model notices it's missing.)
- Re-scope the anti-Agent guideline — change it from "Never use the Agent tool for tasks launched via TaskExecute" to something scoped to actually-running agents, e.g. "Do not spawn a duplicate Agent for a task already running under TaskExecute." That preserves the dedup intent while leaving the fallback open when TaskExecute refused.
- Make the reminder delegation-aware — when a task has
agentType set, the reminder should steer toward TaskExecute (delegate), not "continue on with the tasks at hand" (execute myself). The [READY — use TaskExecute to start] marker for unblocked agentType tasks is already great; consider suppressing the "continue" line for those tasks so delegation isn't talked over.
Happy to PR any of these if a direction sounds right.
Summary
My core workflow is orchestrator-style: the main agent plans and breaks work into tasks, then delegates each large modification to a subagent rather than doing the work itself. The
TaskCreate→TaskExecute→ subagent-per-task flow is exactly the mechanism I want, and the README advertises it. In practice the main agent almost never reaches that path, even with both@tintinweb/pi-subagents(v0.14.2) and@tintinweb/pi-tasks(v0.7.2) loaded and the RPC handshake succeeding. The mechanics work — the model gets steered away from them.I verified the spawn path end-to-end: protocol versions match (both v2),
subagents:ready↔checkSubagentsVersionsetssubagentsAvailable = true, andTaskExecute → spawnSubagent() → subagents:rpc:spawn → manager.spawn()completes. So this is not an RPC/version bug. It's three interacting prompt-injection/friction points that funnel the model into a stuck loop instead of the delegation flow.Environment
@tintinweb/pi-tasks0.7.2@tintinweb/pi-subagents0.14.2The three friction points
1. The system-reminder pushes "do it yourself," not "delegate."
buildSystemReminder()(src/index.ts:95) emits, every 2–4 turns (REMINDER_INTERVAL = 4,ACTIVE_REMINDER_INTERVAL = 2):For a workflow whose entire purpose is delegation to subagents, this nudges the main agent to execute the work itself — the opposite of what
TaskExecuteis for.2. `agentType` is optional on `TaskCreate` and the reminder never mentions it.
TaskCreatedeclaresagentTypeasType.Optional(src/index.ts:578). The every-turn reminder lists task contents but never surfacesagentType. So the main agent routinely creates tasks withoutagentType, thenTaskExecuterefuses (src/index.ts:1035):The agent then loops trying to repair the task metadata instead of delegating.
3. `TaskExecute.promptGuidelines` blocks the fallback to the `Agent` tool.
src/index.ts:1006-1008:Once the model enters the task flow, it over-generalizes this and won't fall back to the plain
Agenttool even whenTaskExecuterefused to spawn. There's no escape hatch.Net effect
Main agent → steered toward TaskCreate (friction #1) → creates tasks without
agentType(friction #2) → TaskExecute refuses (no agentType) → can't fall back (friction #3) → stuck. The intended cool flow is reachable but reliably missed.Suggested fixes (any one materially helps)
agentTypeonTaskCreate— e.g. default to"general-purpose"when omitted. A task without an agentType is currently a dead-end for TaskExecute; defaulting removes the most common refusal. (Or surfaceagentTypein the reminder so the model notices it's missing.)agentTypeset, the reminder should steer towardTaskExecute(delegate), not "continue on with the tasks at hand" (execute myself). The[READY — use TaskExecute to start]marker for unblockedagentTypetasks is already great; consider suppressing the "continue" line for those tasks so delegation isn't talked over.Happy to PR any of these if a direction sounds right.