microsoft/autogen · error · InvalidOperationException

System role is not supported in Gemini.

Error message

System role is not supported in Gemini.

What it means

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.

Source

Thrown at dotnet/src/AutoGen.Gemini/Middleware/GeminiMessageConnector.cs:387

        var content = new Content
        {
            Parts = { parts },
            Role = shouldParseAsUser ? "user" : "model",
        };

        return [MessageEnvelope.Create(content, multiModalMessage.From)];
    }

    private IEnumerable<IMessage> ProcessTextMessage(TextMessage textMessage, IAgent agent)
    {
        if (textMessage.Role == Role.System)
        {
            // there are only user | model role in Gemini
            // if the role is system and the strict mode is enabled, throw an exception
            if (strictMode)
            {
                throw new InvalidOperationException("System role is not supported in Gemini.");
            }

            // if strict mode is not enabled, parse the message as a user message
            var content = new Content
            {
                Parts = { new[] { new Part { Text = textMessage.Content } } },
                Role = "user",
            };

            return [MessageEnvelope.Create(content, textMessage.From)];
        }

        var shouldParseAsUser = ShouldParseAsUser(textMessage, agent);

        if (shouldParseAsUser)
        {
            var content = new Content
            {

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Use GeminiAgent's systemMessage constructor parameter or Gemini's dedicated system-instruction field instead of a System-role TextMessage.
  2. Rewrite System TextMessages as Role.User before sending to a strict Gemini agent.
  3. Instantiate GeminiMessageConnector without strict mode if the downgrade-to-user behavior is acceptable.

Example fix

// before
await geminiAgent.SendAsync(new TextMessage(Role.System, "You are a concise assistant."));

// after
var geminiAgent = new GeminiAgent(..., systemMessage: "You are a concise assistant.");
await geminiAgent.SendAsync("Summarize this PR.");
Defensive patterns

Strategy: validation

Validate before calling

if (msg is TextMessage tm && tm.Role == Role.System)
{
    msg = new TextMessage(Role.User, tm.Content, from: tm.From); // or move to GeminiAgent systemMessage
}

Type guard

static bool IsSystemText(IMessage m) => m is TextMessage { Role: Role.System };

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/7ec1b103f6b5084f. Report an issue: GitHub.