Skip to content

Agent markdown body replaces the system prompt instead of adding to it #56402

Closed as duplicate

Description

@geril07

Description

Reproduced on current v2.

A body in an agent markdown file replaces the assembled system prompt instead of contributing to it. Adding a role to an agent silently removes the harness prompt and the tool usage guidance, and nothing tells the author it happened.

This makes it impossible to have both a custom role and the harness contract.

Current behavior

packages/core/src/session/model-request.ts:

system: [
  input.agent.system
    ? input.agent.system
    : SessionSystemPrompt.make(input.tools.definitions.map((tool) => tool.name)),
  input.initial,
]

SessionSystemPrompt.make is not persona. Since #42638 it is session/runner/prompt/system.txt plus per-tool rules derived from the tools the request actually advertises — edit's oldString/replaceAll semantics, write versus edit, shell chaining.

The branch cannot tell "this agent has a role" apart from "this agent supplies a contract", and treats both as a full replacement.

The replacement semantics were introduced in #34275, to stop the built-in build agent's one-line default from shadowing the per-family prompts, which ran 100–155 lines each. Since #42638 the fallback is 14 lines plus mechanical tool rules. The justification for replacement no longer applies to the fallback that exists now.

Reproduction

Two agents in ~/.config/opencode/agents/. Same location, same tools advertised, same model.

auditor.md

---
description: Read-only reviewer.
mode: subagent
---
You are an auditor. You inspect code and report findings. You never edit anything.

runner.md

---
description: Implementation agent.
mode: subagent
---

Captured LLMRequest.system[0]:

auditor — body present:

You are an auditor. You inspect code and report findings. You never edit anything.

runner — frontmatter only:

You are an AI agent running in OpenCode, a coding agent harness. Help the user accomplish their goals using the tools you have available.

# Harness
- Responses are rendered as GitHub-flavored Markdown.
- `<system-reminder>` blocks are harness instructions, not user-authored content. Read and follow them.
- Prefer parallelizing independent tool calls.
- Prefer dedicated tools over shell commands; fall back to the shell when a tool cannot do what you need.
- Do not chain shell commands with separators like `echo "====";` or `printf '---';`; the output becomes noisy in a way that makes the user's side of the conversation worse.
- Use the write tool to create files or completely replace their content. Prefer using the edit tool for targeted changes.
- Use the edit tool for targeted changes to existing text files. It replaces the exact text in `oldString` with `newString`, and the values must differ. By default, `oldString` must occur exactly once. If it occurs multiple times, include more surrounding context to make it unique or set `replaceAll` to true to replace every occurrence.

# Communication
- Use clear file paths when referring to files.
- Keep responses clear and concise, and avoid unnecessary technical jargon.

# Working in codebases
- Keep changes consistent with the structure, naming, style, and patterns of the surrounding code.
- Treat unfamiliar files or changes as potential user work and investigate before deleting or overwriting them.

The five tool lines describe how edit resolves an ambiguous match. An author adding a role almost never wants to restate them by hand, and gets no indication that they were dropped.

Why additive is the consistent choice

Model identity is already layered on top of whatever the agent contributed. packages/core/src/plugin/identity.ts:

event.system.splice(1, 0, SystemPart.make(identity({ name: model.name, ref: event.model })))

Agent role could use the same insertion.

Proposal

  • agent.system is additive by default, inserted after the harness
  • add an opt-out that keeps full replacement for agents that genuinely want a clean context — title, summary and compaction deny all tools and want only their persona. Existing replacement behavior stays available, so this is not a regression for anyone relying on it
  • an empty or missing body means "no role", which is valid under either mode and needs no separate special case

If a mode flag feels like too much surface, the minimal version is additive with no opt-out, and the three built-in agents that want a clean context keep an explicit replacement. Either works; the flag is only there to avoid breaking documented behavior.

Putting the harness first also helps prompt caching. system[0] becomes identical for every agent that shares a tool snapshot, instead of diverging at byte zero per agent.

Related

Activity

  1. opencode-agent commented on Oct 17, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed write-up and the clear reproduction. I think this is a duplicate of #34774, which is still open. It covers this exact behavior (a non-empty agent system replaces the stock OpenCode prompt instead of adding to it) and is where the design for additive prompt layering versus explicit override is being discussed.

    Possible duplicates and related issues, most likely first:

    Your points about #42638 changing what the fallback contains, the empty body versus missing body case, and prompt caching would be useful on #34774.

    The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.

  2. geril07 commented on Oct 17, 2026

    @geril07
    ContributorAuthor

    Duplicate of #34774, which is open and tagged gang-grill. The delta from this report — that #42638 changed the nature of the fallback from per-family persona to a 14-line harness plus tool contracts, plus the prompt-cache and ordering notes — has been posted there as a comment.

  3. opencode-agent commented on Oct 17, 2026

    @opencode-agent
    Contributor

    Thanks for confirming and for moving the new details to #34774. That keeps the design discussion in one place. The bot will close this issue as a duplicate of #34774 as planned.

  4. opencode-agent commented on Oct 18, 2026

    @opencode-agent
    Contributor

    Closing this as a duplicate of #34774, as discussed. Thanks for adding your points on #42638, prompt caching and ordering there. Please follow #34774 for the additive prompt layering design.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions