Skip to content

SystemMessage added after UserMessage causes API errors for models requiring system message first (affected since v3.8.42) #161

@wangvm

Description

@wangvm

I encountered an issue when using LLMTornado with certain LLM models that require the SystemMessage to be placed as the first message in the conversation. The current implementation of SetupConversation adds the system message after appending user input, which violates this requirement and causes API errors.

Specifically, when using the model Jackrong/Qwen3.5-9B-Claude-4.6-Opus-Reasoning-Distilled-v2-GGUF (a fine-tuned Qwen3.5 model), the API returns an error because the system message appears after the user message in the messages array.

Root Cause

In the SetupConversation method, the execution order is:

  1. Load existing conversation history (AddMessagesToConversation)
  2. Append user input (AppendUserInput)
  3. Add system message (AddSystemMessage)

This results in a messages array where system messages may not be at index 0. For models that strictly enforce the system → user → assistant ordering convention, this causes the API request to be rejected.

Affected Code

private static Conversation SetupConversation(TornadoAgent agent, List<ChatMessagePart>? input = null, List<ChatMessage>? messages = null, string? responseId = null, CancellationToken cancellationToken = default)
{
    Conversation chat = agent.Client.Chat.CreateConversation(agent.Options);

    chat.RequestParameters.CancellationToken = cancellationToken;

    chat = AddMessagesToConversation(chat, messages);

    if (input?.Count > 0)
    {
        chat.AppendUserInput(input);
    }

    if (!string.IsNullOrEmpty(responseId))
    {
        chat.RequestParameters.ResponseRequestParameters!.PreviousResponseId = responseId;
    }

    // System message added at the end
    chat.AddSystemMessage(agent.Instructions);

    return chat;
}

Expected Behavior

The system message should be the first message in the conversation. For new conversations, the order should be: SystemMessageUserMessage. For existing conversations, the system message should remain at the beginning of the message array.

Current Behavior

System message is appended after the user input, resulting in an invalid message order for models that enforce the system-first convention.

Steps to Reproduce

  1. Use LLMTornado version v3.8.42 or later.
  2. Configure a TornadoAgent with a model that requires system message first (e.g., Qwen-based models).
  3. Call the agent with any user input.
  4. Observe API error indicating invalid message order.

Environment

Workaround (for users)

For users currently blocked by this issue, a temporary workaround is to ensure that the conversation messages array already contains the system message before calling SetupConversation, by passing it through the messages parameter, and setting agent.Instructions to null or empty to avoid duplicate system messages.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions