MoonshotAI / MoonshotAI/kimi-code
Restored session permanently loses tool/subagent access when its persisted runtime binding is stale (acp-runtime-after-reap)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
Bug
A session whose persisted agent runtime binding references a runtime that the current process never registers becomes permanently unable to execute tools or spawn subagents after being restored. Every tool call and subagent spawn fails with:
runtime acp:session_<id> does not exist in workspace <id>
The agent still converses (model calls need no runtime), but cannot act. Restarting turns or re-seeding does not help — only creating a brand-new session escapes.
Root cause
AgentRuntimeBindingService's restore hook (packages/agent-core-v2/src/agent/runtimeBinding/runtimeBindingService.ts) replays a persisted {workspaceId, runtimeId} binding back into state without checking that the runtime exists. RuntimeRegistry is purely in-memory per process. So when a session that was previously driven via kimi acp (binding persisted as acp:<sessionId> by bindSessionRuntime) is later resumed in a host that never registers ACP runtimes — the TUI, kap-server, or headless kimi -S <id> -p — the restored binding points at a runtime id that will never exist in that process:
- runtime-gated tools (Bash, Read, Write, …) stay deactivated because availability probes return false, and
IAgentRuntimeService.acquire()throwsruntime.not_foundfor every subagent spawn and any tool that does run.
Note that validating the binding at restore time is not a correct fix: in the healthy ACP flow, agent scope restore runs before bindSessionRuntime registers the session's ACP runtime (wireSession in packages/acp-server/src/server.ts), so restore-time acquisition would break the normal resume path.
Reproduction
- Create a session over ACP (
kimi acp+session/new), so the main agent's binding persists asacp:<sessionId>. - Resume the same session in a non-ACP host, e.g. headless:
kimi -S <sessionId> -p "…". - Ask the agent to spawn a subagent → fails with
runtime acp:session_<id> does not exist in workspace <id>; runtime-gated tools are missing from the toolset.
Proposed fix
Heal lazily at the point of use: in AgentRuntimeService.inspect()/acquire()/isAvailable() (packages/agent-core-v2/src/agent/runtimeBinding/agentRuntime.ts), catch RuntimeError with code runtime.not_found, rebind the agent to the always-present local runtime via IAgentRuntimeBindingService.set() (which persists the durable RuntimeSetBinding event), and retry once. Runtimes that are registered but unavailable (disconnected/draining) never trigger the heal; if the fallback is also missing, the original error is rethrown with the fallback failure attached as cause.
PR with the fix + unit tests follows, linked to this issue.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/agent-core-v2/src/agent/runtimeBinding/agentRuntime.ts and trace inspect(), acquire(), and isAvailable() against AgentRuntimeBindingService.set(). Review the restore hook in packages/agent-core-v2/src/agent/runtimeBinding/runtimeBindingService.ts and ACP registration through wireSession in packages/acp-server/src/server.ts. Done means stale runtime.not_found bindings heal to local without healing registered-but-unavailable runtimes, and unit tests cover the retry and fallback error paths.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100