microsoft/autogen · error · ValueError

Agent factory must take 0 or 2 arguments.

Error message

Agent factory must take 0 or 2 arguments.

What it means

GrpcWorkerAgentRuntime._invoke_agent_factory supports exactly two factory signatures: zero arguments (modern style, using AgentInstantiationContext) or two arguments (runtime, agent_id — deprecated). It inspects the callable's parameter count and raises ValueError('Agent factory must take 0 or 2 arguments.') for anything else. The error occurs at agent instantiation time (when a message first arrives for the type), not at registration time, because the factory is only invoked lazily by _get_agent.

Source

Thrown at python/packages/autogen-ext/src/autogen_ext/runtimes/grpc/_worker_runtime.py:790

    async def _invoke_agent_factory(
        self,
        agent_factory: Callable[[], T | Awaitable[T]] | Callable[[AgentRuntime, AgentId], T | Awaitable[T]],
        agent_id: AgentId,
    ) -> T:
        with AgentInstantiationContext.populate_context((self, agent_id)):
            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[[AgentRuntime, 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):
                agent = cast(T, await agent)

        return agent

    async def _get_agent(self, agent_id: AgentId) -> Agent:
        if agent_id in self._instantiated_agents:
            return self._instantiated_agents[agent_id]

        if agent_id.type not in self._agent_factories:
            raise ValueError(f"Agent with name {agent_id.type} not found.")

        agent_factory = self._agent_factories[agent_id.type]
        agent = await self._invoke_agent_factory(agent_factory, agent_id)
        self._instantiated_agents[agent_id] = agent
        return agent

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Make the factory take zero arguments and read runtime/agent id from AgentInstantiationContext.current() (the non-deprecated style)
  2. Or take exactly (runtime, agent_id) — accepting the deprecation warning — if context injection is unsuitable
  3. Check the callable locally: len(inspect.signature(factory).parameters) must be 0 or 2 before registering
  4. Add an integration test that sends a message to the registered type so factory invocation errors surface in CI, not production

Example fix

# before
async def make_agent(agent_id):  # 1 argument -> ValueError on first message
    return MyAgent(agent_id)
await runtime.register_factory('t', make_agent)

# after
from autogen_core import AgentInstantiationContext
def make_agent():
    _rt, agent_id = AgentInstantiationContext.current()
    return MyAgent(agent_id)
await runtime.register_factory('t', make_agent)
Defensive patterns

Strategy: type-guard

Validate before calling

import inspect
def valid_factory_signature(factory) -> bool:
    return len(inspect.signature(factory).parameters) in (0, 2)

Type guard

import inspect
def is_valid_agent_factory(factory) -> bool:
    try:
        return len(inspect.signature(factory).parameters) in (0, 2)
    except (TypeError, ValueError):
        return False

Prevention

When it happens

Trigger: Passing a factory with 1, 3+, keyword-only-required, or *args-style signatures that inspect.signature counts differently than 0 or 2; passing a partial or bound method whose remaining parameter count is not 0 or 2; the factory works in tests that never deliver a message, then blows up on first real message routing.

Common situations: Refactoring a factory to take (runtime) or (agent_id) only; using functools.partial that leaves one bound parameter; lambdas with default args miscounted after wrapping; teams testing registration but not message delivery so the failure appears only in production traffic.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/baf43f726a518e61. Report an issue: GitHub.