{"record":{"id":"f853e7d54432426a","repo":"microsoft/autogen","slug":"multiple-and-not-continuous-system-messages-are-no-f853e7","errorCode":null,"errorMessage":"Multiple and Not continuous system messages are not supported if model_info['multiple_system_messages'] is False","messagePattern":"Multiple and Not continuous system messages are not supported if model_info\\['multiple_system_messages'\\] is False","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-ext/src/autogen_ext/models/openai/_openai_client.py","lineNumber":597,"sourceCode":"        if self.model_info[\"json_output\"] is False and json_output is True:\n            raise ValueError(\"Model does not support JSON output.\")\n\n        if not self.model_info.get(\"multiple_system_messages\", False):\n            # Some models accept only one system message(or, it will read only the last one)\n            # So, merge system messages into one (if multiple and continuous)\n            system_message_content = \"\"\n            _messages: List[LLMMessage] = []\n            _first_system_message_idx = -1\n            _last_system_message_idx = -1\n            # Index of the first system message for adding the merged system message at the correct position\n            for idx, message in enumerate(messages):\n                if isinstance(message, SystemMessage):\n                    if _first_system_message_idx == -1:\n                        _first_system_message_idx = idx\n                    elif _last_system_message_idx + 1 != idx:\n                        # That case, system message is not continuous\n                        # Merge system messages only contiues system messages\n                        raise ValueError(\n                            \"Multiple and Not continuous system messages are not supported if model_info['multiple_system_messages'] is False\"\n                        )\n                    system_message_content += message.content + \"\\n\"\n                    _last_system_message_idx = idx\n                else:\n                    _messages.append(message)\n            system_message_content = system_message_content.rstrip()\n            if system_message_content != \"\":\n                system_message = SystemMessage(content=system_message_content)\n                _messages.insert(_first_system_message_idx, system_message)\n            messages = _messages\n\n        # in that case, for ad-hoc, we using startswith instead of model_family for code consistency\n        if create_args.get(\"model\", \"unknown\").startswith(\"claude-\"):\n            # When Claude models last message is AssistantMessage, It could not end with whitespace\n            messages = self._rstrip_last_assistant_message(messages)\n\n        oai_messages_nested = [","sourceCodeStart":579,"sourceCodeEnd":615,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-ext/src/autogen_ext/models/openai/_openai_client.py#L579-L615","documentation":"Thrown by OpenAIChatCompletionClient when model_info does not opt in to multiple_system_messages and the conversation contains system messages that are not contiguous (a system message appears after a non-system message, leaving a gap). The client automatically merges consecutive system messages into one, but cannot safely reorder or merge system messages interleaved with user/assistant turns, so it raises instead.","triggerScenarios":"Passing a message list like [SystemMessage, UserMessage, SystemMessage] to create/create_stream when model_info lacks multiple_system_messages=True. The check fires when a SystemMessage is found at an index that is not immediately after the previous SystemMessage index.","commonSituations":"Agents that inject a second system prompt mid-conversation (e.g. per-task instructions added after user turns); assembling contexts from multiple modules that each prepend their own SystemMessage; switching from a model that tolerates multiple system messages to one that does not.","solutions":["Merge all system-level instructions into a single SystemMessage at the start of the conversation before calling create","If the target model accepts multiple system messages, set model_info={'multiple_system_messages': True, ...}","Move mid-conversation directives into UserMessage or AssistantMessage content instead of additional SystemMessages"],"exampleFix":"# before\nmessages = [\n    SystemMessage(content=\"You are helpful.\"),\n    UserMessage(content=\"hi\", source=\"user\"),\n    SystemMessage(content=\"Always answer in French.\"),\n]\nawait client.create(messages)\n\n# after\nmessages = [\n    SystemMessage(content=\"You are helpful. Always answer in French.\"),\n    UserMessage(content=\"hi\", source=\"user\"),\n]\nawait client.create(messages)","handlingStrategy":"validation","validationCode":"from autogen_agentchat.messages import SystemMessage\n\ndef merged_system(messages):\n    \"\"\"Collapse ALL system messages into one leading SystemMessage.\"\"\"\n    system = \"\\n\".join(m.content for m in messages if isinstance(m, SystemMessage))\n    rest = [m for m in messages if not isinstance(m, SystemMessage)]\n    return ([SystemMessage(content=system)] if system else []) + rest","typeGuard":"def system_messages_are_continuous(messages) -> bool:\n    idxs = [i for i, m in enumerate(messages) if isinstance(m, SystemMessage)]\n    return idxs == list(range(idxs[0], idxs[0] + len(idxs))) if idxs else True","tryCatchPattern":"try:\n    result = await client.create(messages)\nexcept ValueError as e:\n    if \"multiple_system_messages\" in str(e):\n        result = await client.create(merged_system(messages))\n    else:\n        raise","preventionTips":["Emit exactly one SystemMessage at the top of every conversation your agent builds","Set multiple_system_messages=True in model_info only after verifying the backend accepts it","Add a unit test asserting your message pipeline never interleaves SystemMessages"],"tags":["openai","system-message","validation","message-format"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}