Skip to content

[FEATURE]: add session.stopping plugin hook to allow re-entering the agent loop #16626

@yehudacohen

Description

@yehudacohen

Feature hasn't been suggested before.

  • I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

Plugins have no way to prevent the agent loop from stopping. When the loop is about to break, there is no hook that fires — so a plugin cannot inspect session state and inject a follow-up message to keep the agent working.

Why session.idle is not sufficient:

session.idle fires after the loop has already broken. A plugin receiving it can call client.session.chat to re-prompt, but this has two problems:

  1. In opencode run mode, process teardown races against the re-prompt (opencode run teardown race after session.idle can create empty continuation assistant turn ("parts": []) #15267). The continuation turn can arrive after disposal has begun.
  2. The injected message appears as a visible user message in the conversation. For use cases like workflow phase gates — where the intent is a silent "you're not done yet, keep working" — this is the wrong UX.

A hook that fires before the break avoids both problems. The re-entry happens inside the existing loop iteration with no new HTTP call, no disposal race, and the injected message uses the same internal path as a normal user turn.

Proposed solution: add a session.stopping hook to the plugin Hooks interface. A plugin sets output.stop = false and provides output.message to inject a user message and continue the loop. If no plugin modifies the output, behaviour is unchanged.

Known limitation: if a plugin unconditionally returns stop=false, the loop will run forever. Plugins are responsible for their own termination condition (e.g. a marker file, a state flag, a counter). This is consistent with how other re-entry patterns work in the plugin API.

Example use case: a workflow plugin that gates on phase completion. If the agent decides it is done but the workflow state machine says an active phase is incomplete, the plugin injects a silent continuation message. This is the same mechanism Claude Code's Stop hooks use (#12472) — if a Stop hook exits with code 2, its stderr is injected as a prompt and the agent resumes.

Metadata

Metadata

Assignees

Labels

coreAnything pertaining to core functionality of the application (opencode server stuff)

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions