OpenHands / OpenHands/software-agent-sdk

Ensure a system message always precedes the first user message in LLM requests

Open
#5,144 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

invariants
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 for system (→ instructions) and a dict list for user (→ input). Sending steering instructions as a lone user message conflates "how" with "what", and a lone system message would serialize to instructions with empty input.
  • 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.