{"record":{"id":"96dc1aa55c235ca9","repo":"microsoft/semantic-kernel","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/semantic_kernel/agents/runtime/in_process/in_process_runtime.py","lineNumber":778,"sourceCode":"        self,\n        agent_factory: Callable[[], T | Awaitable[T]] | Callable[[CoreRuntime, 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 \"\n                        \"instead. Two arg factories will be removed in a future version.\",\n                        stacklevel=2,\n                    )\n                    factory_two = cast(Callable[[CoreRuntime, 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                    return cast(T, await agent)\n\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:","sourceCodeStart":760,"sourceCodeEnd":796,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/agents/runtime/in_process/in_process_runtime.py#L760-L796","documentation":"_invoke_agent_factory inspects the factory's signature and expects either 0 parameters (modern) or 2 parameters (deprecated runtime+agent_id). If the factory has any other arity (1, 3+), ValueError is raised. The two-arg form is deprecated and emits a DeprecationWarning.","triggerScenarios":"Registering a factory function with 1 argument (e.g. def factory(runtime) or 3+ arguments. The runtime only supports 0-arg or 2-arg factories.","commonSituations":"A developer writes a factory that takes a runtime or configuration argument, not realizing the API only supports 0 or 2 args. Migrating from a closure-based factory to a method-based one changes the visible arity (self becomes param 1).","solutions":["Use a 0-argument factory (preferred): capture any needed config via closure.","If you need runtime/agent_id access, use AgentInstantiationContext.current_runtime() and current_agent_id() inside a 0-arg factory instead of the deprecated 2-arg form.","If using a bound method, be aware that self is not counted by inspect.signature on bound methods — but on unbound methods it is."],"exampleFix":"# before\nasync def factory(config):\n    return MyAgent(config)\nawait runtime.register_factory('my_agent', functools.partial(factory, my_config))  # 1 arg raises\n\n# after\ndef factory():\n    return MyAgent(my_config)\nawait runtime.register_factory('my_agent', factory)  # 0 args, config via closure","handlingStrategy":"validation","validationCode":"import inspect\n\ndef validate_factory_arity(factory):\n    params = inspect.signature(factory).parameters\n    n = len(params)\n    if n not in (0, 2):\n        raise ValueError(f'Factory must take 0 or 2 arguments, got {n}')\n    return factory\n\nvalidate_factory_arity(my_factory)\nawait runtime.register_factory('my_agent', my_factory)","typeGuard":"import inspect\n\ndef is_valid_factory(factory) -> bool:\n    n = len(inspect.signature(factory).parameters)\n    return n in (0, 2)","tryCatchPattern":"null","preventionTips":["Use 0-argument factories (the modern pattern). Capture config via closures.","If you need runtime/agent_id, use AgentInstantiationContext inside the factory, not factory parameters.","Beware unbound methods where self counts as a parameter."],"tags":["agent-runtime","factory","signature","deprecated","in-process-runtime","semantic-kernel"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}