{"record":{"id":"abaea475475129dc","repo":"microsoft/autogen","slug":"system-message-has-already-been-set-and-only-one-s","errorCode":null,"errorMessage":"system message has already been set and only one system message is supported. \"system\" role for input messages in the Message","messagePattern":"system message has already been set and only one system message is supported\\. \"system\" role for input messages in the Message","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/AutoGen.Anthropic/Agent/AnthropicClientAgent.cs","lineNumber":90,"sourceCode":"            Tools = _tools?.ToList(),\n            ToolChoice = _toolChoice ?? (_tools is { Length: > 0 } ? ToolChoice.Auto : null),\n            StopSequences = options?.StopSequence?.ToArray(),\n        };\n\n        chatCompletionRequest.Messages = BuildMessages(messages);\n\n        return chatCompletionRequest;\n    }\n\n    private List<ChatMessage> BuildMessages(IEnumerable<IMessage> messages)\n    {\n        List<ChatMessage> chatMessages = new();\n        foreach (IMessage? message in messages)\n        {\n            switch (message)\n            {\n                case IMessage<ChatMessage> chatMessage when chatMessage.Content.Role == \"system\":\n                    throw new InvalidOperationException(\n                        \"system message has already been set and only one system message is supported. \\\"system\\\" role for input messages in the Message\");\n\n                case IMessage<ChatMessage> chatMessage:\n                    chatMessages.Add(chatMessage.Content);\n                    break;\n\n                default:\n                    throw new ArgumentException($\"Unexpected message type: {message?.GetType()}\");\n            }\n        }\n\n        // merge messages with the same role\n        // fixing #2884\n        var mergedMessages = chatMessages.Aggregate(new List<ChatMessage>(), (acc, message) =>\n        {\n            if (acc.Count > 0 && acc.Last().Role == message.Role)\n            {\n                acc.Last().Content.AddRange(message.Content);","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/dotnet/src/AutoGen.Anthropic/Agent/AnthropicClientAgent.cs#L72-L108","documentation":"AutoGen.Anthropic's AnthropicClientAgent.BuildMessages throws InvalidOperationException when an input message contains a ChatMessage whose Role == \"system\". The agent already injects the system message (from its systemMessage parameter) at the top of the Anthropic request, and the Anthropic API allows only one system prompt, so a second system-role message in the conversation history is rejected client-side.","triggerScenarios":"Sending an IMessage<ChatMessage> with Content.Role == \"system\" in the messages enumerable to AnthropicClientAgent (directly or via a group chat that replays history); using RegisterMessageConnector and re-sending the agent's own stored chat history that includes a system entry; two agents in a group chat where one emits system-role messages.","commonSituations":"Porting OpenAI sample code to Anthropic while keeping system messages inline in the message list; group-chat middleware that prefixes every turn with a system instruction; replaying a persisted conversation log that recorded the initial system prompt as a regular message.","solutions":["Remove system-role messages from the input list; put the instruction in the agent's systemMessage constructor parameter instead.","If you aggregate history, filter before sending: messages.Where(m => !(m is IMessage<ChatMessage> c && c.Content.Role == \"system\")).","In multi-agent flows, have other agents speak as \"user\"/\"assistant\" (or AutoGen TextMessage), never \"system\".","Upgrade AutoGen.Anthropic if a newer version tolerates/merges system messages instead of throwing."],"exampleFix":"// before\nvar agent = new AnthropicClientAgent(client, \"assistant\", systemMessage: \"You are helpful.\");\nawait agent.SendAsync(new MessageEnvelope<ChatMessage>(new ChatMessage { Role = \"system\", Content = [new TextContent { Text = \"Always answer briefly.\" }] })); // throws\n\n// after\nvar agent = new AnthropicClientAgent(client, \"assistant\", systemMessage: \"You are helpful. Always answer briefly.\");\nawait agent.SendAsync(new MessageEnvelope<ChatMessage>(new ChatMessage { Role = \"user\", Content = [new TextContent { Text = \"hi\" }] }));","handlingStrategy":"type-guard","validationCode":"var hasSystem = messages.OfType<IMessage<ChatMessage>>().Any(m => m.Content.Role == \"system\");\nif (hasSystem)\n{\n    messages = messages.Where(m => !(m is IMessage<ChatMessage> c && c.Content.Role == \"system\"));\n    // fold the text into the agent's systemMessage instead\n}","typeGuard":"static bool ContainsSystemMessage(IEnumerable<IMessage> messages) =>\n    messages.OfType<IMessage<ChatMessage>>().Any(m => m.Content.Role == \"system\");","tryCatchPattern":"try { await agent.SendAsync(messages); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"system message\")) { messages = messages.Where(m => m is not IMessage<ChatMessage> c || c.Content.Role != \"system\"); await agent.SendAsync(messages); }","preventionTips":["Always pass the system prompt via AnthropicClientAgent's systemMessage parameter; never inline system-role messages in history.","When persisting conversation logs for replay, tag the initial system prompt so replay code can strip it.","In group chats, use user/assistant roles for agent-to-agent traffic."],"tags":["anthropic","system-message","message-validation","autogen","claude"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}