Draft Issue: Split System Prompt & System Reminder for Better Context Management
Status: Draft for review - Not yet submitted
What happened?
Currently, Qwen Code conflates two distinct types of system instructions:
- System Prompt: Long-lived base instructions (capabilities, constraints, guidelines)
- System Reminders: Dynamic, contextual information (subagent availability, plan mode, arena sessions)
Both are processed differently but sent to the LLM in a way that can cause confusion and hallucination:
- System Prompts are sent as API-level
systemInstruction
- System Reminders are sent as user message content (prepended to user query)
Additionally, the core instruction tells the model that <system-reminder> tags "are NOT part of the user's provided input" — but since reminders are injected into the user message space, the model may not properly distinguish system instructions from user intent.
What did you expect to happen?
A clear separation between:
-
System Prompt (base instructions): Sent as true system-level instruction
- Capabilities and constraints
- User guidelines and preferences
- Tool usage policies
- Dynamic examples that only include tools in the active toolset
-
System Reminder (dynamic context): Also sent at system level
- Subagent availability
- Current mode (plan mode, arena)
- Todo list changes
- Session state
- Available tools list to prevent hallucinated tool calls
This would ensure:
- Clear semantic hierarchy between instructions
- Better model adherence to system-level guidance
- Reduced hallucination from instruction confusion (e.g., examples won't reference unavailable tools)
- More predictable behavior across conversation turns
- A mechanism to explicitly tell the model which tools ARE available
Why is this needed?
- Reduces Hallucination: When system reminders are injected into user message space, the model may treat them as user requests rather than authoritative instructions
- Improves Context Clarity: Clear distinction helps the model understand what is system directive vs. contextual information
- Better Instruction Hierarchy: Base prompt instructions should take precedence over dynamic reminders — this is harder to ensure when both are in user message space
- Debuggability: When something goes wrong, it's easier to trace which instruction type influenced the behavior
Concrete Hallucination Example
The system prompt contains example patterns showing tool usage:
<example>
user: Run the build and fix any type errors
assistant: I'm going to use the ${ToolNames.TODO_WRITE} tool to write the following items...
When a tool like write_file appears in examples but is not registered in coreTools, the LLM may still attempt to call it based on the example pattern. This results in hallucinated tool calls that will never succeed.
The problem:
- System prompt includes examples using
${ToolNames.WRITE_FILE}
- If
write_file is not in the active toolset, the call fails
- The model continues trying despite failures
- User experience degrades
Root cause: Examples in system prompts don't automatically adapt to the current toolset - they're static text that can mislead the model.
Additional context
Current Architecture
System Prompt Flow:
Config.getSystemPrompt() / QWEN_SYSTEM_MD
↓
Sent as API systemInstruction
System Reminder Flow:
In sendMessageStream() - client.ts
↓
Prepended to user message content
↓
Sent as user message (NOT system instruction)
Key Code Location
In packages/core/src/core/client.ts:606-642:
requestToSent = [...systemReminders, ...requestToSent];
// Reminders are added to user message, not system instruction
Example Problem Scenario
- System prompt says: "Always confirm with user before executing destructive commands"
- A system reminder indicates: "Plan mode is active — do not execute yet"
- User says: "Go ahead and delete everything"
- Because the reminder is in user message space, the model may deprioritize it over the user's explicit "go ahead"
Labels
type/feature-request
status/needs-triage
area/context-management
Draft Issue: Split System Prompt & System Reminder for Better Context Management
What happened?
Currently, Qwen Code conflates two distinct types of system instructions:
Both are processed differently but sent to the LLM in a way that can cause confusion and hallucination:
systemInstructionAdditionally, the core instruction tells the model that
<system-reminder>tags "are NOT part of the user's provided input" — but since reminders are injected into the user message space, the model may not properly distinguish system instructions from user intent.What did you expect to happen?
A clear separation between:
System Prompt (base instructions): Sent as true system-level instruction
System Reminder (dynamic context): Also sent at system level
This would ensure:
Why is this needed?
Concrete Hallucination Example
The system prompt contains example patterns showing tool usage:
When a tool like
write_fileappears in examples but is not registered incoreTools, the LLM may still attempt to call it based on the example pattern. This results in hallucinated tool calls that will never succeed.The problem:
${ToolNames.WRITE_FILE}write_fileis not in the active toolset, the call failsRoot cause: Examples in system prompts don't automatically adapt to the current toolset - they're static text that can mislead the model.
Additional context
Current Architecture
Key Code Location
In
packages/core/src/core/client.ts:606-642:Example Problem Scenario
Labels
type/feature-requeststatus/needs-triagearea/context-management