microsoft/semantic-kernel · error · ValueError
Agent factory must take 0 or 2 arguments.
Error message
Agent factory must take 0 or 2 arguments.
What it means
_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.
Source
Thrown at python/semantic_kernel/agents/runtime/in_process/in_process_runtime.py:778
self,
agent_factory: Callable[[], T | Awaitable[T]] | Callable[[CoreRuntime, AgentId], T | Awaitable[T]],
agent_id: AgentId,
) -> T:
with AgentInstantiationContext.populate_context((self, agent_id)):
try:
if len(inspect.signature(agent_factory).parameters) == 0:
factory_one = cast(Callable[[], T], agent_factory)
agent = factory_one()
elif len(inspect.signature(agent_factory).parameters) == 2:
warnings.warn(
"Agent factories that take two arguments are deprecated. Use AgentInstantiationContext "
"instead. Two arg factories will be removed in a future version.",
stacklevel=2,
)
factory_two = cast(Callable[[CoreRuntime, AgentId], T], agent_factory)
agent = factory_two(self, agent_id)
else:
raise ValueError("Agent factory must take 0 or 2 arguments.")
if inspect.isawaitable(agent):
return cast(T, await agent)
return agent
except BaseException as e:
event_logger.info(
AgentConstructionExceptionEvent(
agent_id=agent_id,
exception=e,
)
)
logger.error(f"Error constructing agent {agent_id}", exc_info=True)
raise
async def _get_agent(self, agent_id: AgentId) -> Agent:
if agent_id in self._instantiated_agents:View on GitHub (pinned to c028a0c7dc)
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.
Example fix
# before
async def factory(config):
return MyAgent(config)
await runtime.register_factory('my_agent', functools.partial(factory, my_config)) # 1 arg raises
# after
def factory():
return MyAgent(my_config)
await runtime.register_factory('my_agent', factory) # 0 args, config via closure Defensive patterns
Strategy: validation
Validate before calling
import inspect
def validate_factory_arity(factory):
params = inspect.signature(factory).parameters
n = len(params)
if n not in (0, 2):
raise ValueError(f'Factory must take 0 or 2 arguments, got {n}')
return factory
validate_factory_arity(my_factory)
await runtime.register_factory('my_agent', my_factory) Type guard
import inspect
def is_valid_factory(factory) -> bool:
n = len(inspect.signature(factory).parameters)
return n in (0, 2) Try / catch
null
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- Agent with type {type} already exists.
- Runtime is already started
- Runtime is not started
- Factory registered using the wrong type.
- Agent with name {agent_id.type} not found.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/96dc1aa55c235ca9.
Report an issue: GitHub.