{"record":{"id":"9369bda86dbea610","repo":"microsoft/autogen","slug":"agent-factory-must-take-0-or-2-arguments","errorCode":null,"errorMessage":"Agent factory must take 0 or 2 arguments.","messagePattern":"Agent factory must take 0 or 2 arguments\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-core/src/autogen_core/_single_threaded_agent_runtime.py","lineNumber":960,"sourceCode":"    async def _invoke_agent_factory(\n        self,\n        agent_factory: Callable[[], T | Awaitable[T]] | Callable[[AgentRuntime, AgentId], T | Awaitable[T]],\n        agent_id: AgentId,\n    ) -> T:\n        with AgentInstantiationContext.populate_context((self, agent_id)):\n            try:\n                if len(inspect.signature(agent_factory).parameters) == 0:\n                    factory_one = cast(Callable[[], T], agent_factory)\n                    agent = factory_one()\n                elif len(inspect.signature(agent_factory).parameters) == 2:\n                    warnings.warn(\n                        \"Agent factories that take two arguments are deprecated. Use AgentInstantiationContext instead. Two arg factories will be removed in a future version.\",\n                        stacklevel=2,\n                    )\n                    factory_two = cast(Callable[[AgentRuntime, AgentId], T], agent_factory)\n                    agent = factory_two(self, agent_id)\n                else:\n                    raise ValueError(\"Agent factory must take 0 or 2 arguments.\")\n\n                if inspect.isawaitable(agent):\n                    agent = cast(T, await agent)\n                return agent\n\n            except BaseException as e:\n                event_logger.info(\n                    AgentConstructionExceptionEvent(\n                        agent_id=agent_id,\n                        exception=e,\n                    )\n                )\n                logger.error(f\"Error constructing agent {agent_id}\", exc_info=True)\n                raise\n\n    async def _get_agent(self, agent_id: AgentId) -> Agent:\n        if agent_id in self._instantiated_agents:\n            return self._instantiated_agents[agent_id]","sourceCodeStart":942,"sourceCodeEnd":978,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-core/src/autogen_core/_single_threaded_agent_runtime.py#L942-L978","documentation":"_invoke_agent_factory introspects the factory's signature: only zero-argument factories (modern) and two-argument (runtime, agent_id) factories (deprecated) are accepted. Anything else — 1, 3+, keyword-only-required, or *args-based — raises ValueError. Note two-arg factories additionally emit a DeprecationWarning.","triggerScenarios":"Passing a lambda with parameters, e.g. lambda cfg: make_agent(cfg) or a bound method like self.create_agent to register_factory; factories capturing config via closure are fine, but explicit parameters other than the legacy (runtime, agent_id) pair fail; class methods whose self binding changes the parameter count unexpectedly.","commonSituations":"Trying to inject configuration through factory arguments instead of closures/partial; migrating code from runtimes that passed context into factories; using functools.partial incorrectly so the signature still exposes extra parameters.","solutions":["Close over configuration: register a lambda/partial that takes no arguments and returns the configured agent","For runtime/agent_id access inside construction, use AgentInstantiationContext.current_agent_runtime()/current_agent_id() in a 0-arg factory instead of the deprecated 2-arg form","Check len(inspect.signature(factory).parameters) <= 2 and that extra params have defaults before registering"],"exampleFix":"# before\nawait runtime.register_factory(\n    AgentType(\"worker\"), lambda cfg: WorkerAgent(cfg)  # 1-arg -> ValueError\n)\n\n# after\ncfg = load_config()\nawait runtime.register_factory(\n    AgentType(\"worker\"), lambda: WorkerAgent(cfg)  # 0-arg closure\n)","handlingStrategy":"validation","validationCode":"import inspect\n\ndef factory_signature_valid(factory) -> bool:\n    params = [p for p in inspect.signature(factory).parameters.values()\n              if p.default is inspect.Parameter.empty and p.kind in (p.POSITIONAL_ONLY, p.POSITIONAL_OR_KEYWORD, p.KEYWORD_ONLY)]\n    return len(params) in (0, 2)","typeGuard":"def is_zero_arg_factory(factory) -> bool:\n    import inspect\n    return len(inspect.signature(factory).parameters) == 0","tryCatchPattern":"try:\n    await runtime.register_factory(t, factory)\nexcept ValueError as e:\n    if \"0 or 2 arguments\" in str(e):\n        raise TypeError(\"wrap config injection in a closure/partial\") from e\n    raise","preventionTips":["Inject config via closures/partial, not factory parameters","Use AgentInstantiationContext for runtime/agent_id inside factories (2-arg form is deprecated)","Validate factory signatures in a registration smoke test"],"tags":["autogen-core","agent-registration","factory","signature","valueerror"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}