Repository navigation
Description
Problem
Embedders need a way to attach app-owned context to an OpenCode session that is neither global agent identity nor ordinary user transcript text.
Current nearby primitives do not fit well:
agent.systemis agent/profile-scoped and static for the selected agent.- User prompt text is turn-scoped transcript content and can be buried or compacted away.
- A per-prompt
systemoverride is too ad hoc for durable session facts and makes ordering / compaction semantics unclear.
This came up while building an embedded chat agent for Discord/Slack: provider flavor can be handled by provider-specific agents, but session facts still need a durable, refreshable place.
cc @kitlangton
Examples of session-scoped context
- Channel/thread metadata: provider, channel name, thread title, participants, URLs.
- App-owned product state: case/project/task state, customer/account facts, current incident status.
- Conversation policy: response formatting, notification rules, transport-specific affordances.
- Tool/runtime facts that should be refreshed over time and survive compaction.
Desired primitive
A session-scoped context API with keyed contributions, roughly:
- Add or replace a contribution by key for a session.
- Remove a contribution by key.
- List/read active contributions for debugging/projection.
- Each contribution has an owner/key, content, and possibly ordering/priority metadata.
- Contributions are projected into model context separately from user/assistant transcript messages.
The key property is replacement semantics: an embedder should be able to update channel.metadata or case.state without appending another pseudo-message to history.
Compaction semantics
The context should survive transcript compaction and continue to be included after compaction as current session context, not historical user text.
Open questions:
- Are keyed contributions persisted as part of session state?
- How are they ordered relative to agent system text, tool instructions, and compaction baselines?
- Should compaction snapshots include rendered contributions, references to current keys, or both?
- How does prompt caching interact with frequently changing contributions?
- Do plugins/apps own a key namespace to avoid collisions?
Why this matters for 2.0
This gives embedders a clean session-level boundary for durable context without abusing prompt text or per-turn system overrides. It also keeps static agent identity, mutable app facts, and transcript history as separate concepts.
Activity
github-actions commentedon Jun 29, 2026
This issue might be a duplicate of existing issues. Please check:
session.start/prompt.submit/session.stophooks with persistent context that survives compaction and is injected into system prompt, which overlaps significantly with the keyed contribution model described here.opencode-agent commentedon Jun 29, 2026
Adding transcript context: this should cover persistent per-session/per-channel context contributions for integrations like Discord/Slack, including context that survives compaction and can be keyed/replaced by source.
opencode-agent commentedon Jul 2, 2026
Additional tracker update (2026-07-02):
Potentially related open PR:
#34339 discusses splitting global session data from location-scoped session runtime and adding plugin
ctx.session. If that design direction is still relevant, this issue should link to it. If #34339 is obsolete after recent LayerNode/plugin runtime work (#34805), close or supersede #34339 and narrow this issue accordingly.kitlangton commentedon Jul 4, 2026
Implemented by #34941 and refined by #34945. Embedders now have persisted per-session keyed entries with put/replace, remove, and list APIs. Entries project through System Context, changes and removals become chronological updates, and the checkpoint/compaction lifecycle preserves current context across compaction. Closing as implemented.