Summary
When a cron job has sessionTarget: "isolated" but targets a non-cron session key (e.g. agent:main:kos:thread:... or agent:main:kos:space:...), the heartbeat prompt ("Read HEARTBEAT.md...") is injected into the system prompt. The agent then reads HEARTBEAT.md and responds with unrelated tasks, polluting the thread/space.
Root Cause
In src/agents/pi-embedded-runner/run/attempt.ts at line ~1651:
heartbeatPrompt: isDefaultAgent
? resolveHeartbeatPrompt(...)
: undefined,
isDefaultAgent is true because the session key resolves to agent:main (the default agent). resolvePromptModeForSession() returns "full" because isCronSessionKey() checks for a cron: prefix in the session key rest — but kOS thread/space keys use kos:thread:... / kos:space:..., so they don't match.
The params.trigger value IS "cron" (passed from cron/isolated-agent/run.ts:603), but it's never checked at the heartbeat injection site.
Proposed Fix
heartbeatPrompt: isDefaultAgent && params.trigger !== "cron"
? resolveHeartbeatPrompt(...)
: undefined,
This suppresses heartbeat injection for all cron-triggered embedded agent runs, regardless of session key shape.
Workaround
Set agents.defaults.heartbeat.session: "main" in config to pin heartbeat runs to agent:main:main.
Generated with Claude Code
Summary
When a cron job has
sessionTarget: "isolated"but targets a non-cron session key (e.g.agent:main:kos:thread:...oragent:main:kos:space:...), the heartbeat prompt ("Read HEARTBEAT.md...") is injected into the system prompt. The agent then reads HEARTBEAT.md and responds with unrelated tasks, polluting the thread/space.Root Cause
In
src/agents/pi-embedded-runner/run/attempt.tsat line ~1651:isDefaultAgentistruebecause the session key resolves toagent:main(the default agent).resolvePromptModeForSession()returns"full"becauseisCronSessionKey()checks for acron:prefix in the session key rest — but kOS thread/space keys usekos:thread:.../kos:space:..., so they don't match.The
params.triggervalue IS"cron"(passed fromcron/isolated-agent/run.ts:603), but it's never checked at the heartbeat injection site.Proposed Fix
This suppresses heartbeat injection for all cron-triggered embedded agent runs, regardless of session key shape.
Workaround
Set
agents.defaults.heartbeat.session: "main"in config to pin heartbeat runs toagent:main:main.Generated with Claude Code