Multi-agent workflow
WARNING
For those who haven't updated, please cd into ai directory and run pipenv update to update the dependencies.
It is recommended to set AUTOGEN_DISABLE_RUNTIME_TRACING to true in the environment variables to remove the runtime tracing.
INFO
It is currently in the early stages of development, so expect some changes in the future. GraphFlow is also in early development according to the Autogen documentation.
This do not account into the technical details of how the agents message are delivered to end users.
At SocratesCode, we use Autogen and currently with GraphFlow to build our multi-agent AI system.
Framework overview
Autogen is a tool provided by Microsoft that allows you to build AI system. It features many preset agents and groups, allowing you to build agentic AI applications.
📄 Official documentation: Autogen Documentation
📄 User guide about GraphFlow: Graphflow documentation
Workflow overview
Now that we have a basic understanding of Autogen, let's look at how we use its GraphFlow to build our AI system.
GraphFlow is, simply put, a programming "flowchart" for AI agents. It utilizes a directed acyclic graph (DAG) to represent the flow of data and control between agents. This is useful especially considering the unpredictable nature of AI, as it allows us to have finer control over how agents work, interact and communicate with each other via autogen's API.
Current workflow
See the diagram in the technical documentation for more detailed overview of the current workflow.
In this section, we will go through how the workflow works (and customize it) step by step.
Most of the guide below is a practical guide on how to customize the workflow or implement a new agent. For more detailed information, please refer to the Autogen documentation.
For demonstration purposes, we will use fictional agents agent_a, agent_b, and agent_c. You can replace these with the actual agents you want to use in your workflow.
Adding a new agent
After configuring the agents beforehand, we can add them as a node to the GraphFlow builder by adding it as a node to the graph builder. You can do it by the following code snippet:
builder = DiGraphBuilder()
builder.add_node(agent_a).add_node(agent_b).add_node(YOUR_AGENT_HERE)(These agents are fictional for demonstration purposes. You can replace YOUR_AGENT_HERE with the actual agent you want to add).
We can use the add_node() method with the model variable name to add the new agent to the graph builder. This will register the agent as a node in the graph, allowing it to be used in the workflow that we are going to do below.
Configuring the workflow
Now that we have added the agents, let's add (or modify) the workflow to include the new agent. Here we will use directional edges (a concept from graph theory) to connect the nodes (agents) together in a way similar to the flowchart, allowing them to communicate with each other.
builder.add_edge(agent_a, agent_b)
builder.add_edge(agent_b, agent_c)
builder.add_edge(agent_c, YOUR_AGENT_HERE)The sequences will be executed in the left-right order, so the agents will communicate with each other in the order that we specify.
Additionally, we can also add conditional edges to the graph, allowing us to control the flow of the graph based on the output of the agents. This is useful for implementing complex workflows that require conditional logic.
builder.add_conditional_edge(agent_a, agent_b, condition=lambda x: x == "some_condition")Beside one-way conditional edges, in SocratesCode, we have a loop that would loop back to the initial agent, given the "DISAPPROVE" message from the agent. However, Autogen have troubling with the cycle deadlock, so they provided a way to handle this with the parameter "activation_group". Below is the example of the code:
builder.add_conditional_edge(agent_b, agent_c, condition=lambda x: x == "some_condition", activation_group="initial")
# ... other edges
# at near end, it loops back to the initial agent
builder.add_conditional_edge(agent_e, agent_b, condition=lambda x: x == "some_condition", activation_group="rejected")Deep dive
This separation separates the initial flow state, preventing the deadlock from happening.
Running the workflow
After configuring the shape of the graph, we can now build it using builder.build() method. This is then parsed as a parameter to the GraphFlow constructor, which will create the GraphFlow object that we use in the final application
graph = builder.build()
graph_flow = GraphFlow(participants=[agent_a, agent_b, agent_c, YOUR_AGENT_HERE], graph=graph)participants is a list of agents that we want to include in the workflow, and graph is the directed acyclic graph that we built using the DiGraphBuilder. Additionally, for group with more participants, we can use builder.get_participants() instead of listing.