{"record":{"id":"7ec1b103f6b5084f","repo":"microsoft/autogen","slug":"system-role-is-not-supported-in-gemini","errorCode":null,"errorMessage":"System role is not supported in Gemini.","messagePattern":"System role is not supported in Gemini\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/AutoGen.Gemini/Middleware/GeminiMessageConnector.cs","lineNumber":387,"sourceCode":"\n        var content = new Content\n        {\n            Parts = { parts },\n            Role = shouldParseAsUser ? \"user\" : \"model\",\n        };\n\n        return [MessageEnvelope.Create(content, multiModalMessage.From)];\n    }\n\n    private IEnumerable<IMessage> ProcessTextMessage(TextMessage textMessage, IAgent agent)\n    {\n        if (textMessage.Role == Role.System)\n        {\n            // there are only user | model role in Gemini\n            // if the role is system and the strict mode is enabled, throw an exception\n            if (strictMode)\n            {\n                throw new InvalidOperationException(\"System role is not supported in Gemini.\");\n            }\n\n            // if strict mode is not enabled, parse the message as a user message\n            var content = new Content\n            {\n                Parts = { new[] { new Part { Text = textMessage.Content } } },\n                Role = \"user\",\n            };\n\n            return [MessageEnvelope.Create(content, textMessage.From)];\n        }\n\n        var shouldParseAsUser = ShouldParseAsUser(textMessage, agent);\n\n        if (shouldParseAsUser)\n        {\n            var content = new Content\n            {","sourceCodeStart":369,"sourceCodeEnd":405,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/dotnet/src/AutoGen.Gemini/Middleware/GeminiMessageConnector.cs#L369-L405","documentation":"Gemini's chat schema only has 'user' and 'model' roles. GeminiMessageConnector.ProcessTextMessage maps a Role.System TextMessage to a 'user' Content by default, but when the connector was created with strictMode:true it throws instead, to warn you that system-prompt semantics are being silently downgraded.","triggerScenarios":"strictMode:true and sending a TextMessage with Role == Role.System (e.g. a system prompt injected by middleware or another agent's initializer) to a GeminiAgent.","commonSituations":"Portable pipelines that prepend a system prompt as a System-role TextMessage across vendors; connecting GeminiAgent to agents that emit system-role messages in group chat.","solutions":["Use GeminiAgent's systemMessage constructor parameter or Gemini's dedicated system-instruction field instead of a System-role TextMessage.","Rewrite System TextMessages as Role.User before sending to a strict Gemini agent.","Instantiate GeminiMessageConnector without strict mode if the downgrade-to-user behavior is acceptable."],"exampleFix":"// before\nawait geminiAgent.SendAsync(new TextMessage(Role.System, \"You are a concise assistant.\"));\n\n// after\nvar geminiAgent = new GeminiAgent(..., systemMessage: \"You are a concise assistant.\");\nawait geminiAgent.SendAsync(\"Summarize this PR.\");","handlingStrategy":"validation","validationCode":"if (msg is TextMessage tm && tm.Role == Role.System)\n{\n    msg = new TextMessage(Role.User, tm.Content, from: tm.From); // or move to GeminiAgent systemMessage\n}","typeGuard":"static bool IsSystemText(IMessage m) => m is TextMessage { Role: Role.System };","tryCatchPattern":null,"preventionTips":["Pass system prompts via GeminiAgent's systemMessage parameter","Convert cross-vendor system messages at the boundary"],"tags":["gemini","strict-mode","system-role","role-mapping"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}