Repository navigation
[FEATURE]: Five session capabilities that exist in core but are unreachable from a plugin #49389
Description
Activity
github-actions commented
on Sep 16, 2026 on Sep 16, 2026 – with GitHub ActionsContributorMore actionsThis issue might be a duplicate of existing issues. Please check:
- [FEATURE]: expose more v2 session APIs to plugins #47229: also requests exposing missing v2 session APIs to plugins, explicitly including
session.compact— the overlap with points 1 and potentially others here is significant - [FEATURE]: Add explicit hidden or ephemeral sessions for plugin background tasks #40863: covers the hidden/ephemeral session use case that depends on
parentIDforwarding andsession.remove(points 2 and 3) - [FEATURE]: Expose delegation metadata (e.g. plugin-assigned category/label) on subagent sessions and message events — plugins cannot surface it anywhere in the runtime UI #44174: requests exposing delegation
metadataon subagent sessions so plugins can surface it at runtime (overlaps with point 5)
It may be worth coordinating with those issues or consolidating, though the specific framing here (forwarding gaps at call sites) is distinct enough that a separate issue is defensible.
- [FEATURE]: expose more v2 session APIs to plugins #47229: also requests exposing missing v2 session APIs to plugins, explicitly including
Another use case for item 1 (
session.compact): a server plugin that keeps idle sessions' prompt caches warm wants to compact the session when its idle window ends, so the first message after a long break doesn't re-send the whole context uncached. It can detect the end of the window but has no way to start the compaction. Idle-time compaction in core is tracked separately in #50777; exposingcompacthere would let a plugin cover it.Reacted by Jakub Jurczak+1 on points 2 and 3.
Use case: a plugin tool,
ask_file, that asks a cheap reader agent about a file in a short-lived session. In V1 I created it withparentID: toolContext.sessionID, so it stayed nested under the caller. In V2 (@opencode/plugin2.0.12) every call creates a root session, and sincesession.removeisn't exposed, the session list fills up with stray reader sessions that can't be cleaned up.ctx.generate.textavoids the session but loses tools, and the built-in subagent tool counts towardsubagent_depth. ForwardingparentIDin the plugin projection (host.ts:519) would fix it.Reacted by Jakub Jurczak+1 for point 3, I create sessions from plugins and would prefer to keep them organized as child sessions like I could in v1.
Reacted by Jakub JurczakCame here as I just converted to v2, and found that a plugin I use which generates subagents in a special way is unable to assign the
parentIdproperty, which severely screws up my session lists.. :)So looking forward to ensuring parentId being used, on new sessions.
+1 on item 3 (
parentIDis not forwarded onsession.create). Live evidence on OpenCode 2.0.18:POST /api/sessionwith{"title": "probe", "parentID": "ses_..."}returns the created session withoutparentID; the field is ignored (and is absent from the request schema).- The plugin projection is the other half:
SessionDomainis aPickthat cannot passparentIDeither. A plugin that creates sessions for delegation can therefore never produce a child session — no subtask row, and no child navigation, which keys off session records'parentID.
Use case: a harness plugin (ODF, a spec-driven Odoo workflow pack) spawns one session per phase through
ctx.session.create/prompt/wait/contextand currently emulates delegation with top-level sessions. We can set a title and emitcontext.progressmetadata, but the sessions stay unlinked and users cannot follow the delegated agent.If item 3 really is a single forwarding change, it unlocks real child sessions for plugin-created delegation without any plugin-side redesign. Item 2 (
session.remove) is valuable for the same flow: a plugin that creates sessions has no cleanup path today.Reacted by Jakub JurczakPR #47745 was created ~3 weeks ago and directly addresses item 3. Looks a little stale but it looks like a very targeted change. It needs attention from maintainers
How do we do that? Poke on discord? @-tag in the PR? Thumbs-up the PR?
..I believe most of the time there's no way to get attention to Issues/PRs until the opencode team themselves encounter the issue. That's my experience for the past 6 months, so I stopped trying.
Discord is the best way currently, github is a bit of a shit storm rn unfortunately, there is a heap of spam that we deal with and it's very difficult to sift through noise. We also have agents try to find high traction things.
We are going to be better tho, we are trying to fix this process.
I only saw this because of someone on discord
Discord is the best way currently, github is a bit of a shit storm rn unfortunately, there is a heap of spam that we deal with and it's very difficult to sift through noise. We also have agents try to find high traction things.
We are going to be better tho, we are trying to fix this process.
I only saw this because of someone on discord
I understand the difficulty of filtering out spam, and I appreciate that you’re working to improve the process. That said, given OpenCode’s scale, I would expect more reliable triage of issues and PRs to bring urgent problems and requests with strong community support to the team’s attention.
You mention that agents are already helping. I believe this is a task AI can support effectively, particularly with newer decision models such as Jev and Solar Decide, but those tools need to translate into a process customers can rely on. Getting an issue noticed should not depend on someone raising it on Discord.
For me, this is about improving not only the product but also the customer-facing processes that build and maintain trust, rather than leave customers feeling ignored or forgotten. I would be more understanding of these limitations in a single-developer tool like Paseo. With a full team and a business behind OpenCode, I think expecting a more reliable triage and communication process is reasonable.
Yeah we are going to work more on that very soon, it's not an acceptable state.
Reacted by Padure Sergio and Jakub JurczakMerged fixes for most of these, I think 2 are left.
- The subagent tool does not pass metadata to the child session. sessions.create is called with parentID, title, agent, model (packages/core/src/tool/plugin/subagent.ts:188). Session.create accepts metadata and the column exists, so the destination is already there — it is simply never populated. Forwarding an optional metadata argument would let a plugin read delegation context from the child's session row instead of parsing it back out of the prompt text. Today the only spawn-time channel is mutating the prompt string.
What are you looking for here exactly? I don't want to add new parameters to a tool... Ideally you can use the session patch instead:
await ctx.session.update({ sessionID, metadata: { phase: "review" }, })I did find a bug in update for plugins but wndering why u cant use this (once it's fixed)
Have a pr for the final one. Prolly will be in next release. All items are addressed by merged fixes, the open pr, and then hopefully the workaround^ is sufficient.
Lmk if anyone has any complaints or concerns here.
Reacted by Jakub JurczakThank you for working on this rekham
Feature hasn't been suggested before.
Describe the enhancement you want to request
Five capabilities exist and work in core, but are unreachable from a plugin because the value is either omitted from the plugin projection or not forwarded internally. Four are a forwarding change at a single call site; the fifth needs a design decision.
All references are
upstream/v2at2cdd938152. We hit these porting three plugins to the v2 API.1.
session.compactis not projected.SessionDomainis aPickofcreate | get | switchAgent | switchModel | prompt | generate | command | synthetic | interrupt | update | move | wait | context(packages/plugin/src/effect/session.ts:126).compactexists on the core interface (packages/core/src/session.ts:422) and is reachable over HTTP. A plugin that owns compaction via thecompactionhook can respond to a fold the host starts, but cannot start one.2.
session.removeis not projected. SamePick. Combined with (3), a plugin that creates sessions has no way to delete them.3.
parentIDis not forwarded onsession.create. Core accepts it — the input is{ location } | { parentID }(packages/core/src/session.ts:91) — but the plugin projection enumerates fields and omits it (packages/core/src/plugin/host.ts:519). Sincelocationis always supplied there, theparentIDarm is unreachable, so every plugin-created session is a root. Removal cascades to children (packages/core/src/session.ts:356), so a parented child would be collected automatically; as it stands, plugin-created worker sessions accumulate with no host-side cleanup path. #40863 describes the create-child-then-delete pattern this prevents.4.
session.generatecannot use a different model. The input is{ sessionID, prompt }(packages/core/src/session.ts:182) and the model is resolved from the session (packages/core/src/session/generate.ts:32).modelis alsoreadonlyon the hook draft (packages/plugin/src/effect/session.ts:63), andpreparenever reads it, so an override attempt fails silently rather than erroring. The use case is running a hidden, non-persisted completion — summarisation, classification — on a cheaper model than the session's. This one is a genuine new input rather than a forwarded field.5. The subagent tool does not pass
metadatato the child session.sessions.createis called withparentID,title,agent,model(packages/core/src/tool/plugin/subagent.ts:188).Session.createacceptsmetadataand the column exists, so the destination is already there — it is simply never populated. Forwarding an optionalmetadataargument would let a plugin read delegation context from the child's session row instead of parsing it back out of the prompt text. Today the only spawn-time channel is mutating the prompt string.parentIDitself is reliable for task-spawned children on both lines, and is the correct join key; the gap is that a plugin can neither set it nor remove what it creates.Happy to open a PR for any subset of these if the shape is agreeable — 1, 2, 3 and 5 look like one-line changes each, and 4 would want a design opinion first.