The final user message is a composed blob rather than the user's message #104

Closed
opened 2026-08-11 08:42:42 +00:00 by coilyco-ops · 0 comments
Member

The last user message sent to the model is not what the user said. It is a composed string:

Recent #bots conversation, oldest first:

Current summoned message:
manual test: OLIVE CHECK: reply with just the word olive.

The user typed the last line. Everything above it is scaffolding, plus a manual test: prefix added by the HTTP turn path.

What is and is not structured

Worth being precise, because the messages array is used correctly in one place and not another. Measured over 12 hours of captured requests:

  • 40 requests carry "role":"assistant" and 40 carry "role":"tool". Tool rounds are represented properly, with the assistant's tool-call turn and the tool results as their own messages.
  • Conversation history is not. It is flattened into the same user message as the current turn, under a Recent #bots conversation, oldest first: header.

So this is not a claim that the harness ignores the messages array. It is specifically the history and the summoned message sharing one turn.

Why it matters

The canonical user message is unreadable downstream. Anything reading "what did the user ask" gets the scaffolding too. That includes agentproxy.user_message, added in coilyco-flight-deck/agent-proxy#85 precisely so consumers would not have to parse the body, and it is what the ser8 console displays today.

Tokens are spent describing structure the protocol already provides. Header lines, the ordering note, and the Current summoned message: marker are all overhead on every turn.

The model cannot tell turns apart by role. Prior bot replies inside that blob are indistinguishable from member text except by whatever formatting the composer used.

The counterargument, which is real

A Discord channel is multi-party. History is several different humans plus the bot, and OpenAI's user and assistant roles cannot express "which human". The optional name field exists but is inconsistently honoured across providers.

So flattening history may be a deliberate and correct choice. This issue should not be read as "put history in the messages array" unless someone has checked that the multi-party case survives it.

The narrower fix, which stands either way

Whatever representation history needs, the final user turn should contain only the user's message.

Move the history block and its headers into the system message, or into a separate preceding turn, and leave the summoned message clean. That fixes the downstream read without touching the multi-party question.

The manual test: prefix should also not be inside the user's text. It is transport metadata.

  • #102 proposes removing the issue field from the response envelope. Same shape of problem at the other end of the turn: the harness composing structure into a field that should carry only content.
  • #86 is the completion-budget failure. Prompt overhead is not its cause, tool-result inflation is, but this adds to the same budget.
The last `user` message sent to the model is not what the user said. It is a composed string: ``` Recent #bots conversation, oldest first: Current summoned message: manual test: OLIVE CHECK: reply with just the word olive. ``` The user typed the last line. Everything above it is scaffolding, plus a `manual test:` prefix added by the HTTP turn path. ## What is and is not structured Worth being precise, because the messages array is used correctly in one place and not another. Measured over 12 hours of captured requests: * **40 requests carry `"role":"assistant"` and 40 carry `"role":"tool"`.** Tool rounds are represented properly, with the assistant's tool-call turn and the tool results as their own messages. * **Conversation history is not.** It is flattened into the same `user` message as the current turn, under a `Recent #bots conversation, oldest first:` header. So this is not a claim that the harness ignores the messages array. It is specifically the history and the summoned message sharing one turn. ## Why it matters **The canonical user message is unreadable downstream.** Anything reading "what did the user ask" gets the scaffolding too. That includes `agentproxy.user_message`, added in coilyco-flight-deck/agent-proxy#85 precisely so consumers would not have to parse the body, and it is what the ser8 console displays today. **Tokens are spent describing structure the protocol already provides.** Header lines, the ordering note, and the `Current summoned message:` marker are all overhead on every turn. **The model cannot tell turns apart by role.** Prior bot replies inside that blob are indistinguishable from member text except by whatever formatting the composer used. ## The counterargument, which is real A Discord channel is **multi-party**. History is several different humans plus the bot, and OpenAI's `user` and `assistant` roles cannot express "which human". The optional `name` field exists but is inconsistently honoured across providers. So flattening history may be a deliberate and correct choice. This issue should not be read as "put history in the messages array" unless someone has checked that the multi-party case survives it. ## The narrower fix, which stands either way Whatever representation history needs, **the final user turn should contain only the user's message.** Move the history block and its headers into the system message, or into a separate preceding turn, and leave the summoned message clean. That fixes the downstream read without touching the multi-party question. The `manual test:` prefix should also not be inside the user's text. It is transport metadata. ## Related * #102 proposes removing the `issue` field from the response envelope. Same shape of problem at the other end of the turn: the harness composing structure into a field that should carry only content. * #86 is the completion-budget failure. Prompt overhead is not its cause, tool-result inflation is, but this adds to the same budget.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo#104
No description provided.