You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[FEATURE]:Expose instruction provenance in the context hook #60008
I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
Problem
Plugins using the context hook cannot reliably distinguish messages loaded from instruction files from ordinary user messages. OpenCode tracks this information internally, but it is lost when synthetic messages are converted.
The loss happens in packages/core/src/session/runner/to-llm-message.ts (case "synthetic"). Unlike neighboring branches that forward message.metadata — user, assistant, skill, shell and location-switched — this branch returns Message.make({ id, role, content }) without it. The "system" branch also drops metadata, but maps to Message.system(text), which has no metadata parameter.
Proposal
Expose a reliable provenance signal for instruction-file messages without unnecessarily exposing internal file paths. A minimal option would be a marker such as metadata: { source: "instruction" }, with no file paths. A dedicated typed field may provide a stronger API contract.
Tests
Distinguish instruction messages from unrelated synthetic messages.
Verify the signal reaches the context hook.
Preserve existing message conversion behavior.
Verify internal provenance metadata is not unintentionally sent to providers.
Would maintainers prefer a metadata marker or a dedicated typed field?
Thanks for the detailed write-up! You're asking for the plugin context hook to be able to tell which messages came from instruction files (AGENTS.md and similar) and which are ordinary user or synthetic messages, without exposing file paths.
Your reading of the code is correct. The instruction loader (packages/core/src/session/instructions.ts) attaches metadata: { instruction: { paths } } to the synthetic message. The "synthetic" branch in runner/to-llm-message.ts then drops that metadata, so the hook only sees plain user content. Today a plugin could only guess by matching the Instructions from: ... text prefix, which isn't reliable. This needs a change in core rather than a plugin, so I haven't written one.
Maintainers will consider it, including your question about a metadata marker versus a typed field. I can't promise a direction or timeline.
Related issues, though none covers the same request:
Activity
opencodejr commentedon Oct 28, 2026
Thanks for the detailed write-up! You're asking for the plugin
contexthook to be able to tell which messages came from instruction files (AGENTS.md and similar) and which are ordinary user or synthetic messages, without exposing file paths.Your reading of the code is correct. The instruction loader (
packages/core/src/session/instructions.ts) attachesmetadata: { instruction: { paths } }to the synthetic message. The"synthetic"branch inrunner/to-llm-message.tsthen drops that metadata, so the hook only sees plain user content. Today a plugin could only guess by matching theInstructions from: ...text prefix, which isn't reliable. This needs a change in core rather than a plugin, so I haven't written one.Maintainers will consider it, including your question about a metadata marker versus a typed field. I can't promise a direction or timeline.
Related issues, though none covers the same request: