OpenHands / OpenHands/software-agent-sdk
Ensure a system message always precedes the first user message in LLM requests
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.1k
- Forks
- 539
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 137
Description
Summary
This is a tracking issue for a repo-wide invariant: every LLM request built in this repository must place a system message before the first user message.
The main agent loop already enforces this via Agent.init_state() (openhands-sdk/openhands/sdk/agent/agent.py) — it guarantees the SystemPromptEvent sits at index 0/1 and raises AssertionError if a user message appears before it. Standalone LLM calls (condenser, goal judge, pre-flight pings, security analyzers) do not all follow the same rule today.
Why it matters
- Consistent model steering: standalone calls that omit a system message lose the shared context/format expectations other paths get.
- Correct transport serialization: on the OpenAI Responses API,
Message.to_responses_value()returns a string forsystem(→instructions) and a dict list foruser(→input). Sending steering instructions as a loneusermessage conflates "how" with "what", and a lonesystemmessage would serialize toinstructionswith emptyinput. - Subscription/Codex transport prepends system chunks onto the first user message; a missing system lead-in produces a bare, unsteered request.
Subissues
- #5142 — Condenser summarization: split into system + user (PR #5143)
- #5145 — Goal judge: split judge prompt into system + user messages
- #5146 — Agent-server profile pre-flight ping: prepend a system message
- #5147 — GraySwan analyzer: guarantee system message first when history window drops the SystemPromptEvent
- #5148 — Condenser: ensure the SystemPromptEvent is never forgotten (keep_first=0 / summary-first edge case)
- #5149 — Condenser hard context reset: preserve the leading system prompt instead of summarizing it at offset 0
- #5150 — Document the invariant (this pattern, as a repo convention)
Each subissue must add (or verify) a system message before the first user message in the request it builds.
This issue was created by an AI agent (OpenHands) on behalf of juanmichelini.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Agent.init_state() in openhands-sdk/openhands/sdk/agent/agent.py and review the linked subissues #5145–#5150 for the standalone request paths they identify. Check each condenser, goal judge, pre-flight, and GraySwan request, plus the documentation task, to verify a system message precedes the first user message and that relevant tests pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- ai, backend
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100