microsoft/semantic-kernel · error · ValueError

Agent with type {type} already exists.

Error message

Agent with type {type} already exists.

What it means

register_factory checks if the agent type string already exists in _agent_factories before registering. If a factory was already registered for that type, it raises ValueError. This prevents accidental shadowing of one factory by another.

Source

Thrown at python/semantic_kernel/agents/runtime/in_process/in_process_runtime.py:741

        return await (await self._get_agent(agent)).save_state()

    async def agent_load_state(self, agent: AgentId, state: Mapping[str, Any]) -> None:
        """Load the state of a single agent."""
        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:
        """Register a factory for creating agents."""
        if isinstance(type, str):
            type = CoreAgentType(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 type_func_alias(agent_instance) != expected_class:
                raise ValueError("Factory registered using the wrong type.")

            return agent_instance

        self._agent_factories[type.type] = factory_wrapper

        return type

    async def _invoke_agent_factory(

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Create a new InProcessRuntime instance for each test or session rather than re-registering on an existing one.
  2. Check if the type is already registered before calling register_factory (though the runtime does not expose a public 'is_registered' check, you can track this in your own code).
  3. Call runtime.stop() and create a fresh runtime if you need to re-register.

Example fix

# before
await runtime.register_factory('my_agent', factory1)
await runtime.register_factory('my_agent', factory2)  # raises

# after
await runtime.register_factory('my_agent', factory1)
# To change factory, create a new runtime:
runtime = InProcessRuntime()
await runtime.register_factory('my_agent', factory2)
Defensive patterns

Strategy: validation

Validate before calling

# Track registered types in your own code
registered_types: set[str] = set()
async def safe_register_factory(runtime, type_name, factory, expected_class=None):
    if type_name in registered_types:
        return  # already registered, skip
    await runtime.register_factory(type_name, factory, expected_class=expected_class)
    registered_types.add(type_name)

Type guard

null

Try / catch

try:
    await runtime.register_factory(type_name, factory)
except ValueError:
    pass  # already registered — acceptable in idempotent setup

Prevention

When it happens

Trigger: Calling register_factory('MyAgent', factory1) then register_factory('MyAgent', factory2) without the runtime being reset. Also occurs when the same registration code runs twice (e.g. in a test that doesn't tear down, or a module-level registration executed on import in a reload).

Common situations: Test suites that register factories in setUp without creating a fresh runtime. Application code that registers on every request or reconnect. Importing a module that performs registration at module level, twice (e.g. via test reload).

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/bf1bbac8caf341eb. Report an issue: GitHub.