{"record":{"id":"db37893da49e17ef","repo":"microsoft/autogen","slug":"message-type-message-type-must-be-a-subclass-of","errorCode":null,"errorMessage":"Message type {message_type} must be a subclass of BaseChatMessage or BaseAgentEvent.","messagePattern":"Message type (.+?) must be a subclass of BaseChatMessage or BaseAgentEvent\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-agentchat/src/autogen_agentchat/messages.py","lineNumber":621,"sourceCode":"        self._message_types[ModelClientStreamingChunkEvent.__name__] = ModelClientStreamingChunkEvent\n        self._message_types[ThoughtEvent.__name__] = ThoughtEvent\n        self._message_types[SelectSpeakerEvent.__name__] = SelectSpeakerEvent\n        self._message_types[CodeGenerationEvent.__name__] = CodeGenerationEvent\n        self._message_types[CodeExecutionEvent.__name__] = CodeExecutionEvent\n\n    def is_registered(self, message_type: type[BaseAgentEvent | BaseChatMessage]) -> bool:\n        \"\"\"Check if a message type is registered with the factory.\"\"\"\n        # Get the class name of the message type.\n        class_name = message_type.__name__\n        # Check if the class name is already registered.\n        return class_name in self._message_types\n\n    def register(self, message_type: type[BaseAgentEvent | BaseChatMessage]) -> None:\n        \"\"\"Register a new message type with the factory.\"\"\"\n        if self.is_registered(message_type):\n            raise ValueError(f\"Message type {message_type} is already registered.\")\n        if not issubclass(message_type, BaseChatMessage) and not issubclass(message_type, BaseAgentEvent):\n            raise ValueError(f\"Message type {message_type} must be a subclass of BaseChatMessage or BaseAgentEvent.\")\n        # Get the class name of the\n        class_name = message_type.__name__\n        # Check if the class name is already registered.\n        # Register the message type.\n        self._message_types[class_name] = message_type\n\n    def create(self, data: Mapping[str, Any]) -> BaseAgentEvent | BaseChatMessage:\n        \"\"\"Create a message from a dictionary of JSON-serializable data.\"\"\"\n        # Get the type of the message from the dictionary.\n        message_type = data.get(\"type\")\n        if message_type is None:\n            raise ValueError(\"Field 'type' is required in the message data to recover the message type.\")\n        if message_type not in self._message_types:\n            raise ValueError(f\"Unknown message type: {message_type}\")\n        if not isinstance(message_type, str):\n            raise ValueError(f\"Message type must be a string, got {type(message_type)}\")\n\n        # Get the class for the message type.","sourceCodeStart":603,"sourceCodeEnd":639,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-agentchat/src/autogen_agentchat/messages.py#L603-L639","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Subclass BaseChatMessage or BaseAgentEvent (e.g. class MyEvent(BaseAgentEvent): ...)","Register the class itself: factory.register(MyEvent), not factory.register(MyEvent(...))","Pre-validate with issubclass(MyEvent, (BaseChatMessage, BaseAgentEvent))"],"exampleFix":"# before\nfrom pydantic import BaseModel\nclass MyPayload(BaseModel):\n    value: str\nfactory.register(MyPayload)  # ValueError\n\n# after\nfrom autogen_agentchat.base import BaseAgentEvent\nclass MyEvent(BaseAgentEvent):\n    value: str\nfactory.register(MyEvent)","handlingStrategy":"type-guard","validationCode":"from autogen_agentchat.base import BaseChatMessage, BaseAgentEvent\nassert issubclass(MyMessageType, (BaseChatMessage, BaseAgentEvent)), \"must derive from agentchat base types\"","typeGuard":"from autogen_agentchat.base import BaseChatMessage, BaseAgentEvent\n\ndef is_registrable_message_type(obj) -> bool:\n    \"\"\"True when obj is a class deriving from BaseChatMessage or BaseAgentEvent.\"\"\"\n    return isinstance(obj, type) and issubclass(obj, (BaseChatMessage, BaseAgentEvent))","tryCatchPattern":"try:\n    factory.register(candidate)\nexcept ValueError as e:\n    if \"must be a subclass\" in str(e):\n        candidate = build_agentchat_subclass(candidate)  # adapt before registering\n        factory.register(candidate)\n    else:\n        raise","preventionTips":["Derive custom message types from BaseChatMessage or BaseAgentEvent, not bare BaseModel","Register the class object, never an instance","Pre-check with issubclass(...) before registering"],"tags":["message-factory","registration","type-check","agentchat"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}