Skip to content

fix(opencode): stop repeated cross-turn tool loops - #165

Open
robertelee78 wants to merge 1 commit into
pacphi:mainfrom
robertelee78:fix/opencode-cross-turn-tool-loop
Open

fix(opencode): stop repeated cross-turn tool loops#165
robertelee78 wants to merge 1 commit into
pacphi:mainfrom
robertelee78:fix/opencode-cross-turn-tool-loop

Conversation

@robertelee78

@robertelee78 robertelee78 commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Why this belongs in Agentic Kit

OpenCode 1.18.18 checks for repeated tool calls only among parts attached to the current assistant message. A normal tool result starts another assistant continuation, so the same completed call can repeat across assistant messages without reaching the native detector. Interleaved reasoning or text can also mask its same-message tail check.

This is not an hf2q inference responsibility: the server does not reliably know whether OpenCode executed a tool or what result the client delivered. Agentic Kit already owns and receipt-deploys the OpenCode lifecycle adapter through ak sync, and that adapter observes user turns plus tool.execute.before and tool.execute.after. It is therefore the narrow, upgrade-resistant place for an immediate compatibility guard while OpenCode core remains unchanged.

Native detector source: https://github.com/anomalyco/opencode/blob/v1.18.18/packages/opencode/src/session/processor.ts

The open upstream proposal scans matching calls across the whole compacted history, which would also count legitimate nonconsecutive calls. This guard intentionally does not copy that behavior: anomalyco/opencode#32089

Behavior

  • Track only the trailing streak of completed calls within one session and one user turn.
  • Fingerprint the tool name, recursively canonicalized JSON arguments, and exact completed output.
  • Allow three identical completed calls, then abort the session before a fourth identical execution.
  • Reset on a changed tool, arguments, output, or new user message; isolate sessions from each other.
  • Preserve the streak across assistant continuations, reasoning/text parts, and compaction.

The session abort is deliberately fail-closed because the fourth execution may repeat a side effect. This can stop an intentional polling loop if it returns the exact same output three times; changing output or beginning a new user turn resets the guard. The workaround should be removable after OpenCode ships an equivalent turn-scoped, tested core fix.

Changes

  • Add the bounded guard to the managed ruflo-hooks.js template.
  • Document the host-adapter contract in README and ADR-0017.
  • Add six regressions for cross-assistant detection, canonical argument keys, changed-call/output reset, user/session isolation, and the wired abort path.

Validation

  • node --test tests/kit/opencode-hooks.test.mjs
  • pnpm run typecheck
  • pnpm run lint
  • pnpm run build
  • GitHub CI passed across Ubuntu, macOS, and Windows on Node 22, 24, and 26, plus quality, links, and the maintainer devcontainer build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant