microsoft/autogen · error · ArgumentException

Invalid message type

Error message

Invalid message type

What it means

MistralClientAgent.BuildChatHistory only accepts messages already wrapped as IMessage<ChatMessage> (the Mistral-native chat shape); anything else throws ArgumentException. The wrapping is normally done by MistralChatMessageConnector middleware, so this error means raw AutoGen messages reached the agent unconverted.

Source

Thrown at dotnet/src/AutoGen.Mistral/Agent/MistralClientAgent.cs:119

            MaxTokens = options?.MaxToken,
            ResponseFormat = _jsonOutput ? new ResponseFormat() { ResponseFormatType = "json_object" } : null,
        };

        if (options?.Functions != null)
        {
            chatRequest.Tools = options.Functions.Select(f => new FunctionTool(f.ToMistralFunctionDefinition())).ToList();
            chatRequest.ToolChoice = _toolChoice ?? ToolChoiceEnum.Auto;
        }

        return chatRequest;
    }

    private IEnumerable<ChatMessage> BuildChatHistory(IEnumerable<IMessage> messages)
    {
        var history = messages.Select(m => m switch
        {
            IMessage<ChatMessage> chatMessage => chatMessage.Content,
            _ => throw new ArgumentException("Invalid message type")
        });

        // if there's no system message in the history, add one to the beginning
        if (!history.Any(m => m.Role == ChatMessage.RoleEnum.System))
        {
            history = new[] { new ChatMessage(ChatMessage.RoleEnum.System, _systemMessage) }.Concat(history);
        }

        return history;
    }
}

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Use MistralAgent (which wires MistralChatMessageConnector) or explicitly register the connector middleware on MistralClientAgent.
  2. If calling the client agent directly, wrap content yourself: MessageEnvelope.Create(new ChatMessage(role, content), from).
  3. Check middleware order: the connector must run before the request is serialized.

Example fix

// before
var agent = new MistralClientAgent(name: "a", client: client, model: "mistral-large-latest");
var reply = await agent.SendAsync(new TextMessage(Role.User, "hi"));

// after
var agent = new MistralAgent(name: "a", client: client, model: "mistral-large-latest"); // connector registered
var reply = await agent.SendAsync("hi");
Defensive patterns

Strategy: type-guard

Validate before calling

var unwrapped = messages.Where(m => m is not Core.IMessage<ChatMessage>).ToList();
if (unwrapped.Count > 0) { messages = ConvertViaConnector(messages); } // or use MistralAgent

Type guard

static bool IsMistralChatReady(IEnumerable<IMessage> msgs) => msgs.All(m => m is Core.IMessage<ChatMessage>);

Prevention

When it happens

Trigger: Calling a MistralClientAgent's reply pipeline without registering MistralChatMessageConnector (or calling the underlying client directly) and passing TextMessage/ToolCallMessage instances instead of MessageEnvelope<ChatMessage>.

Common situations: Using MistralClientAgent instead of the higher-level MistralAgent that auto-registers the connector; custom middleware ordering that strips envelopes; sending messages produced by other providers into the Mistral client agent.

Related errors


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