Building Nested Group Chat Hierarchies with DiGraphGroupChat in Autogen

Microsoft Autogen enables arbitrarily deep nested group chat hierarchies by modeling conversations as directed graphs (DiGraph), where each node represents an agent or sub-group, and edges define conditional message routing between parent and child groups.

Building nested group chat hierarchies with DiGraphGroupChat allows you to orchestrate complex multi-agent workflows in Microsoft Autogen. The framework treats group chats as directed graphs where nodes can be individual agents or entire sub-groups, enabling recursive nesting that mirrors organizational structures. This architecture, implemented in the autogen_agentchat package, provides precise control over conversation flow through conditional edges and automatic cycle detection.

Core DiGraph Components for Hierarchical Chats

The DiGraphGroupChat system relies on four foundational classes defined in autogen_agentchat/teams/_group_chat/_graph/_digraph_group_chat.py:

  • DiGraphNode – A Pydantic model that stores an agent's name and a list of outgoing edges. Each node represents a participant in the chat hierarchy, which can be either a single agent or an entire sub-group manager.

  • DiGraphEdge – Describes a directed edge containing the target node name and optional condition or activation_condition parameters. These conditions control when the edge is traversed, enabling logic like "route to TeamA only if trigger1 is present."

  • DiGraph – The container class that maps node names to DiGraphNode instances. It validates the graph structure (detecting cycles and missing nodes) and provides utilities for traversal and serialization via model_dump_json() and model_validate_json().

  • DiGraphBuilder – Located in autogen_agentchat/teams/_group_chat/_graph/_graph_builder.py, this helper constructs a DiGraph from user-friendly dictionaries or YAML/JSON specifications, simplifying the creation of complex nested configurations.

How Message Routing Works in Nested Hierarchies

The runtime execution follows a strict traversal protocol managed by GroupChatManager:

  1. Graph Definition – You instantiate a DiGraph with nodes and edges describing your hierarchy, from root groups down to leaf agents.

  2. Manager InstantiationGroupChatManager receives the DiGraph and creates separate agent instances for every node. When a node represents a nested group, you pass sub-managers via the sub_managers parameter.

  3. Message Flow – When an agent sends a message, the manager examines outgoing edges from the current node. If an edge includes a condition, the manager evaluates it against the message content. Passing conditions forward the message to the target node, which becomes the new active participant.

  4. Nested Execution – Because each node can itself be a GroupChatManager, the parent graph treats the child manager as a single node. Control returns to the parent only after the child group reaches a termination condition or exhausts its own edges.

  5. Cycle Prevention – The DiGraph validator detects cycles lacking termination conditions and raises an error. Conditional cycles are explicitly permitted (e.g., "repeat until trigger X"), allowing iterative refinement loops within nested structures.

  6. Persistence – The entire hierarchy serializes to JSON via Pydantic's model_dump_json(), enabling you to save complex organizational topologies and reconstruct them later with model_validate_json().

Implementing Nested Group Chat Hierarchies

Simple Two-Level Hierarchy

Create a root chat that spawns a team, which then spawns a sub-team:

from autogen_agentchat.teams._group_chat._graph._digraph_group_chat import (
    DiGraph, DiGraphNode, DiGraphEdge
)
from autogen_agentchat.teams.group_chat_manager import GroupChatManager

# Define the graph structure

graph = DiGraph(
    {
        "Root": DiGraphNode(
            name="Root",
            edges=[DiGraphEdge(target="TeamA")]
        ),
        "TeamA": DiGraphNode(
            name="TeamA",
            edges=[DiGraphEdge(target="SubTeam1")]
        ),
        "SubTeam1": DiGraphNode(name="SubTeam1", edges=[])
    }
)

# Instantiate and run

manager = GroupChatManager(graph=graph, name="RootChat")
manager.run()

Conditional Branching Between Teams

Route messages to different teams based on content triggers:

graph = DiGraph(
    {
        "Root": DiGraphNode(
            name="Root",
            edges=[
                DiGraphEdge(target="TeamA", condition="trigger1"),
                DiGraphEdge(target="TeamB", condition="trigger2")
            ]
        ),
        "TeamA": DiGraphNode(name="TeamA", edges=[]),
        "TeamB": DiGraphNode(name="TeamB", edges=[])
    }
)

The manager evaluates the condition string against incoming messages to determine whether to activate TeamA or TeamB.

Deep Nesting with Child Managers

Embed a complete sub-hierarchy within a parent graph by passing child managers:

from autogen_agentchat.teams.group_chat_manager import GroupChatManager

# Parent graph references child group as a single node

parent_graph = DiGraph(
    {
        "Root": DiGraphNode(name="Root", edges=[DiGraphEdge(target="ChildGroup")]),
        "ChildGroup": DiGraphNode(name="ChildGroup", edges=[]),
    }
)

# Child graph defines its own internal workflow

child_graph = DiGraph(
    {
        "SubRoot": DiGraphNode(name="SubRoot", edges=[DiGraphEdge(target="Leaf")]),
        "Leaf": DiGraphNode(name="Leaf", edges=[])
    }
)

# Wire nested managers

child_manager = GroupChatManager(graph=child_graph, name="ChildGroup")
parent_manager = GroupChatManager(
    graph=parent_graph,
    name="RootChat",
    sub_managers={"ChildGroup": child_manager}
)

parent_manager.run()

When RootChat activates ChildGroup, the child manager executes its internal graph independently before returning control upstream.

Persisting Graph Structures

Serialize complex hierarchies for distributed deployment or session recovery:


# Export to JSON

json_str = graph.model_dump_json()

# Restore in another process

restored_graph = DiGraph.model_validate_json(json_str)

This preserves the exact node-to-edge relationships and conditional logic required to recreate the nested hierarchy elsewhere.

Key Source Files and Architecture

The DiGraphGroupChat implementation spans these critical files in the autogen_agentchat package:

Summary

  • DiGraphGroupChat models conversations as directed graphs where nodes are agents or sub-groups and edges define message routing rules.

  • DiGraphNode and DiGraphEdge provide the structural foundation, while DiGraph handles validation and serialization in autogen_agentchat/teams/_group_chat/_graph/_digraph_group_chat.py.

  • Nesting occurs when a GroupChatManager is registered as a sub-manager in another manager's sub_managers dictionary, allowing recursive hierarchy depths.

  • Conditional routing uses the condition parameter on edges to dynamically select conversation paths based on message content.

  • Cycle detection prevents infinite loops by validating graphs at initialization, though intentional conditional cycles are supported for iterative workflows.

  • Serialization via Pydantic methods enables persistence and transmission of complex chat topologies across processes.

Frequently Asked Questions

What is DiGraphGroupChat in Autogen?

DiGraphGroupChat is an Autogen architecture that represents group chats as directed graphs rather than simple round-robin or random selections. Each node in the graph is a DiGraphNode representing an agent or nested group, and edges (DiGraphEdge) define allowed conversation flows, including conditional branching logic. This enables complex hierarchical workflows where parent groups can spawn child groups indefinitely.

How do you prevent infinite loops in nested group chats?

The DiGraph class automatically validates the graph structure upon instantiation in autogen_agentchat/teams/_group_chat/_graph/_digraph_group_chat.py. It detects cycles that lack termination conditions and raises validation errors before execution begins. You can create intentional loops by adding conditional edges (e.g., condition="retry_needed"), which require explicit trigger content to cycle back, preventing runaway execution.

Can you serialize and reuse a DiGraph hierarchy across sessions?

Yes. Because DiGraph inherits from Pydantic's BaseModel, you can call model_dump_json() to export the entire hierarchy—including all nodes, edges, and conditions—to a JSON string. Later, use DiGraph.model_validate_json() to reconstruct the exact graph structure. This supports saving complex organizational topologies and deploying them across distributed environments.

How does conditional routing work between parent and child groups?

When GroupChatManager processes a message, it evaluates the condition or activation_condition attribute on each outgoing DiGraphEdge. If the condition matches the message content (e.g., a specific trigger string), the manager forwards the message to the target node. If the target is a nested child manager (registered in sub_managers), the parent delegates control entirely to the child until that sub-graph completes its execution, at which point the parent resumes its own traversal logic.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →