microsoft/autogen · error · ValueError

Agent instances must be the same object type.

Error message

Agent instances must be the same object type.

What it means

When register_agent_instance adds a second instance under a type that already has instance registrations (the sentinel-factory path matched), it checks that the new instance's concrete class equals the recorded _agent_instance_types[type]. A different class under the same type string raises ValueError, because try_get_underlying_agent_instance promises one concrete type per agent type.

Source

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

        agent_instance: Agent,
        agent_id: AgentId,
    ) -> AgentId:
        def agent_factory() -> Agent:
            raise RuntimeError(
                "Agent factory was invoked for an agent instance that was not registered. This is likely due to the agent type being incorrectly subscribed to a topic. If this exception occurs when publishing a message to the DefaultTopicId, then it is likely that `skip_class_subscriptions` needs to be turned off when registering the agent."
            )

        if agent_id in self._instantiated_agents:
            raise ValueError(f"Agent with id {agent_id} already exists.")

        if agent_id.type not in self._agent_factories:
            self._agent_factories[agent_id.type] = agent_factory
            self._agent_instance_types[agent_id.type] = type_func_alias(agent_instance)
        else:
            if self._agent_factories[agent_id.type].__code__ != agent_factory.__code__:
                raise ValueError("Agent factories and agent instances cannot be registered to the same type.")
            if self._agent_instance_types[agent_id.type] != type_func_alias(agent_instance):
                raise ValueError("Agent instances must be the same object type.")

        await agent_instance.bind_id_and_runtime(id=agent_id, runtime=self)
        self._instantiated_agents[agent_id] = agent_instance
        return agent_id

    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)):
            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.",

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Use a separate AgentType string per implementation class (e.g. 'handler.v1' vs 'handler.v2')
  2. Ensure all instances registered under one type are exactly the same class (register the subclass everywhere, not just some keys)
  3. During migration, finish swapping all instances before running, or register the new class under a new type

Example fix

# before
await runtime.register_agent_instance(V1(), AgentId("handler", "1"))
await runtime.register_agent_instance(V2(), AgentId("handler", "2"))  # ValueError

# after
await runtime.register_agent_instance(V1(), AgentId("handler.v1", "1"))
await runtime.register_agent_instance(V2(), AgentId("handler.v2", "2"))
Defensive patterns

Strategy: validation

Validate before calling

def instances_same_class(runtime, t: str, new_instance) -> bool:
    recorded = runtime._agent_instance_types.get(t)
    return recorded is None or recorded is type(new_instance)

Type guard

def matches_recorded_type(recorded_type, instance) -> bool:
    return type(instance) is recorded_type

Try / catch

try:
    await runtime.register_agent_instance(inst2, AgentId(t, "2"))
except ValueError as e:
    if "same object type" in str(e):
        await runtime.register_agent_instance(inst2, AgentId(type(inst2).__name__.lower(), "2"))
    else:
        raise

Prevention

When it happens

Trigger: Registering instance of class A as AgentId("handler", "1"), then registering an instance of class B (not the same class) as AgentId("handler", "2"). Subclass instances also fail if the first registration set the type to the parent.

Common situations: Registering per-tenant or per-shard instances where someone swapped in a different implementation class for one key; evolving to a new agent class but keeping the old type string with mixed old/new instances during migration.

Related errors


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