microsoft/autogen · error · ValueError

Message type {message_type} must be a subclass of BaseChatMe

Error message

Message type {message_type} must be a subclass of BaseChatMessage or BaseAgentEvent.

What it means

MessageFactory.register only accepts classes that subclass BaseChatMessage or BaseAgentEvent; anything else (a plain pydantic BaseModel, a dataclass, a non-class object) raises ValueError. The check uses issubclass, so passing an instance instead of the class also fails with a TypeError or this ValueError.

Source

Thrown at python/packages/autogen-agentchat/src/autogen_agentchat/messages.py:621

        self._message_types[ModelClientStreamingChunkEvent.__name__] = ModelClientStreamingChunkEvent
        self._message_types[ThoughtEvent.__name__] = ThoughtEvent
        self._message_types[SelectSpeakerEvent.__name__] = SelectSpeakerEvent
        self._message_types[CodeGenerationEvent.__name__] = CodeGenerationEvent
        self._message_types[CodeExecutionEvent.__name__] = CodeExecutionEvent

    def is_registered(self, message_type: type[BaseAgentEvent | BaseChatMessage]) -> bool:
        """Check if a message type is registered with the factory."""
        # Get the class name of the message type.
        class_name = message_type.__name__
        # Check if the class name is already registered.
        return class_name in self._message_types

    def register(self, message_type: type[BaseAgentEvent | BaseChatMessage]) -> None:
        """Register a new message type with the factory."""
        if self.is_registered(message_type):
            raise ValueError(f"Message type {message_type} is already registered.")
        if not issubclass(message_type, BaseChatMessage) and not issubclass(message_type, BaseAgentEvent):
            raise ValueError(f"Message type {message_type} must be a subclass of BaseChatMessage or BaseAgentEvent.")
        # Get the class name of the
        class_name = message_type.__name__
        # Check if the class name is already registered.
        # Register the message type.
        self._message_types[class_name] = message_type

    def create(self, data: Mapping[str, Any]) -> BaseAgentEvent | BaseChatMessage:
        """Create a message from a dictionary of JSON-serializable data."""
        # Get the type of the message from the dictionary.
        message_type = data.get("type")
        if message_type is None:
            raise ValueError("Field 'type' is required in the message data to recover the message type.")
        if message_type not in self._message_types:
            raise ValueError(f"Unknown message type: {message_type}")
        if not isinstance(message_type, str):
            raise ValueError(f"Message type must be a string, got {type(message_type)}")

        # Get the class for the message type.

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Subclass BaseChatMessage or BaseAgentEvent (e.g. class MyEvent(BaseAgentEvent): ...)
  2. Register the class itself: factory.register(MyEvent), not factory.register(MyEvent(...))
  3. Pre-validate with issubclass(MyEvent, (BaseChatMessage, BaseAgentEvent))

Example fix

# before
from pydantic import BaseModel
class MyPayload(BaseModel):
    value: str
factory.register(MyPayload)  # ValueError

# after
from autogen_agentchat.base import BaseAgentEvent
class MyEvent(BaseAgentEvent):
    value: str
factory.register(MyEvent)
Defensive patterns

Strategy: type-guard

Validate before calling

from autogen_agentchat.base import BaseChatMessage, BaseAgentEvent
assert issubclass(MyMessageType, (BaseChatMessage, BaseAgentEvent)), "must derive from agentchat base types"

Type guard

from autogen_agentchat.base import BaseChatMessage, BaseAgentEvent

def is_registrable_message_type(obj) -> bool:
    """True when obj is a class deriving from BaseChatMessage or BaseAgentEvent."""
    return isinstance(obj, type) and issubclass(obj, (BaseChatMessage, BaseAgentEvent))

Try / catch

try:
    factory.register(candidate)
except ValueError as e:
    if "must be a subclass" in str(e):
        candidate = build_agentchat_subclass(candidate)  # adapt before registering
        factory.register(candidate)
    else:
        raise

Prevention

When it happens

Trigger: factory.register(SomeBaseModel) where the class only derives from BaseModel; factory.register(my_message_instance) (instance, not type); registering event-like classes from other frameworks that do not derive from autogen's base classes.

Common situations: Porting pydantic models from autogen-core (ChatMessage vs agentchat's BaseChatMessage hierarchy); assuming any serializable model can be a message type; passing the result of a factory function instead of the class.

Related errors


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