0

Establish an AI proxy framework based on multi-node graphs to automate complex tasks

In this tutorial, we guide you in developing an advanced graphics proxy framework powered by the Google Gemini API. Our goal is to build intelligent multi-step agents that perform tasks through a clear graphical structure of interconnected nodes. Each node represents a specific function, from making input, performing logical processing, making decisions and generating output. We use Python, NetworkX for graph modeling, and Matplotlib for visualization. Finally, we implement and run two complete examples, a research assistant and a solution, to illustrate how the framework effectively handles complex inference workflows.

!pip install -q google-generativeai networkx matplotlib


import google.generativeai as genai
import networkx as nx
import matplotlib.pyplot as plt
from typing import Dict, List, Any, Callable
import json
import asyncio
from dataclasses import dataclass
from enum import Enum


API_KEY = "use your API key here"
genai.configure(api_key=API_KEY)

We first install the necessary libraries, Google-generativeai, NetworkX, and Matplotlib to support our graph-based proxy framework. After importing the required modules, we configure the Gemini API using our API key to enable powerful content generation capabilities in the proxy system.

Check Code.

class NodeType(Enum):
    INPUT = "input"
    PROCESS = "process"
    DECISION = "decision"
    OUTPUT = "output"


@dataclass
class AgentNode:
    id: str
    type: NodeType
    prompt: str
    function: Callable = None
    dependencies: List[str] = None

We define an enum to classify different kinds of proxy nodes: input, process, decision, and output. Then, using Dataclass AgentNode, we build each node with ID, type, prompt, optional features, and dependency lists, allowing us to build modular and flexible proxy graphs.

def create_research_agent():
    agent = GraphAgent()
   
    # Input node
    agent.add_node(AgentNode(
        id="topic_input",
        type=NodeType.INPUT,
        prompt="Research topic input"
    ))
   
    agent.add_node(AgentNode(
        id="research_plan",
        type=NodeType.PROCESS,
        prompt="Create a comprehensive research plan for the topic. Include 3-5 key research questions and methodology.",
        dependencies=["topic_input"]
    ))
   
    agent.add_node(AgentNode(
        id="literature_review",
        type=NodeType.PROCESS,
        prompt="Conduct a thorough literature review. Identify key papers, theories, and current gaps in knowledge.",
        dependencies=["research_plan"]
    ))
   
    agent.add_node(AgentNode(
        id="analysis",
        type=NodeType.PROCESS,
        prompt="Analyze the research findings. Identify patterns, contradictions, and novel insights.",
        dependencies=["literature_review"]
    ))
   
    agent.add_node(AgentNode(
        id="quality_check",
        type=NodeType.DECISION,
        prompt="Evaluate research quality. Is the analysis comprehensive? Are there missing perspectives? Return 'APPROVED' or 'NEEDS_REVISION' with reasons.",
        dependencies=["analysis"]
    ))
   
    agent.add_node(AgentNode(
        id="final_report",
        type=NodeType.OUTPUT,
        prompt="Generate a comprehensive research report with executive summary, key findings, and recommendations.",
        dependencies=["quality_check"]
    ))
   
    return agent

We create a research agent by adding specialized node order to the chart. Starting with topic input, we define a process flow that includes planning, literature review, and analysis. The agent then made quality decisions based on the research and eventually generated a comprehensive research report, thus capturing the full life cycle of the structured research workflow.

Check Code.

def create_problem_solver():
    agent = GraphAgent()
   
    agent.add_node(AgentNode(
        id="problem_input",
        type=NodeType.INPUT,
        prompt="Problem statement"
    ))
   
    agent.add_node(AgentNode(
        id="problem_analysis",
        type=NodeType.PROCESS,
        prompt="Break down the problem into components. Identify constraints and requirements.",
        dependencies=["problem_input"]
    ))
   
    agent.add_node(AgentNode(
        id="solution_generation",
        type=NodeType.PROCESS,
        prompt="Generate 3 different solution approaches. For each, explain the methodology and expected outcomes.",
        dependencies=["problem_analysis"]
    ))
   
    agent.add_node(AgentNode(
        id="solution_evaluation",
        type=NodeType.DECISION,
        prompt="Evaluate each solution for feasibility, cost, and effectiveness. Rank them and select the best approach.",
        dependencies=["solution_generation"]
    ))
   
    agent.add_node(AgentNode(
        id="implementation_plan",
        type=NodeType.OUTPUT,
        prompt="Create a detailed implementation plan with timeline, resources, and success metrics.",
        dependencies=["solution_evaluation"]
    ))
   
    return agent

We construct problem-solving factors by defining the logical sequence of nodes, starting from receiving the problem statement. Agents analyze problems, generate multiple solution methods, evaluate them based on feasibility and effectiveness, and end them by developing a structured implementation plan, thus automating the problem and gradually solving the problem.

Check Code.

def run_research_demo():
    """Run the research agent demo"""
    print("šŸš€ Advanced Graph Agent Framework Demo")
    print("=" * 50)
   
    research_agent = create_research_agent()
    print("nšŸ“Š Research Agent Graph Structure:")
    research_agent.visualize()
   
    print("nšŸ” Executing Research Task...")
   
    research_agent.results["topic_input"] = "Artificial Intelligence in Healthcare"
   
    execution_order = list(nx.topological_sort(research_agent.graph))
   
    for node_id in execution_order:
        if node_id == "topic_input":
            continue
           
        context = {}
        node = research_agent.nodes[node_id]
       
        if node.dependencies:
            for dep in node.dependencies:
                context[dep] = research_agent.results.get(dep, "")
       
        prompt = node.prompt
        if context:
            context_str = "n".join([f"{k}: {v}" for k, v in context.items()])
            prompt = f"Context:n{context_str}nnTask: {prompt}"
       
        try:
            response = research_agent.model.generate_content(prompt)
            result = response.text.strip()
            research_agent.results[node_id] = result
            print(f"āœ“ {node_id}: {result[:100]}...")
        except Exception as e:
            research_agent.results[node_id] = f"Error: {str(e)}"
            print(f"āœ— {node_id}: Error - {str(e)}")
   
    print("nšŸ“‹ Research Results:")
    for node_id, result in research_agent.results.items():
        print(f"n{node_id.upper()}:")
        print("-" * 30)
        print(result)
   
    return research_agent.results


def run_problem_solver_demo():
    """Run the problem solver demo"""
    print("n" + "=" * 50)
    problem_solver = create_problem_solver()
    print("nšŸ› ļø Problem Solver Graph Structure:")
    problem_solver.visualize()
   
    print("nāš™ļø Executing Problem Solving...")
   
    problem_solver.results["problem_input"] = "How to reduce carbon emissions in urban transportation"
   
    execution_order = list(nx.topological_sort(problem_solver.graph))
   
    for node_id in execution_order:
        if node_id == "problem_input":
            continue
           
        context = {}
        node = problem_solver.nodes[node_id]
       
        if node.dependencies:
            for dep in node.dependencies:
                context[dep] = problem_solver.results.get(dep, "")
       
        prompt = node.prompt
        if context:
            context_str = "n".join([f"{k}: {v}" for k, v in context.items()])
            prompt = f"Context:n{context_str}nnTask: {prompt}"
       
        try:
            response = problem_solver.model.generate_content(prompt)
            result = response.text.strip()
            problem_solver.results[node_id] = result
            print(f"āœ“ {node_id}: {result[:100]}...")
        except Exception as e:
            problem_solver.results[node_id] = f"Error: {str(e)}"
            print(f"āœ— {node_id}: Error - {str(e)}")
   
    print("nšŸ“‹ Problem Solving Results:")
    for node_id, result in problem_solver.results.items():
        print(f"n{node_id.upper()}:")
        print("-" * 30)
        print(result)
   
    return problem_solver.results


print("šŸŽÆ Running Research Agent Demo:")
research_results = run_research_demo()


print("nšŸŽÆ Running Problem Solver Demo:")
problem_results = run_problem_solver_demo()


print("nāœ… All demos completed successfully!")

We summarized the tutorial by running two powerful demo agents, one for research and the other for problem solving. In each case, we visualize the graph structure, initialize the input, and execute the proxy nodes in topological order. As Gemini generates contextual responses at each step, we observe how each agent produces autonomous progress through planning, analytics, decisions, and outputs, ultimately demonstrating the full potential of our graph-based framework.

In summary, we successfully developed and executed smart agents that decompose and solve tasks using graph-driven architecture. We see how each node handles context dependency prompts, leverages Gemini’s functionality to generate content, and pass the results to subsequent nodes. This modular design enhances flexibility and also allows us to clearly see the logic flow.

Check Code. All credits for this study are to the researchers on the project. Subscribe now To our AI newsletter


Asif Razzaq is CEO of Marktechpost Media Inc. As a visionary entrepreneur and engineer, ASIF is committed to harnessing the potential of artificial intelligence to achieve social benefits. His recent effort is to launch Marktechpost, an artificial intelligence media platform that has an in-depth coverage of machine learning and deep learning news that can sound both technically, both through technical voices and be understood by a wide audience. The platform has over 2 million views per month, demonstrating its popularity among its audience.