OpenCode sessions preserve durable conversational history while assembling the runtime context an agent needs to act correctly in its current environment.
Model Context: The complete model-visible input assembled for one Step, including system instructions, Session History, tool definitions, and step-local additions. Instructions are one component of Model Context, not a synonym for it. Avoid: System Context
Instructions: The opaque algebra of independently refreshable typed instruction sources that render the durable instruction baseline and chronological updates shown to the model. Avoid: Model Context, System Context
Session History: The projected chronological conversation selected for a Step after applying the active compaction and InstructionCheckpoint baseline cutoffs. Avoid: Session Context
Instruction Source: One independently observed typed value within Instructions, represented by a stable namespaced key, JSON codec, loader, pure baseline/update renderers, and an optional removal renderer. Avoid: Prompt fragment
InstructionEntry:
One API-managed, durable, per-Session instruction value. Its slash-free client key maps to the api/<key> Instruction Source key. Entries deliberately render to the model as mechanism-neutral <context> blocks: the model sees session context, not how it was attached.
InstructionDiscovery:
The Location-scoped service that observes ambient global and upward-project AGENTS.md files as one ordered aggregate Instruction Source.
InstructionCheckpoint:
The Session-owned durable instruction baseline, baseline sequence, and Instructions.Applied record used to prepare later Steps.
Instruction Update:
A durable chronological System message published as session.instructions.updated that tells the model the newly effective state of one or more changed Instruction Sources.
Avoid: System notification, raw text diff
Instruction Baseline: The exact joined instruction text stored by InstructionCheckpoint and sent as immutable provider-cache prefix state until completed compaction rebaselines it or Session movement or committed revert resets it. Avoid: Live system prompt
Applied Instructions:
The overwriteable model-hidden Instructions.Applied record in InstructionCheckpoint, containing what the model was last told per Instruction Source.
Unavailable Instruction Source: An expected temporary inability to observe an Instruction Source value; the runtime retains its prior effective state and emits no update, while an unavailable source blocks creation of the first complete Instruction Baseline.
Safe Step Boundary: The point during Step preparation, after prior tool settlement and before durable input promotion, where instruction changes may be admitted chronologically.
Admitted Prompt: A durable user input accepted into the Session inbox but not yet included in Session History.
Prompt Promotion: The durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History.
Step: One logical LLM call spanning pre-flight instruction checkpoint preparation, input promotion, request build, and compaction check; the provider stream; and tool settlement. Avoid: provider turn, turn (unqualified)
Physical Attempt: One actual provider request on the wire in service of a Step; most Steps have one Physical Attempt, while overflow-triggered compaction recovery may give one Step two.
Assistant Turn: A reserved name for the not-yet-modeled unit containing all Steps from prompt promotion until the assistant yields the floor; do not reify it until something durable needs it.
Settlement: The terminal transition for a unit of work: Step and tool settlement are durable, while drain and execution settlement are coordinator-observed.
Execution: One session-scoped coordinator busy period from first wake until idle. An Execution is process-local coordination rather than a durable domain entity.
Session Drain: One process-local execution span that promotes eligible input and runs required Steps until no immediate continuation remains. A Session Drain has no durable identity or transcript boundary.
Model Tool Output: The bounded projection of a Core-executed tool result persisted in Session history and replayed to the model. A tool may shape this projection semantically, but the Tool Registry enforces the final size limit.
Managed Tool Output File: A temporary file created under OpenCode's shared tool-output directory to retain complete output that was too large for Session history.
Model Request Options: Provider-semantic model settings selected from the Catalog and active Session variant before the LLM protocol adapter encodes them for a provider request. Avoid: Request body, wire options
Generation Controls: Provider-neutral sampling and output controls, partitioned from provider semantics and compatibility wire fields when model metadata enters the Catalog.
Native Continuation Metadata: Opaque protocol-shaped data attached to assistant content and required to continue that content natively with a compatible model, such as a reasoning signature or provider-hosted item identifier.
PTY Environment: The host-supplied environment overlay applied by the server when creating a PTY, observed for the request Location and resolved PTY working directory.
OpenCode Client:
The generated Promise and Effect APIs derived from the public HttpApi; Embedded OpenCode shares the Effect API through an in-memory HttpClient against the same router and handlers.
Avoid: Remote client
SDK Contract IR:
The runtime-neutral compiled representation of the authoritative HttpApi, preserving encoded and decoded type projections plus transport metadata so independent SDK emitters can choose their public value model and runtime interpreter.
Embedded OpenCode: A scoped in-process host that structurally extends the OpenCode Client, supplies an in-memory HTTP transport, and exposes additional same-process capabilities directly. Avoid: Local implementation
Page:
A bounded ordered result containing items and opaque previous and next cursor links for navigating the same query in either direction.
Avoid: Response envelope
Instructions.combine(...) preserves caller order and rejects duplicate stable namespaced source keys. The runner loads its producers concurrently, then combines them in its fixed declared order.Instructions.make(...) hides the value type so differently typed sources compose uniformly; its codec compares and stores the value, while pure renderers produce baseline, update, and optional removal text.Instructions.initialize(...) observes composed Instructions once and produces a complete Instruction Baseline with Applied Instructions.Instructions.reconcile(...) observes composed Instructions once and returns either unchanged or one combined chronological update. It never rewrites the baseline.Instructions.rebaseline(...) renders a fresh baseline after completed compaction, recalling previously applied values for sources that are temporarily unavailable.session.instructions.updated.AGENTS.md files and honors OPENCODE_DISABLE_PROJECT_CONFIG for project files.AGENTS.md files toward the Location root are injected once per Session as durable synthetic instruction messages.api/<key> Instruction Source, so adding, replacing, or removing an entry is reconciled at the next Safe Step Boundary.skill tool.TERM and OPENCODE_TERMINAL.HttpClient transport differs.HttpClient.HttpClient from its environment so callers own transport selection, recording, tracing, retries, and tests. Convenience runtimes may provide a fetch transport separately..client property.sessions; whether the stable Session namespace should instead be singular session must be settled before stabilization. Internal server identifiers do not implicitly define public client names.HttpApi is authoritative for shared OpenCode Client capabilities. Codegen compiles its Session group directly; the Effect runtime uses an equivalent Protocol-only projection so generated artifacts remain independent of Core and Server.HttpApi once into an SDK Contract IR. Promise and Effect emitters share endpoint structure and transport metadata without being required to expose identical public values: an emitter may select encoded wire types, decoded domain types, compile-time brands, runtime validation, and its own execution abstraction independently.HttpApiClient. Lighter wire-shaped Effect output remains possible through another emitter policy rather than constraining the shared IR.@opencode-ai/protocol owns Session endpoint construction and middleware placement. Server supplies concrete middleware keys to produce the authoritative build-time API; the client projection supplies transport-only keys without importing Core or Server at runtime.Error subclass identity, preserving discrimination across package copies and realms while remaining structurally aligned with Effect domain errors.ClientError class with a structured reason such as transport failure, unexpected status, unsupported content type, or malformed response. Promise methods reject with either a tagged declared domain failure or ClientError, matching the Effect client's conceptual domain/infrastructure error division.AbortSignal and header overrides. Cancellation and transport metadata do not enter the domain input object; broader interceptor and response-mode APIs remain deferred.AsyncIterable directly rather than a Promise-wrapped stream object. Iteration opens the connection, AbortSignal cancels it, and ending iteration closes the underlying request; the Effect emitter analogously returns Stream directly.AsyncIterable iteration, beginning with its first next() call, rather than during synchronous method construction.AsyncIterable and Effect Stream fail explicitly; live consumers refresh and resubscribe, while durable sequence-based resume remains explicit composition above the generated client.baseUrl, defaults to globalThis.fetch, accepts client-level headers, and merges them with per-call header overrides.baseUrl and obtains HttpClient.HttpClient from the Effect environment. It does not install fetch or duplicate per-call transport policy; callers transform/provide the client for headers, tracing, retries, recording, and tests, while fiber interruption owns cancellation.@opencode-ai/client behind isolated root and /effect exports. The root has no runtime path to Effect; /effect imports only Effect, Schema, and Protocol.@opencode-ai/sdk-next, which will assume the existing @opencode-ai/sdk name after legacy consumers migrate. Client remains network-only and SDK depends one-way on Client.HttpRouter in memory. It opens no listener and performs no network I/O, while preserving Server routing, middleware, codecs, handlers, and errors.HttpApi; embedded-only same-process capabilities extend Embedded OpenCode separately.sessions.log({ sessionID, after, follow }) is the public durable Session event stream. It verifies the Session, replays durable events after the optional aggregate sequence, optionally continues with newly committed durable events, excludes live-only fragments, and is transported as SSE in both networked and embedded modes.events.subscribe() is a distinct public instance-wide live stream for Session and non-Session activity. It has no replay guarantee and includes connection, heartbeat, and instance-disposal lifecycle events; consumers recover from disconnection by refreshing authoritative state.events.subscribe(): instance-wide live events and durable Session events have different schemas, replay guarantees, cursors, lifecycle events, and failure behavior.events.subscribe() is bounded to the connected OpenCode instance or workspace; any future cross-instance administrative stream requires a separately designed API.events.subscribe() does not automatically reconnect after transport loss. The live-only stream fails with ClientError; consumers refresh authoritative state before explicitly opening a new subscription because events missed during disconnection cannot be replayed.sessions.log({ sessionID, after, follow }) returns the generated HTTP client's cold durable event stream and does not build reconnection policy into the endpoint or client constructor. Transport loss fails the stream with ClientError. Callers may compose an explicit resuming stream above it by retaining the last observed durable sequence and opening a new subscription with after; any reusable resume helper remains a separate API design question.sessions.list(...) design returns a Page in both networked and Embedded OpenCode; embedded execution does not define a separate unbounded array-returning list operation. The beta client currently preserves the existing HTTP { data, cursor } envelope until emitter-level Page projection is implemented.sessions.messages(...) returns a Page and uses the same cursor discipline as sessions.list(...): the initial request supplies sessionID, ordering, and page size; continuation supplies sessionID plus only an opaque branded message cursor carrying ordering, page size, direction, and message anchor. Using a cursor with another Session is invalid.sessions.message({ sessionID, messageID }) is a required resource lookup. An unknown Session fails with SessionNotFoundError; a known Session with an absent or differently owned message fails with MessageNotFoundError without disclosing cross-Session ownership. Absence is not represented as undefined across the public HTTP boundary.sessions.interrupt({ sessionID }) first verifies that the durable Session exists, failing with SessionNotFoundError otherwise. For a known Session, interruption is idempotent: idle, already-settled, or locally unowned execution is a no-op.sessions.active() snapshots the current process's foreground Session drain registry as a record of Session IDs to { type: "running" }. Missing IDs are inactive; background subagents and tasks do not make their parent Session active, and process restart clears the registry.sessions.context({ sessionID }) preserves the existing message-only operation. It returns projected Session History; it does not include or represent the complete Model Context, whose system text, Instruction Baseline, tools, and step-local additions remain separate.sessions.prompt(...) exposes resume?: boolean. Omitting it preserves durable admission followed by an advisory execution wake; resume: false requests durable admit-only behavior.sessions.prompt(...); SessionPending.admit is the internal primitive, while the public Admission result and resume option express its durable admission semantics.sessions.create(...) accepts an optional location. Omission resolves through the connected OpenCode instance's default or current location; an explicit value selects a known location. Networked and embedded transports use the same handler semantics.sessions.switchAgent({ sessionID, agent }) is part of the common client alongside sessions.switchModel(...). It affects subsequent Session activity and fails with SessionNotFoundError for an unknown Session.OPENCODE_DISABLE_PROJECT_CONFIG; global instructions remain eligible.outputPaths field.Semantic values that mean the same thing internally and publicly live in the lightweight Schema leaf. Core consumes Schema for domain behavior; Protocol composes Schema values into paths, payloads, envelopes, errors, cursors, and streams; Server imports both, hosts Protocol's exact groups, and owns protocol/domain adaptation. The root Promise client remains zero-Effect, /effect depends on Effect plus Schema and Protocol, and @opencode-ai/sdk-next composes the scoped in-process host above Client, Core, and Server.
Shared public records are plain objects declared with Schema.Struct. A same-name inferred interface gives object records readable TypeScript signatures without constructors, prototypes, or nominal identity; unions retain explicit type aliases.
Before stabilizing the client API:
session versus the current beta sessions) and use an explicit codegen annotation if the consumer name should differ from the server group identifier.@opencode-ai/client and @opencode-ai/client/effect bundles through import-boundary tests.Dev: "The date changed while the session was active. Should the Instruction Update say what the old date was?" Domain expert: "No. Emit the newly effective date so the agent can act on the current instructions."
experimental.chat.system.transform can mutate assembled system text arbitrarily, but V2 plugins do not yet expose an equivalent hook. Decide separately whether to port it, model dynamic uses as explicit Instruction Sources, or narrow its semantics.