Closed
Description
Issue Description
The functions get_all_nodes
and get_all_edges
in src/agents/extensions/visualization.py
can lead to infinite recursion when there are circular references between agents (when agents form a cycle through handoffs).
Current Behavior
When agents have circular references through handoffs, the visualization functions will recursively traverse the agent graph without any cycle detection, leading to infinite recursion and eventual stack overflow.
Expected Behavior
The visualization functions should handle circular references gracefully by detecting cycles and preventing repeated traversal of the same agents.
Proposed Solution
Add a visited
set to track already visited agents and prevent repeated recursion. Here's a sketch of the fix:
def get_all_nodes(agent: Agent, parent: Optional[Agent] = None, visited: Optional[set] = None) -> str:
if visited is None:
visited = set()
if agent.name in visited: # Prevent infinite recursion
return ""
visited.add(agent.name)
# ... rest of the function ...
Similar changes would be needed for get_all_edges
.
Activity
wassfila commentedon May 12, 2025
Although this is technically possible(once the bug gets fixed), what sense does it make if agents keep forever turning in circle ? They might need a sort of memory context that allows to break the circle somehow. Note that it's always possible to use an Agent as a tool, and that agent could have many as a tools, the difference is that the Agent as a tool will Always return and the handoff "never". So I'd say maybe for your use case the framework needs to have a sort of "conditional return", which means it could then dynamically decide if it should handoff/keep the hand, or return like being called as a tool, that seems to me safer than handoff circles.
qinqiang2000 commentedon May 15, 2025
Hi @wassfila,
You’re right that an endless loop is pointless, but short, controlled cycles can be useful. Anthropic’s recent post on “Building Effective Agents” describes evaluator-optimizer (or “self-critique”) patterns where two agents deliberately hand a task back and forth until a shared stopping condition—accuracy threshold, max-iterations, etc.—is met. That requires:
A recursion-safe graph walk — I’ll patch get_all_nodes/edges to track a visited set so visualisation never overflows, even with cycles.
Conditional hand-offs — exposing a max_handoffs/“should return” hook so an agent can decide at runtime whether to hand off again or return like a tool call.
With those guards the framework supports both simple chains and the more autonomous, self-refining loops the blog highlights—without risking infinite spins.
Fix visualization recursion with cycle detection (openai#737)
Fix visualization recursion with cycle detection (openai#737)