Summary
opencode-mem can create internal structured-output sessions that inherit a normal OpenCode agent and its ordinary tools. If the model calls an ordinary tool instead of StructuredOutput, OpenCode continues the agent loop. Because the plugin does not set an agent, tool restrictions, or a finite step limit, this can lead to an unbounded tool loop, extreme token/cache consumption, and unintended local side effects.
This was observed in a real incident. Sensitive prompts, command bodies, local paths, credentials, and session IDs are intentionally omitted.
Environment
opencode-mem: 2.20.0
- OpenCode: 1.18.4
- OS: Windows
- OpenCode provider/model: DeepSeek /
deepseek-v4-flash
- Triggering features: auto-capture and user-profile learning through the structured-output path
Observed behavior
The internal opencode-mem capture sessions did not terminate after producing structured output. Instead, the model repeatedly selected ordinary agent tools such as bash, read, and memory. Each completed tool result was appended to the session history and caused another model request.
Aggregate evidence from 16 internal capture sessions:
| Metric |
Value |
| Input tokens |
6,608,198 |
| Output tokens |
1,028,838 |
| Cache-read tokens |
2,863,690,880 |
| Share of recorded cache-read usage |
88.54% |
| Share of recorded cost |
81.98% |
The three largest sessions produced 1,570, 984, and 824 effective assistant/tool rounds from a single user message. Across the 16 sessions there were:
- 5,398
bash tool calls
- 39
read calls
- 361
memory searches
- only one observed
StructuredOutput call, which ended in error
Twenty-nine completed shell operations used Out-File against OpenCode state paths. No command bodies or target paths are included here. This means the incident crossed the boundary from resource exhaustion into potential local-state modification.
Relevant implementation behavior
In v2.20.0, the OpenCode structured-output path creates a temporary session and calls session.prompt with a model, system prompt, text part, and format: { type: "json_schema" }, but it does not explicitly set:
- a dedicated internal agent
- a restricted tool set
- a finite step limit
- a total token/tool budget
Source: src/services/ai/opencode-provider.ts
OpenCode 1.18.4 implements JSON-schema output by adding a StructuredOutput tool and setting tool choice to required, while ordinary agent tools remain available. A tool-calls finish continues the session loop, and the default maximum steps are effectively unlimited when the agent does not define one.
Source: packages/opencode/src/session/prompt.ts
This combination allows an internal summarization/profile task to become a general-purpose autonomous tool session. Network stream errors were present but were not the cause: database records show distinct completed tool rounds, not provider-level retries.
Expected behavior
Internal capture/profile-learning sessions should:
- have no access to ordinary tools such as shell, file, task, memory, or question tools;
- allow only the framework structured-output mechanism;
- have a small finite step/time/token budget;
- fail closed if any non-
StructuredOutput tool is requested;
- terminate immediately when structured output fails validation.
Suggested fix
- Create a dedicated least-privilege internal agent or explicitly disable all ordinary tools for these sessions.
- Enforce a finite step limit, timeout, and total tool/token budget at the common
generateStructuredOutput boundary.
- Abort the session if the model requests any tool other than
StructuredOutput.
- Add regression tests where a provider repeatedly requests ordinary tools with changing arguments; verify that execution stops without running them.
- Identify and exclude internal sessions using session metadata rather than prompt-text marker matching.
Safe reproduction outline
- Configure the plugin to use the OpenCode provider path for capture/profile learning.
- Use an OpenCode default agent that exposes ordinary tools.
- Trigger an internal structured-output capture.
- Use a provider response that selects an ordinary tool instead of
StructuredOutput.
- Observe that the tool executes and the session continues unless an external limit stops it.
Mitigation used
Auto-capture was disabled immediately. The plugin was then removed and OpenCode restarted because no released upstream fix covering tool isolation and bounded execution was available at the time of the incident.
Related reports
Issues #162 and #169 involve auto-capture/provider failures, but they do not describe unrestricted tool inheritance, an unbounded agent loop, or token/cache exhaustion.
Summary
opencode-memcan create internal structured-output sessions that inherit a normal OpenCode agent and its ordinary tools. If the model calls an ordinary tool instead ofStructuredOutput, OpenCode continues the agent loop. Because the plugin does not set an agent, tool restrictions, or a finite step limit, this can lead to an unbounded tool loop, extreme token/cache consumption, and unintended local side effects.This was observed in a real incident. Sensitive prompts, command bodies, local paths, credentials, and session IDs are intentionally omitted.
Environment
opencode-mem: 2.20.0deepseek-v4-flashObserved behavior
The internal
opencode-mem capturesessions did not terminate after producing structured output. Instead, the model repeatedly selected ordinary agent tools such asbash,read, andmemory. Each completed tool result was appended to the session history and caused another model request.Aggregate evidence from 16 internal capture sessions:
The three largest sessions produced 1,570, 984, and 824 effective assistant/tool rounds from a single user message. Across the 16 sessions there were:
bashtool callsreadcallsmemorysearchesStructuredOutputcall, which ended in errorTwenty-nine completed shell operations used
Out-Fileagainst OpenCode state paths. No command bodies or target paths are included here. This means the incident crossed the boundary from resource exhaustion into potential local-state modification.Relevant implementation behavior
In v2.20.0, the OpenCode structured-output path creates a temporary session and calls
session.promptwith a model, system prompt, text part, andformat: { type: "json_schema" }, but it does not explicitly set:Source:
src/services/ai/opencode-provider.tsOpenCode 1.18.4 implements JSON-schema output by adding a
StructuredOutputtool and setting tool choice to required, while ordinary agent tools remain available. Atool-callsfinish continues the session loop, and the default maximum steps are effectively unlimited when the agent does not define one.Source:
packages/opencode/src/session/prompt.tsThis combination allows an internal summarization/profile task to become a general-purpose autonomous tool session. Network stream errors were present but were not the cause: database records show distinct completed tool rounds, not provider-level retries.
Expected behavior
Internal capture/profile-learning sessions should:
StructuredOutputtool is requested;Suggested fix
generateStructuredOutputboundary.StructuredOutput.Safe reproduction outline
StructuredOutput.Mitigation used
Auto-capture was disabled immediately. The plugin was then removed and OpenCode restarted because no released upstream fix covering tool isolation and bounded execution was available at the time of the incident.
Related reports
Issues #162 and #169 involve auto-capture/provider failures, but they do not describe unrestricted tool inheritance, an unbounded agent loop, or token/cache exhaustion.