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
This was initially reported as #1466 and automatically closed because this repository uses Discussions as the public intake channel. Reposting here under Bug reports per CONTRIBUTING.md.
Summary
After a TUI session replacement (/new or /resume), the replacement AgentSession loses the controllers provided through the original sessionOptions. As a result, agent_message.* host handlers are not registered in the replacement kernel.
The Python module remains importable, but its host request fails:
RuntimeError: host request type "agent_message.list_agents" is not available in this session
A fresh RLM child in the affected session fails similarly when calling agent_message.send(...) and ends as completed_without_reply.
Environment
Prime Agent: 0.7.2
Node.js: 24.14.0
Mode: daemon + TUI
OS: Windows 11 / WSL2 Ubuntu
Reproduced after a clean machine reboot with a single healthy daemon
Also reproducible on upstream main by source inspection at 2c34b82
The installed 0.7.2 dist matches the corresponding upstream tag in the affected paths. No local Prime Agent core modifications are present.
Reproduction
Start Prime Agent in daemon/TUI mode.
Run /new in the TUI. (/resume has the same affected replacement boundary.)
The child gets the equivalent host-request-unavailable error. The parent later receives completed_without_reply, not the intended business reply.
Expected behavior
Replacement sessions should retain the same host-request capabilities as the initial daemon session:
agent_message.list_agents
agent_message.send
other controller-backed handlers such as agent_observe and rlm_heartbeat
A child should be able to send its reply after /new, /resume, fork, or JSONL import, and retained parent-to-child follow-ups should remain available.
Source-level cause
At v0.7.2 and current main:
packages/coding-agent/src/core/kernel/index.ts throws host request type "..." is not available in this session when the requested key is absent from hostHandlers.
AgentSession._createKernelHostHandlers() registers agent_message.* only when _agentMessageController exists and the skill is visible.
_agentMessageController is assigned only from config.agentMessageController in the AgentSession constructor.
The daemon injects that controller through the initial runtime's sessionOptions.
AgentSessionRuntime.switchSession() and newSession() construct a replacement runtime with cwd, agentDir, sessionManager, sessionStartEvent, and sessionConfig, but do not preserve or pass the original sessionOptions.
TUI /new uses daemon new_session; TUI /resume uses daemon switch_session. The replacement AgentSession therefore has _agentMessageController === undefined, so the new kernel omits agent_message.* handlers.
The relevant agent-session-runtime.ts, agent-session.ts, and agent-messages.ts paths are unchanged between v0.7.2 and main at 2c34b82.
Preserve sessionOptions in AgentSessionRuntime and pass them through every replacement-runtime constructor path:
newSession()
switchSession()
fork
JSONL import
Alternatively, re-inject the current daemon state controllers at the replacement boundary. Re-importing the Python module is not sufficient because the missing capability is in the Node host-handler map.
Suggested regression coverage
For both /new and /resume:
agent_message.list_agents() succeeds.
A fresh child sends a parent reply through agent_message.send().
Parent-to-retained-child follow-up returns delivered or queued.
The retained child sends a second reply.
No completed_without_reply notice is emitted for a child that attempted a valid reply.
The same capability-preservation assertion should cover fork/import replacement paths and the other controller-backed handlers.
Follow-up: narrowed fix direction, reproduction precondition, and regression evidence
I dug deeper into this after posting and want to (a) correct the suggested fix, (b) add a reproduction precondition, and (c) share regression evidence.
1. Still present on current main. Verified by source inspection at the current main head (941d7b3, 2026-08-17): AgentSessionRuntime.switchSession(), newSession(), fork() (all three branches), and importFromJsonl() build the replacement runtime with cwd, agentDir, sessionManager, sessionStartEvent, and sessionConfig — none pass sessionOptions to createRuntime. AgentSession assigns the three controllers only from the creation config, and _createKernelHostHandlers() registers agent_message.*/agent_observe.*/rlm_heartbeat.* only when the corresponding controller is present (plus the skill-visibility check below). The daemon injects all three controllers at runtime creation (initial session, subagent spawn, and subagent rehydration), never in the replacement methods. The replacement commands (new_session, switch_session, fork, import_jsonl) route to those methods, so the replacement session has no controllers. The affected paths (agent-session-runtime.ts, agent-session.ts, agent-messages.ts, agent-observe.ts) are byte-identical between the v0.7.2 tag and current main, so the report applies unchanged to both.
No merged PR fixes this, and the open PRs I checked do not overlap: #1389 refactors the same fork() region but does not touch sessionOptions/controllers (worth coordinating with on merge); #1357 and its base branch are about host-request dispatcher internals (revocation/admission), not session replacement; #1243 was closed without merging. #1280 and Issue #1374 (resume lifecycle), plus #597 (family surface), are related but do not restore the controllers.
2. Correction: do not propagate all of sessionOptions. My original suggestion was too broad. sessionOptions also carries session-specific state — model, thinkingLevel, scopedModels, tools, autonomous config, and so on — which must not be blindly copied into a replacement session (e.g. switching to a session with a different model/tools should keep the target's settings). The minimal direction is to carry only the three daemon-owned controllers through the replacement factories: agentMessageController, agentObserveController, rlmHeartbeatController. Concretely: pick those three fields from the original sessionOptions when constructing the runtime, and pass the picked object as sessionOptions in each of the six replacement createRuntime call sites (switchSession, newSession, fork ×3 branches, importFromJsonl). Everything else stays as-is.
3. Reproduction precondition.agent_message.* handlers are registered only when BOTH conditions hold: the controller is present AND the bundled agent-message skill is visible to the session. If the skill is not visible (e.g. built-in skills disabled or overridden), the same RuntimeError appears even in a fresh session — that is a different failure. A valid reproduction of THIS bug must therefore prove initial GREEN (the handlers work before the replacement) and then show the same calls fail after the replacement. My repro and tests follow that order.
4. Regression evidence. I finalized a Vitest suite (11 cases) covering this regression. Coverage: each replacement family (newSession, switchSession, fork, JSONL import) probes agent_message.list_agents, a parent-addressed structured final reply via agent_message.send, agent_observe.list_agents, and rlm_heartbeat.list before and after the replacement, plus a negative control (an unknown host request still fails with the same "not available" error); the daemon switch_session command path; controller-backed child final behavior (a fresh child delivers its structured final reply after replacement, no completed_without_reply notice, retained parent→child follow-up and a second child reply both work); both fork branches; and an assertion that the replacement factory receives exactly the three controller keys and nothing else — locking in the minimal direction above. An accepted historical RED run against the v0.7.2 base recorded 8 failed / 3 passed for an 11-case suite with this same case taxonomy (the failures are the capability/replacement cases; the passing cases are fixture hygiene); the finalized suite with the three-controller pick applied passes 11/11. A single-environment smoke test of the patched build found that after /new, /resume, fork, and JSONL import all three controller-backed handlers remained available, and a fresh child delivered a structured final reply with no completed_without_reply; this is not upstream CI.
5. Request. Could a maintainer confirm this matches your understanding of the replacement boundary, and whether the three-controller pick is the right shape? Per CONTRIBUTING.md I will not open a PR without an invitation. If this is useful, I can prepare the change plus the regression suite on a clean branch once invited, and I will adjust placement/scope to your conventions. If an equivalent fix is already in flight, please point me at it and I will stand down.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
This was initially reported as #1466 and automatically closed because this repository uses Discussions as the public intake channel. Reposting here under Bug reports per
CONTRIBUTING.md.Summary
After a TUI session replacement (
/newor/resume), the replacementAgentSessionloses the controllers provided through the originalsessionOptions. As a result,agent_message.*host handlers are not registered in the replacement kernel.The Python module remains importable, but its host request fails:
A fresh RLM child in the affected session fails similarly when calling
agent_message.send(...)and ends ascompleted_without_reply.Environment
0.7.224.14.0mainby source inspection at2c34b82The installed
0.7.2dist matches the corresponding upstream tag in the affected paths. No local Prime Agent core modifications are present.Reproduction
/newin the TUI. (/resumehas the same affected replacement boundary.)Actual result:
The child gets the equivalent host-request-unavailable error. The parent later receives
completed_without_reply, not the intended business reply.Expected behavior
Replacement sessions should retain the same host-request capabilities as the initial daemon session:
agent_message.list_agentsagent_message.sendagent_observeandrlm_heartbeatA child should be able to send its reply after
/new,/resume, fork, or JSONL import, and retained parent-to-child follow-ups should remain available.Source-level cause
At
v0.7.2and currentmain:packages/coding-agent/src/core/kernel/index.tsthrowshost request type "..." is not available in this sessionwhen the requested key is absent fromhostHandlers.AgentSession._createKernelHostHandlers()registersagent_message.*only when_agentMessageControllerexists and the skill is visible._agentMessageControlleris assigned only fromconfig.agentMessageControllerin theAgentSessionconstructor.sessionOptions.AgentSessionRuntime.switchSession()andnewSession()construct a replacement runtime withcwd,agentDir,sessionManager,sessionStartEvent, andsessionConfig, but do not preserve or pass the originalsessionOptions./newuses daemonnew_session; TUI/resumeuses daemonswitch_session. The replacementAgentSessiontherefore has_agentMessageController === undefined, so the new kernel omitsagent_message.*handlers.The relevant
agent-session-runtime.ts,agent-session.ts, andagent-messages.tspaths are unchanged betweenv0.7.2andmainat2c34b82.Related but not equivalent work:
/resumelifecycle behavior but do not restore these controllers.Suggested fix
Preserve
sessionOptionsinAgentSessionRuntimeand pass them through every replacement-runtime constructor path:newSession()switchSession()Alternatively, re-inject the current daemon state controllers at the replacement boundary. Re-importing the Python module is not sufficient because the missing capability is in the Node host-handler map.
Suggested regression coverage
For both
/newand/resume:agent_message.list_agents()succeeds.agent_message.send().deliveredorqueued.completed_without_replynotice is emitted for a child that attempted a valid reply.The same capability-preservation assertion should cover fork/import replacement paths and the other controller-backed handlers.
All reactions