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
- Remove any handoff where source == target.
- When generating handoffs programmatically, skip the case where the two agents are identical.
- 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 generating handoffs programmatically, skip self-pairs.
- Review the handoff list for reflexive edges before construction.
- Add a unit test asserting no source equals its target.
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
- The agent {agent.Name ?? agent.Id} cannot have a handoff to
- The following agents are not defined in the orchestration: {
- Entry agent is not defined.
- Handoffs cannot be empty. Please provide at least one handof
- Agent {agent_name} is not a member of the handoff group.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/09905d14d412794d.
Report an issue: GitHub.