Skip to content

Infinite recursion in src/agents/extensions/visualization.py due to circular references #668

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
qinqiang2000 opened this issue May 9, 2025 · 2 comments · May be fixed by #737
Open

Infinite recursion in src/agents/extensions/visualization.py due to circular references #668

qinqiang2000 opened this issue May 9, 2025 · 2 comments · May be fixed by #737
Labels
bug Something isn't working

Comments

@qinqiang2000
Copy link

qinqiang2000 commented May 9, 2025

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.

@qinqiang2000 qinqiang2000 added the bug Something isn't working label May 9, 2025
@wassfila
Copy link

wassfila commented 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
Copy link
Author

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:

  1. A recursion-safe graph walk — I’ll patch get_all_nodes/edges to track a visited set so visualisation never overflows, even with cycles.

  2. 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.

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.

@rm-openai rm-openai linked a pull request May 21, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants