fix(opencode): use instructions array, not agent.build.prompt#60
Merged
fix(opencode): use instructions array, not agent.build.prompt#60
Conversation
Setting agent.build.prompt/agent.plan.prompt in opencode.json puts the
custom prompt at the top of system[1], pushing OpenCode's canonical
`<environment>…Skills provide specialized instructions…` opening down.
Anthropic's third-party-app detector fingerprints the first bytes of
system[1] on Claude Max OAuth requests. When the canonical opening is
missing, it routes the request to extra-usage billing and returns 400:
{"error":{"type":"invalid_request_error",
"message":"Third-party apps now draw from your extra usage,
not your plan limits. Add more at
claude.ai/settings/usage and keep going."}}
This blocks every Opus-tier Claude Max request the moment the user
attaches any memory file via agent.build.prompt, even if the file is
tiny (repro: 251-byte USER.md still breaks).
Fix: emit a top-level `instructions` array instead. OpenCode loads each
path through Instruction.system() (packages/opencode/src/session/
instruction.ts), appending them with the `Instructions from: <path>`
prefix *after* the canonical opening — the same mechanism that
auto-discovers AGENTS.md. The OAuth flow stays intact and memory is
preserved end-to-end.
Also drops the now-unused OPENCODE_PROMPT builder in
runtime_discover_dm_paths (AGENTS.md auto-discovery covers the root
file; memory files ride the instructions array).
Verified on intelligence-chubes4 (Kimaki 0.6.0 + opencode 1.14.20):
- agent.build.prompt with {file:} includes → 400 on opus-4-7
- instructions array with same paths → 200 OK, full memory in context
This was referenced Apr 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Switch
runtimes/opencode.shaway from emittingagent.build.prompt/agent.plan.promptwith a{file:}-bundle, and over to a top-levelinstructions: [...]array.Root cause
Setting
agent.build.promptinopencode.jsonputs our custom prompt at the very top ofsystem[1]in the outgoing Anthropic request, which pushes OpenCode's canonical<environment>…Skills provide specialized instructions…opening down.Anthropic's third-party-app detector fingerprints the first bytes of
system[1]on Claude Max OAuth requests. When the canonical opening isn't the first thing, the request is routed through extra-usage billing and returns HTTP 400:This bricks every Opus-tier Claude Max request the moment any memory file is attached via
agent.build.prompt, even a tiny one (repro: 251-byteUSER.mdis enough).Tied to remorses/kimaki#99 — Kimaki 0.4.101 fixed the system-prompt sanitization for its request path, but wp-coding-agents' hand-written
agent.build.promptbypasses the sanitizer's anchor and re-breaks it.Fix
runtime_generate_config()now emits"instructions": ["./path1", "./path2", ...]from$DM_AGENT_FILES. OpenCode loads each path throughInstruction.system()inpackages/opencode/src/session/instruction.tsand appends them with theInstructions from: <path>prefix after the canonical opening — the same mechanism that auto-discoversAGENTS.md. OAuth flow stays intact; memory is preserved end-to-end.Also drops the now-unused
OPENCODE_PROMPTbuilder inruntime_discover_dm_paths(AGENTS.md auto-discovery covers the root file; memory files ride the instructions array).Test plan
agent.build.prompt = "{file:./AGENTS.md}\n{file:...}"on live intelligence-chubes4 (Kimaki 0.6.0, opencode 1.14.20)opencode.jsonon the live site → 200 OK, full memory in context (AGENTS.md + SITE.md + RULES.md + SOUL.md + USER.md + MEMORY.md all present in system[])bash -n runtimes/opencode.shsetup.shproducesopencode.jsonwithinstructionsarray, noagentblock🤖 Generated with Claude Code