Skip to content

feat(opencode-agents): render agent instruction templates - #182

Merged
apucacao merged 1 commit into
mainfrom
cursor/opencode-render-instructions-d425
Oct 20, 2026
Merged

apucacao merged 1 commit into
mainfrom
cursor/opencode-render-instructions-d425

Conversation

@apucacao

@apucacao apucacao commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Decision

Render {{variables}} in non-system config messages with parse_template. History and the user turn stay raw. Instruction rendering, including the judge prompt, is already on #179, which is merged to main.

Why

Configured messages were posted with placeholders still in them. The other handlers render those messages. History and the latest user turn are already concrete text.

What this PR does not do

  • It does not treat the model resolver as a writer of config["instructions"]. ModelResolver only returns a provider id and a model id.
  • It does not add a messages-mode route.
  • It does not change the session lifecycle from feat(opencode-agents): open one OpenCode session per call #179.
  • It does not choose the AI Config key.

Next

Observability #2547 passes base_url to create_opencode_handler. This PR's base is main.

Open in Web Open in Cursor 

@apucacao
apucacao requested a review from jeffdupont October 19, 2026 20:33
@cursor
cursor Bot force-pushed the cursor/opencode-render-instructions-d425 branch from 8a74e40 to 62fb13a Compare October 19, 2026 20:57
@apucacao
apucacao marked this pull request as ready for review October 19, 2026 21:49

@jeffdupont jeffdupont left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — rendering once in the handler matches the runner contract ("the handler owns the single parse_template pass") and the claude/langchain/openai handlers. A couple of things worth addressing, non-blocking:

  1. Resolver-override claim in the docstring (handler.py:694-695): it says rendering happens after the model resolver "so a caller system-prompt override written onto config is what gets rendered", but ModelResolver is Callable[[dict], tuple[str, str]] and nothing writes config["instructions"]. That only works if a custom resolver mutates its input — an undocumented side effect with no test. If downstream relies on it, please make it an explicit contract (documented on ModelResolver + a test where the resolver writes config["instructions"] = "Override {{x}}"), or preferably a dedicated override param; otherwise drop the claim.

  2. Configured messages aren't rendered (_user_prompt, handler.py:704-735): non-system config["messages"] go through compose_history without parse_template, unlike claude-agents (handler.py:369,388) and openai-agents (handler.py:178). Since collapse_messages_to_instructions leaves messages intact when instructions is set, "Assist {{caller_email}}" would reach OpenCode literally. Render config messages (keeping history/user input raw), or document that agent mode doesn't template them.

  3. Tests: consider covering variables=None, nested {{user.name}}, an unknown placeholder left intact, and that set_input_content_attributes receives the rendered text.

Note this should land before (or with) #179, which removes the skip_judges guidance.

@cursor
cursor Bot force-pushed the cursor/opencode-render-instructions-d425 branch from 62fb13a to fabccbd Compare October 20, 2026 16:46
@cursor

cursor Bot commented Oct 20, 2026

Copy link
Copy Markdown

Addressed in fabccbd. Left unmerged because the base is still #179.

  1. Dropped the claim that the model resolver writes config["instructions"]. Nothing in this package does that, and it is not part of ModelResolver.
  2. Non-system config messages go through parse_template. History and the user turn stay raw.
  3. Tests cover variables=None, nested {{user.name}}, an unknown placeholder left intact, and gen_ai.system_instructions seeing the rendered text.

OpenCode tests: 44 passed.

@cursor
cursor Bot force-pushed the cursor/opencode-render-instructions-d425 branch from fabccbd to 1513cf1 Compare October 20, 2026 18:41
@cursor
cursor Bot force-pushed the cursor/opencode-completion-prompts-d425 branch from c8d2911 to 491939d Compare October 20, 2026 19:10
@cursor
cursor Bot force-pushed the cursor/opencode-render-instructions-d425 branch 2 times, most recently from ef5e3fd to 76210d8 Compare October 20, 2026 20:33
Base automatically changed from cursor/opencode-completion-prompts-d425 to main October 20, 2026 20:35
Non-system config messages go through parse_template. History and the
user turn stay raw. The resolver is not a place that writes instructions.
@cursor
cursor Bot force-pushed the cursor/opencode-render-instructions-d425 branch from 76210d8 to 804822b Compare October 20, 2026 20:36
@apucacao
apucacao merged commit 83175aa into main Oct 20, 2026
7 checks passed
@apucacao
apucacao deleted the cursor/opencode-render-instructions-d425 branch October 20, 2026 20:40
@github-actions github-actions Bot mentioned this pull request Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants