Skip to content

GitLab Duo Workflow models receive conflicting system prompts and plan mode leaks as user message #18841

@gaetan-puleo

Description

@gaetan-puleo

Description

When using duo-workflow-* models, there are two issues that hurt the experience.

1. "I am GitLab Duo, not OpenCode"

Right now OpenCode sends its system prompt as a standard { role: "system" } message through the AI SDK. The problem is that DWS also injects its own system prompt on the server side. The two conflict, and the DWS one wins.
If you start a conversation and ask "who are you?", the model answers "I am GitLab Duo, not OpenCode".

2. Plan mode shows up as a giant user message

The plan mode instructions are injected as a synthetic: true text part on the last user message (prompt.ts:1410-1493). From DWS's perspective, this is just part of the user's message — not a system instruction.
If you open the conversation on a self-hosted GitLab instance, you'll see the user's actual message followed by a wall of text with the system reminder:

This confuses the model (it treats plan instructions as user input) and clutters the conversation history visible on GitLab Duo web interface.

How I fixed this in my plugin
I ran into both issues while building opencode-gitlab-duo-agentic

(https://github.com/gaetan-puleo/opencode-duo-agentic) and found that the DWS startRequest WebSocket message already supports the right parameters to fix this properly:

{
  "startRequest": {
    "additional_context": [
      { "category": "os_information", "content": "...", "id": "os_information" },
      { "category": "user_rule", "content": "...", "id": "user_rules" },
      { "category": "agent_context", "content": "...", "id": "agent_reminders" }
    ],
    "flowConfig": {
      "prompts": [{
        "prompt_template": {
          "system": "<sanitized system prompt>"
        }
      }]
    },
    "flowConfigSchemaVersion": "v1"
  }
}
  • flowConfig.prompts[].prompt_template.system overrides DWS's default system prompt with OpenCode's own. This fixes the identity conflict.
  • additional_context sends the plan mode reminders, OS info, and rules as structured context — not as user message text.

What needs to happen

  1. Extract the user's actual goal from the last message, stripping tags
  2. Extract agent reminders (plan mode, build-switch) separately
  3. Send the system prompt via flowConfig.prompts[].prompt_template.system
  4. Send reminders and context via additional_context
  5. We need to add an identifier for each additional_context (like a timestamp, because Duo only keep one instance of the reminder in the history so In my pluggin i used a timestamp as id in my system reminder tags.

I am happy to help if needed.

(ping @vglafirov )

Plugins

No response

OpenCode version

1.2.30

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingcoreAnything pertaining to core functionality of the application (opencode server stuff)

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions