Repository navigation
[FEATURE]: Plugin hooks should be able to inject AI-visible messages into conversation context #17412
Description
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
Problem
OpenCode's plugin hooks (tool.execute.before, tool.execute.after, session.idle) can intercept and modify tool calls, but they cannot inject messages into the AI's conversation context. This makes it impossible to build skills that require ongoing behavioral enforcement — the AI simply forgets after a few tool calls, and near-guaranteed forgets after compaction.
Evidence: planning-with-files skill benchmark
The planning-with-files skill enforces a structured 3-file planning pattern (task_plan.md, findings.md, progress.md). On Claude Code, it uses PreToolUse/PostToolUse/Stop hooks to continuously remind the AI. The hooks inject messages the AI sees in conversation — not just intercept tool calls.
Benchmark results (10 parallel subagents, 5 task types, 30 objectively verifiable assertions):
| Metric | With skill + hooks (Claude Code) | Without skill |
|---|---|---|
| Pass rate (30 assertions) | 96.7% (29/30) | 6.7% (2/30) |
| 3-file pattern followed | 5/5 evals | 0/5 evals |
| Blind A/B wins | 3/3 (100%) | 0/3 |
| Avg blind rubric score | 10.0/10 | 6.8/10 |
What happens on OpenCode today
We run this same skill on OpenCode. The SKILL.md loads, the AI starts strong, then:
- After ~5-10 tool calls — the AI "forgets" to update progress.md and findings.md. No PostToolUse hook to remind it.
- After automatic compaction — the planning workflow is ~100% forgotten. The compacted summary doesn't preserve behavioral rules. The AI continues the task but abandons the 3-file pattern entirely.
- When the AI finishes — no Stop hook to check "did you update all planning files?" — it just stops.
We've tried mitigations: AGENTS.md rules, agent.prompt injection for subagents, TodoWrite tracking. None survive compaction reliably.
The gap
| Capability | Claude Code | OpenCode |
|---|---|---|
| Block/modify tool calls | ✅ hooks | ✅ tool.execute.before |
| Inject AI-visible message after tool call | ✅ (stderr → system message) | ❌ |
| Re-activate agent before stopping | ✅ Stop hook (exit 2 → continue) | ❌ (session.idle is fire-and-forget) |
Proposed API
For tool.execute.after — allow injecting a message the AI sees:
"tool.execute.after": async (input, output) => {
if (input.tool === "edit") {
output.inject = [
{ role: "user", text: "Remember to update progress.md with what you just changed." },
]
}
}For session.stopping (per #16598) — allow continuation with injected message:
"session.stopping": async (input, output) => {
output.inject("You haven't updated progress.md yet.");
output.continue();
}Implementation
We've submitted a proof-of-concept PR that implements the tool.execute.after injection side:
#19519 —
feat: allow tool.execute.after hooks to inject AI-visible messages
The implementation is ~57 lines across 2 files:
- Adds an optional
injectfield to thetool.execute.afteroutput type - A
flushInjectedMessages()helper persists injected entries as synthetic user messages (same pattern as existing subtask summary messages) - Handles all three hook call sites: registry tools, MCP tools, and subtask tools
- Fully backward compatible —
injectis optional, existing plugins are unaffected
Why this matters
Skills are OpenCode's strongest differentiator. But any skill requiring behavioral enforcement beyond initial instructions (planning, linting, security guardrails, SOP compliance) degrades severely without message injection. The benchmark data shows a 96.7% → estimated ~30% drop — making an entire category of skills non-viable.
Related
- feat: allow tool.execute.after hooks to inject AI-visible messages #19519 — PR implementing this feature (tool.execute.after injection)
- Native Claude Code hooks compatibility (PreToolUse, PostToolUse, Stop) #12472 — Native Claude Code hooks compatibility (broader scope, same root cause)
- feat: add session.stopping hook for plugins #16598 / [FEATURE]: add session.stopping plugin hook to allow re-entering the agent loop #16626 — Draft PR for
session.stoppinglifecycle event (prerequisite for Stop hook) - [FEATURE]:can implement claude code skills #8846 — Claude Code skills support discussion
Activity
github-actions commentedon Mar 13, 2026
This issue might be a duplicate of existing issues. Please check:
(Note: #12472 and #16626 are already referenced in your issue.)
doomsday616 commentedon Mar 13, 2026
Paging interested parties
Tagging folks from related discussions who may find this relevant:
session.stoppingwork in feat: add session.stopping hook for plugins #16598 / [FEATURE]: add session.stopping plugin hook to allow re-entering the agent loop #16626 is the prerequisite for the Stop hook side of this. Theoutput.inject()+output.continue()API proposed here would build directly on top of thatoutput.inject()pattern would cover your PostToolUse lint-on-edit use casetool.execute.beforecan block the tool today, but injecting a message like "use pastewatch_read_file instead" so the AI actually sees it requires this featureThe core argument: OpenCode's plugin system can already intercept tool calls, but skills that need ongoing behavioral enforcement (planning, linting, security) degrade severely because there's no way to inject reminders the AI actually sees. Compaction makes it worse — behavioral rules from initial skill loading are the first thing lost.
doomsday616 commentedon Mar 13, 2026
🐱 Gentle nudge to the team
Hey OpenCode team — would love to get some eyes on this from the core maintainers:
output.inject()ontool.execute.afteris something that fits the plugin architecture direction.session.stoppingdraft PR (feat: add session.stopping hook for plugins #16598) by @yehudacohen already tackles half of this (the Stop hook side). The other half (PostToolUse message injection) is arguably simpler to implement.output.inject()is feasible within the current hook execution pipeline.This isn't just about one skill — it's about making OpenCode's skill ecosystem competitive for any workflow that needs the AI to stay on track beyond initial instructions. The data shows it's a 10x difference. 🙏
feat(plugin): allow tool.execute.after hooks to inject AI-visible mes…
Arcadi4 commentedon May 27, 2026
Seems like the core problem is already resolved by
experimental.chat.messages.transform. However, I still found the DX and UX undesirable, so I opened a follow-up #29633.github-actions commentedon Jul 27, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.