{"record":{"id":"0b11adc9bbc9f2bd","repo":"microsoft/autogen","slug":"cannot-serialize-codeexecutoragent-with-approval-f","errorCode":null,"errorMessage":"Cannot serialize CodeExecutorAgent with approval_func set. The approval function is not serializable.","messagePattern":"Cannot serialize CodeExecutorAgent with approval_func set\\. The approval function is not serializable\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-agentchat/src/autogen_agentchat/agents/_code_executor_agent.py","lineNumber":745,"sourceCode":"        return result\n\n    async def on_reset(self, cancellation_token: CancellationToken) -> None:\n        \"\"\"Its a no-op as the code executor agent has no mutable state.\"\"\"\n        pass\n\n    def _extract_markdown_code_blocks(self, markdown_text: str) -> List[CodeBlock]:\n        pattern = re.compile(rf\"```(?:\\s*({self._supported_languages_regex}))\\n([\\s\\S]*?)```\", re.IGNORECASE)\n        matches = pattern.findall(markdown_text)\n        code_blocks: List[CodeBlock] = []\n        for match in matches:\n            language = match[0].strip() if match[0] else \"\"\n            code_content = match[1]\n            code_blocks.append(CodeBlock(code=code_content, language=language))\n        return code_blocks\n\n    def _to_config(self) -> CodeExecutorAgentConfig:\n        if self._approval_func is not None:\n            raise ValueError(\n                \"Cannot serialize CodeExecutorAgent with approval_func set. The approval function is not serializable.\"\n            )\n\n        return CodeExecutorAgentConfig(\n            name=self.name,\n            model_client=(self._model_client.dump_component() if self._model_client is not None else None),\n            code_executor=self._code_executor.dump_component(),\n            description=self.description,\n            sources=list(self._sources) if self._sources is not None else None,\n            system_message=(\n                self._system_messages[0].content\n                if self._system_messages and isinstance(self._system_messages[0].content, str)\n                else None\n            ),\n            model_client_stream=self._model_client_stream,\n            model_context=self._model_context.dump_component(),\n            supported_languages=self._supported_languages,\n        )","sourceCodeStart":727,"sourceCodeEnd":763,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-agentchat/src/autogen_agentchat/agents/_code_executor_agent.py#L727-L763","documentation":"CodeExecutorAgent._to_config() refuses to serialize the agent when an approval_func is set, because a Python callback function cannot be represented in the declarative component config. dump_component()/save state will therefore fail.","triggerScenarios":"Calling agent.dump_component() (or a workflow that serializes agents) on a CodeExecutorAgent constructed with approval_func=some_callable.","commonSituations":"Human-in-the-loop setups with code approval callbacks combined with checkpointing/persistence frameworks that dump agent components; attempting save/load round-trips of an agent holding closures.","solutions":["Don't serialize agents that hold callbacks: rebuild the agent from your own config and re-attach approval_func after loading.","Remove approval_func before calling dump_component() and register it again on the reconstructed instance.","Store the approval decision as serializable state (e.g. allowlist rules) instead of a closure."],"exampleFix":"// before\nagent = CodeExecutorAgent(name=\"coder\", code_executor=exec_, approval_func=my_func)\nconfig = agent.dump_component()  # raises\n\n// after\nagent = CodeExecutorAgent(name=\"coder\", code_executor=exec_)\nconfig = agent.dump_component()  # ok\n# rebuild later and re-attach the callback\nagent2 = CodeExecutorAgent.load_component(config)\nagent2._approval_func = my_func  # or re-construct with approval_func","handlingStrategy":"validation","validationCode":"def can_serialize(agent) -> bool:\n    return getattr(agent, \"_approval_func\", None) is None\n\nif can_serialize(agent):\n    config = agent.dump_component()\nelse:\n    # persist executor/model config only; rebuild agent + reattach callback later\n    config = None","typeGuard":null,"tryCatchPattern":"try:\n    config = agent.dump_component()\nexcept ValueError as e:\n    if \"not serializable\" in str(e):\n        # rebuild without the callback, reattach on load\n        ...\n    raise","preventionTips":["Never checkpoint agents holding function references; store config plus a callback registry key instead.","Keep approval logic behind a serializable policy (allowlist) where possible.","Test your save path with the exact production agent configuration."],"tags":["serialization","code-executor","approval-callback","components"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}