microsoft/autogen · error · ValueError

Agent with type {type} already exists.

Error message

Agent with type {type} already exists.

What it means

register_factory raises ValueError when an agent factory is already registered under the same AgentType string. The runtime maps type strings to factories one-to-one; a second registration for an existing type is rejected instead of overwritten.

Source

Thrown at python/packages/autogen-core/src/autogen_core/_single_threaded_agent_runtime.py:897

    async def agent_save_state(self, agent: AgentId) -> Mapping[str, Any]:
        return await (await self._get_agent(agent)).save_state()

    async def agent_load_state(self, agent: AgentId, state: Mapping[str, Any]) -> None:
        await (await self._get_agent(agent)).load_state(state)

    async def register_factory(
        self,
        type: str | AgentType,
        agent_factory: Callable[[], T | Awaitable[T]],
        *,
        expected_class: type[T] | None = None,
    ) -> AgentType:
        if isinstance(type, str):
            type = AgentType(type)

        if type.type in self._agent_factories:
            raise ValueError(f"Agent with type {type} already exists.")

        async def factory_wrapper() -> T:
            maybe_agent_instance = agent_factory()
            if inspect.isawaitable(maybe_agent_instance):
                agent_instance = await maybe_agent_instance
            else:
                agent_instance = maybe_agent_instance

            if expected_class is not None and not issubclass(type_func_alias(agent_instance), expected_class):
                raise ValueError(
                    f"Factory registered using the wrong type: expected {expected_class.__name__}, got {type_func_alias(agent_instance).__name__}"
                )
            return agent_instance

        self._agent_factories[type.type] = factory_wrapper

        return type

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Use the try_register variant (e.g. try_register_factory / type-safe register with exists_ok semantics) or check existence before registering
  2. Create a fresh runtime per test/session instead of re-registering on a shared one
  3. Namespace your type strings (e.g. 'myapp.worker') to avoid collisions

Example fix

# before
await runtime.register_factory(AgentType("worker"), Worker.create)  # second time -> ValueError

# after
if AgentType("worker") not in already_registered:  # or use try_register_* API
    await runtime.register_factory(AgentType("worker"), Worker.create)
# fresh runtime per session also avoids this
Defensive patterns

Strategy: validation

Validate before calling

async def register_factory_once(runtime, type_str, factory):
    try:
        await runtime.try_register_factory(AgentType(type_str), factory)  # no-op if exists
    except AttributeError:
        if type_str not in runtime._agent_factories:
            await runtime.register_factory(AgentType(type_str), factory)

Try / catch

try:
    await runtime.register_factory(t, factory)
except ValueError as e:
    if "already exists" in str(e):
        pass  # already registered this session
    else:
        raise

Prevention

When it happens

Trigger: Calling await runtime.register_factory(AgentType("worker"), factory) twice; registering a type, then trying register_factory again after a failed attempt (first registration persists); a register helper (e.g. BaseAgent.__subclasses__ registration or type-safe RuntimeAgentType.register) colliding with a manual registration of the same type string.

Common situations: Hot-reload/notebook re-execution of registration cells; test suites sharing a runtime across cases that each register the same type; retry loops around registration; two teams using the same generic type name ('assistant').

Related errors


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