microsoft/autogen · error · InvalidOperationException
ToolCallMessage is not supported as user role in Gemini.
Error message
ToolCallMessage is not supported as user role in Gemini.
What it means
GeminiMessageConnector.ProcessToolCallMessage throws in strict mode when a ToolCallMessage must be rendered with the Gemini 'user' role. ShouldParseAsUser decides the role; a function-call part is only valid as 'model' in the Gemini API, so a tool call attributed to someone other than the Gemini agent itself cannot be represented and strict mode rejects it.
Source
Thrown at dotnet/src/AutoGen.Gemini/Middleware/GeminiMessageConnector.cs:317
functionCallResultParts.Add(part);
}
var content = new Content
{
Parts = { functionCallResultParts },
Role = "function",
};
return [MessageEnvelope.Create(content, toolCallResultMessage.From)];
}
private IEnumerable<IMessage> ProcessToolCallMessage(ToolCallMessage toolCallMessage, IAgent agent)
{
var shouldParseAsUser = ShouldParseAsUser(toolCallMessage, agent);
if (strictMode && shouldParseAsUser)
{
throw new InvalidOperationException("ToolCallMessage is not supported as user role in Gemini.");
}
var functionCallParts = new List<Part>();
foreach (var toolCall in toolCallMessage.ToolCalls)
{
var part = new Part
{
FunctionCall = new FunctionCall
{
Name = toolCall.FunctionName,
Args = Struct.Parser.ParseJson(toolCall.FunctionArguments),
}
};
functionCallParts.Add(part);
}
var content = new Content
{View on GitHub (pinned to 027ecf0a37)
Solutions
- Set message.From to the Gemini agent's name before sending its own ToolCallMessage history back to it.
- Convert foreign ToolCallMessages into ToolCallResultMessages or a TextMessage summary before they reach a strict Gemini agent.
- Disable strict mode (strictMode:false) so the connector maps it leniently.
- Reorder group-chat routing so tool-call/result pairs are only sent to the agent that issued them.
Example fix
// before
var foreign = new ToolCallMessage(calls, from: "openai-assistant");
await geminiAgent.InitiateChatAsync(null, null, foreign); // strict connector
// after
var summary = new TextMessage(Role.User, "openai-assistant called: " + string.Join(",", calls.Select(c => c.FunctionName)), from: "openai-assistant");
await geminiAgent.SendAsync(summary); Defensive patterns
Strategy: validation
Validate before calling
if (msg is ToolCallMessage tcm && tcm.From != geminiAgent.Name)
{
msg = new TextMessage(Role.User, "tool calls: " + string.Join(",", tcm.ToolCalls.Select(t => t.FunctionName)), from: tcm.From);
} Prevention
- Keep tool-call/result messages local to the agent that produced them
- Use strictMode only on agents with controlled inputs
When it happens
Trigger: strictMode:true plus a ToolCallMessage whose From differs from the Gemini agent's name (e.g. a tool-call message produced by another agent in a group chat) reaching the Gemini agent.
Common situations: Multi-agent group chats where an assistant agent's ToolCallMessage is replayed to the Gemini agent as context; middleware forwarding tool calls between agents with strict connectors.
Related errors
- Image message is not supported as model role in Gemini.
- System role is not supported 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/faae2ffa8d8bf1c0.
Report an issue: GitHub.