microsoft/semantic-kernel · error · ValueError

Agent {agent_name} cannot handoff to itself.

Error message

Agent {agent_name} cannot handoff to itself.

What it means

Raised as a ValueError in _validate_handoffs when a handoff connection's target equals its source (agent hands off to itself). A self-handoff creates an infinite routing loop with no progress, so the validator explicitly rejects it.

Source

Thrown at python/semantic_kernel/agents/orchestration/handoffs.py:527

        The type is appended with the internal topic type to ensure uniqueness in the runtime
        that may be shared by multiple orchestrations.
        """
        return f"{agent.name}_{internal_topic_type}"

    def _validate_handoffs(self) -> None:
        """Validate the handoffs to ensure all connections are valid."""
        if not self._handoffs:
            raise ValueError("Handoffs cannot be empty. Please provide at least one handoff connection.")

        member_names = {m.name for m in self._members}
        for agent_name, connections in self._handoffs.items():
            if agent_name not in member_names:
                raise ValueError(f"Agent {agent_name} is not a member of the handoff group.")
            for handoff_agent_name in connections:
                if handoff_agent_name not in member_names:
                    raise ValueError(f"Agent {handoff_agent_name} is not a member of the handoff group.")
                if handoff_agent_name == agent_name:
                    raise ValueError(f"Agent {agent_name} cannot handoff to itself.")


# endregion HandoffOrchestration

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Remove any handoff where source == target.
  2. When generating handoffs programmatically, skip the case where the two agents are identical.
  3. Review the handoff list for reflexive edges before constructing the orchestration.

Example fix

# before
handoffs = [Handoff(agent_a, agent_a), Handoff(agent_a, agent_b)]
# after - drop the self-handoff
handoffs = [Handoff(agent_a, agent_b)]
Defensive patterns

Strategy: validation

Validate before calling

# Reject self-handoffs before constructing:
for h in handoffs:
    src = h.source.name if hasattr(h.source, "name") else h.source
    tgt = h.target.name if hasattr(h.target, "name") else h.target
    assert src != tgt, f"Agent '{src}' cannot hand off to itself"
handoffs = [h for h in handoffs if source_of(h) != target_of(h)]

Try / catch

try:
    orchestration = HandoffOrchestration(members=members, handoffs=handoffs)
except ValueError as ex:
    if "cannot handoff to itself" in str(ex):
        handoffs = [h for h in handoffs if name(h.source) != name(h.target)]
        orchestration = HandoffOrchestration(members=members, handoffs=handoffs)

Prevention

When it happens

Trigger: A Handoff(agent_x, agent_x) is provided where both source and target resolve to the same agent name. Can happen when handoffs are generated programmatically (e.g. all-pairs) without excluding the diagonal, or via a copy-paste mistake.

Common situations: Auto-generating handoffs in a loop over members and forgetting to skip self-pairs; copy-pasting a Handoff and forgetting to change the target; accidentally adding a reflexive edge when refactoring.

Related errors


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