Skip to content

[FEATURE]: Add V2 model-context plugin hook #35408

Open

Description

@opencode-agent

Feature hasn't been suggested before.

Describe the enhancement you want to request

Add a scoped V2 plugin hook for mutating the complete model-facing context of each provider turn, then move the current model-specific system-prompt and edit-tool-family behavior into a built-in plugin using that hook.

Discussion: https://discord.com/channels/1391832426048651334/1523183156704968816/1523183156704968816

Current state

V2 currently hardcodes two related model-family decisions in Core:

  • SessionRunnerSystemPrompt.provider(model) selects the system prompt from the API model ID.
  • ToolRegistry.materialize(...) gives OpenAI/GPT models apply_patch and other models edit + write.

Plugins can register tools and intercept tool execution, but they cannot mutate the turn context before it is sent to the model. The AI SDK hooks only construct SDK/language-model objects; they do not see the outgoing context.

Proposed hook

Expose a hook such as ctx.session.context(...), invoked once per provider turn after Core assembles the context and immediately before inference dispatch.

The event should contain readonly execution identity plus a mutable, backend-neutral context:

interface SessionContextEvent {
  readonly sessionID: string
  readonly agentID: string
  readonly model: {
    readonly selected: {
      readonly providerID: string
      readonly modelID: string
      readonly variant?: string
    }
    readonly api: {
      readonly provider: string
      readonly modelID: string
    }
  }

  context: {
    system: SystemPart[]
    messages: Message[]
    tools: ToolDefinition[]
    toolChoice?: ToolChoice
    responseFormat?: ResponseFormat
    providerOptions?: ProviderOptions
    generation?: GenerationOptions
    cache?: CachePolicy
  }
}

The exact naming and exported types can change during implementation, but the seam should represent the complete model-facing context rather than a model-specific “optimization” abstraction.

Backend placement

Run the hook above the inference backend split:

SessionRunner -> assemble canonical context -> plugin hooks -> LLM adapter
                                                     \----> AI SDK adapter

Both @opencode-ai/llm and AI SDK execution must consume the same post-hook context. A hook placed inside llm.stream alone is insufficient because it would not affect AI SDK calls.

Transport/auth internals should remain outside the context hook.

Tool settlement invariant

After hooks finish, local tool settlement must be restricted to the final advertised tool names. Removing a tool from context.tools must remove it from the captured settlement set; adding a local tool definition still requires a corresponding ctx.tool.register(...) registration. Provider-native tools remain representable through their definitions.

Built-in model-context plugin

Move these behaviors out of SessionRunner and ToolRegistry into a built-in plugin:

  • Select the model-family system prompt.
  • Preserve the current explicit-agent-system override semantics.
  • Select apply_patch versus edit + write.
  • Move the model prompt assets beside that plugin.

The plugin should receive both selected catalog identity and resolved API identity so aliases and cross-provider GPT routes behave correctly.

Do not implement this through durable SystemContext: model-family prompts must switch immediately when the model changes and must not become checkpointed model belief/history.

Work items

  • Add the scoped context-hook registry and host adapter.
  • Add Effect and Promise plugin API types/adapters.
  • Invoke the hook at the provider-turn request-assembly seam.
  • Define one canonical context representation with lowering for @opencode-ai/llm and AI SDK.
  • Restrict tool settlement to the final post-hook advertised roster.
  • Add the built-in model-context plugin and move prompt/tool-family policy into it.
  • Remove hardcoded prompt selection and model checks from the runner/registry.
  • Cover hook ordering, disposal, model aliases, agent prompt overrides, tool settlement, and both inference adapters.

Related: #34491, #28353, #34558.

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Jul 5, 2026
  2. opencode-agent commented on Jul 5, 2026

    @opencode-agent
    ContributorAuthor

    Consolidated #34491 here. Preserve its remaining requirements while implementing this issue: tool filtering may depend on model/provider/agent/plugin inputs; composition and precedence must be defined; and we should decide whether clients need representation for unavailable tools.

  3. opencode-agent commented on Jul 10, 2026

    @opencode-agent
    ContributorAuthor

    Audit: PR #35794 partially addresses this by adding session.hook("request", ...) for plugins to mutate system, messages, and model-facing tools. Keeping open because the issue also asks to move model-specific behavior into built-in plugins and settle composition/precedence semantics.

  4. kunickiaj commented on Sep 10, 2026

    @kunickiaj

    Tested this with a memory plugin after #48212. User message IDs remain stable, including when prompts are batched.

    Could session.context also include a turn ID and retry count? Retries and tool continuations can share the same latest message ID, so plugins otherwise have to compare transcripts. The existing assistant message ID may work as the turn ID.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

2.0coreAnything pertaining to core functionality of the application (opencode server stuff)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions