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
- 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.
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
- Pass system prompts via GeminiAgent's systemMessage parameter
- Convert cross-vendor system messages at the boundary
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
- ToolCallMessage is not supported as user role in Gemini.
- Image message is not supported as model role in Gemini.
- Unsupported message type: {m.GetType()}
- Message type {m.GetType()} is not supported.
- The first message must be from the user or function
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/7ec1b103f6b5084f.
Report an issue: GitHub.