Skip to content

plugin hooks fire for subagents, so you can correct them mid-task #41304

Description

@semanticRig

What I found

OpenCode subagents share their parent's plugin hooks. The tool.execute.after hook fires for every subagent session. It receives the session ID and the tool output. And it can mutate that output before the model sees it.

This means you can splice a correction into a running subagent's context mid-turn. No daemon, no polling, no bash tool that the model might skip. The hook fires deterministically.

How it works

The operator writes a message to a maildir spool (new/ directory). The plugin hook, running on every tool.execute.after, checks the spool, atomically moves the message to cur/, and appends it to the tool output text. The language model sees it on its next reasoning step:

⚠️ [SESSION-BUS] Messages:
  [cto→qa-agent]!! [correction]: Use bcrypt not sha256 for password hashing

The maildir gives crash-safe delivery without any locks. A message being written stays in tmp/. Once fully written and synced, an atomic rename puts it in new/. The reader atomically renames it to cur/ when delivered. Kill the process at any point and you either get the message or you do not. Partial reads are impossible.

The code

Working implementation at https://github.com/semanticRig/cross-session-agent-messaging

About 500 lines total: a Python core library for the spool, a TypeScript plugin for the injection hooks, and MCP server wrappers for the tools. Tested on OpenCode 1.18.15 with 10 parallel subagents.

Honest limitations

  • The hook fires after a tool call. If the subagent emits a final answer with no further tool call, the message lands on the next tool turn, not retroactively.
  • Delivery is at-least-once. A crash between the rename into new/ and the move to cur/ can double-deliver. The message ID handles deduplication.
  • This uses an undocumented hook contract. The payload shape can change between OpenCode versions.

Why this matters

Claude Code added agent teams in 2.1.224. You can correct a subagent mid-task from another terminal. OpenCode has no equivalent. But the plugin system makes it possible to build one with remarkably little code.

I wrote up the technical details and the discovery process at the repo linked above. Would love feedback, especially from anyone who has worked with the plugin API internals. If there is a better hook for this or a documented contract I missed, let me know.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions