You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
DispatchDaemon.buildTaskPrompt hardcodes workerMode: 'ephemeral' when loading the worker role prompt, regardless of the spawned worker's actual workerMode. Persistent workers therefore receive ephemeral-mode operating instructions, including the explicit directive that contradicts persistent semantics:
Auto-shutdown: After completing or handing off a task, your session ends automatically
Do not check the task queue. Your session ends after closing or handing off your task.
The infrastructure for persistent-worker prompts is already in place. loadRolePrompt correctly routes to persistent-worker.md when workerMode: 'persistent' is passed, and that prompt file exists (packages/smithy/src/prompts/persistent-worker.md). The bug is that the caller doesn't pass the worker's actual mode.
Root cause
// packages/smithy/src/services/dispatch-daemon.ts:2999 (master 0a7052a)privateasyncbuildTaskPrompt(task: Task,workerId: EntityId): Promise<string>{constparts: string[]=[];constroleResult=loadRolePrompt('worker',undefined,{projectRoot: this.config.projectRoot,workerMode: 'ephemeral',// ← hardcoded, never reads agent's actual mode});// ...}
For comparison, loadRolePrompt already does the right thing once told:
And persistent-worker.md exists alongside worker.md in the same directory.
Steps to reproduce
Register a persistent worker: sf agent register worker --name CodeDelivery --worker-mode persistent
Assign it a task: sf task assign --to <worker-id> <task-id>
Once the daemon spawns its session (requires PR Version Packages #8 / komoreka fork for persistent workers to get auto-spawned; or use any path that calls buildTaskPrompt), inspect the spawn args:
ps -ef | grep claude | grep -v grep
# The initial prompt contains: "You are an **Ephemeral Worker** ..."# and "your session ends after closing or handing off your task"
The worker now operates with ephemeral semantics: completes the task, runs sf task complete, and shuts down — defeating the whole point of registering it as persistent.
Proposed fix
Read the worker's workerMode from agent metadata and pass it through:
Other callsites of loadRolePrompt('worker', ...) should be audited the same way. Only the dispatch-daemon hardcodes it; the prompts module itself is correct.
Why this matters
Persistent workers are intended to stay alive across multiple task cycles, picking up newly assigned tasks via inbox messages (processPersistentAgentMessage). Telling them via the role prompt to auto-shutdown after each task defeats that design — they exit normally, then sit idle waiting for either a manual restart or (post-PR #8) the next orphan-recovery cycle to respawn them. The persistent-worker mode loses its main benefit (context continuity) and becomes a more expensive ephemeral worker.
This was uncovered while dogfooding a single-persistent-worker setup (CodeDelivery) against cloudboostup-website. The daemon-spawn fix in komoreka PR #8 made the worker actually start; this issue is the next gap: it starts, but it thinks it's ephemeral.
Summary
DispatchDaemon.buildTaskPrompthardcodesworkerMode: 'ephemeral'when loading the worker role prompt, regardless of the spawned worker's actualworkerMode. Persistent workers therefore receive ephemeral-mode operating instructions, including the explicit directive that contradicts persistent semantics:The infrastructure for persistent-worker prompts is already in place.
loadRolePromptcorrectly routes topersistent-worker.mdwhenworkerMode: 'persistent'is passed, and that prompt file exists (packages/smithy/src/prompts/persistent-worker.md). The bug is that the caller doesn't pass the worker's actual mode.Root cause
For comparison,
loadRolePromptalready does the right thing once told:And
persistent-worker.mdexists alongsideworker.mdin the same directory.Steps to reproduce
sf agent register worker --name CodeDelivery --worker-mode persistentsf task assign --to <worker-id> <task-id>buildTaskPrompt), inspect the spawn args:The worker now operates with ephemeral semantics: completes the task, runs
sf task complete, and shuts down — defeating the whole point of registering it as persistent.Proposed fix
Read the worker's
workerModefrom agent metadata and pass it through:Other callsites of
loadRolePrompt('worker', ...)should be audited the same way. Only the dispatch-daemon hardcodes it; the prompts module itself is correct.Why this matters
Persistent workers are intended to stay alive across multiple task cycles, picking up newly assigned tasks via inbox messages (
processPersistentAgentMessage). Telling them via the role prompt to auto-shutdown after each task defeats that design — they exit normally, then sit idle waiting for either a manual restart or (post-PR #8) the next orphan-recovery cycle to respawn them. The persistent-worker mode loses its main benefit (context continuity) and becomes a more expensive ephemeral worker.This was uncovered while dogfooding a single-persistent-worker setup (CodeDelivery) against
cloudboostup-website. The daemon-spawn fix in komoreka PR #8 made the worker actually start; this issue is the next gap: it starts, but it thinks it's ephemeral.Environment
upstream/master @ 0a7052aassignTaskToWorkerandrecoverOrphanedTask(i.e. the daemon dispatch paths). CLI-spawn (bug: sf agent start spawns claude but doesn't register session with session-manager — agent invisible to daemon #119) has its own bypass issue.Related