anomalyco / anomalyco/opencode

Prompt tool list diverges from the runtime registry mid-session — no MCP mutation involved

Open
#48,214 6 comments 0 reactions 1 assignee View on GitHub

@neriousy is already working on this.

Since Sep 9, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

DESCRIPTION:
I believe this is related to but broader than #39902. Our divergence happens with no MCP mutation involved.

What I observed (production, headless opencode serve 1.18.25, systemd, multi-tenant): a session works for one batch of tool calls, then the next batch resolves nothing — the prompt still lists ~27 tools, the model emits tool calls, and every call answers "No such tool available". Built-ins (bash, read, glob) and plugin tools alike, zero log lines. A second occurrence: a freshly created session's first batch was already collapsed. Four occurrences total in one week, two in a single day. Restarting the server does not repair the broken session; a new session works.

Why I think it's not #39902: no MCP add/remove/connect/disconnect happened in any occurrence. The session's own tool registry appears disposed mid-life — the prompt's tool list (built from cached instance state) and the runtime resolution (live registry) silently diverge.

Suggested direction: build the prompt's tool list from the live registry at request-build time, so a disposed registry produces a visibly consistent prompt (zero tools) or a loud error — never a declaration the runtime cannot resolve.

Two related observations from instrumenting this: a plugin throw in chat.params is swallowed entirely (the turn completes with an empty assistant message, no 500, no log); the tool.definition hook input carries no sessionID.

PLUGINS:
A handful of in-house plugins (tool permission guards and instrumentation hooks). No third-party plugins.

OPENCODE VERSION:
1.18.25 (headless opencode serve)

STEPS TO REPRODUCE:
I have not found a deterministic repro — the loss appears transient. What I can offer is the observation context and a way to catch it:

Environment: headless opencode serve 1.18.25 behind systemd, several concurrent sessions (dispatch/sub-agent sessions, multi-step tool turns).

Observed shape: a session's tool batch succeeds, then a later batch in the SAME session answers "No such tool available" for every tool the model calls — while the prompt still lists the tools. Once in this state the session stays broken; a new session works.

Instrumentation that catches it: a plugin hooking tool.definition counts the tool definitions sent per LLM step; the count drops to zero exactly when the loss occurs (healthy steps stream ~10-30 definitions). If a maintainer wants, I can share the minimal plugin and the exact hook-firing order I measured (chat.message once per user message; tool.definition and chat.params per step).

SCREENSHOT AND/OR SHARE LINK:
No response

OPERATING SYSTEM:
Linux (Ubuntu-based server, headless)

TERMINAL:
Headless server deployment via systemd (opencode serve), accessed over HTTP API and browser UI only.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.