Skip to content

GNN Routing

Use Graph Neural Networks for intelligent agent routing.

Overview

gMAS provides PyTorch Geometric integration that enables GNN-based routing. Instead of static edges, a GNN can learn which agents should communicate based on the task and intermediate results.

Converting to PyG Format

from gmas.core import AgentProfile
from gmas.builder import build_property_graph

agents = [
    AgentProfile(agent_id=f"agent_{i}", display_name=f"Agent {i}")
    for i in range(5)
]

graph = build_property_graph(
    agents,
    workflow_edges=[
        ("agent_0", "agent_1"),
        ("agent_0", "agent_2"),
        ("agent_1", "agent_3"),
        ("agent_2", "agent_3"),
        ("agent_3", "agent_4"),
    ],
    query="Example query",
)

pyg_data = graph.to_pyg_data()
print(pyg_data)
# Data(x=[6, 768], edge_index=[2, 10])  # 5 agents + 1 task node

Custom Node/Edge Features

# Add custom features to the PyG data
node_features = {
    "trust_score": torch.tensor([0.9, 0.8, 0.95, 0.7, 0.85, 0.0]),
}
edge_features = {
    "reliability": torch.tensor([0.9, 0.8, 0.85, 0.7, 0.95,
                                  0.9, 0.8, 0.85, 0.7, 0.95]),
}

pyg_data = graph.to_pyg_data(
    node_features=node_features,
    edge_features=edge_features,
    include_embeddings=True,
    include_default_edge_attr=True,
)

Training a GNN Router

import torch
import torch.nn.functional as F
from torch_geometric.nn import GATConv

class GNNRouter(torch.nn.Module):
    def __init__(self, in_channels: int = 768, hidden_channels: int = 128):
        super().__init__()
        self.conv1 = GATConv(in_channels, hidden_channels, heads=4)
        self.conv2 = GATConv(hidden_channels * 4, hidden_channels, heads=1)

    def forward(self, x, edge_index):
        x = self.conv1(x, edge_index).relu()
        x = self.conv2(x, edge_index)
        return x

    def predict_adjacency(self, x, edge_index, num_nodes):
        node_embs = self.forward(x, edge_index)
        # Compute pairwise scores
        scores = torch.mm(node_embs, node_embs.T)
        return torch.sigmoid(scores)

model = GNNRouter()

Updating Graph Communication

Use GNN output to update the graph's adjacency matrix:

# Get predictions from the GNN
new_A = model.predict_adjacency(pyg_data.x, pyg_data.edge_index, num_nodes=5)

# Update the graph with new routing
graph.update_communication(
    A_com=new_A,        # New adjacency matrix
    s_tilde=None,       # Optional score matrix
    p_matrix=None,      # Optional probability matrix
)

# Now run execution with the GNN-routed graph
result = runner.run_round(graph)

GNN Routing Module

gMAS provides built-in GNN models:

from gmas.core.gnn import GCN, GAT, GraphSAGE

# GCN routing
model = GCN(in_channels=768, hidden_channels=128, out_channels=64)

# GAT routing (with attention)
model = GAT(in_channels=768, hidden_channels=128, out_channels=64, heads=4)

# GraphSAGE routing
model = GraphSAGE(in_channels=768, hidden_channels=128, out_channels=64)

Node Encoder

Encode agent descriptions into embeddings for GNN input:

from gmas.core import NodeEncoder

encoder = NodeEncoder(model_name="all-MiniLM-L6-v2")

# Encode single agent
embedding = encoder.encode(agent)

# Encode batch
embeddings = encoder.encode_batch(agents)

# Assign embeddings to agents
for agent, emb in zip(agents, embeddings):
    agent = agent.with_embedding(emb)

Full GNN Routing Pipeline

# 1. Create and encode agents
encoder = NodeEncoder()
agents = [agent.with_embedding(emb) for agent, emb in
          zip(agents, encoder.encode_batch(agents))]

# 2. Build graph
graph = build_property_graph(agents, workflow_edges=edges, query="...")

# 3. Convert to PyG
pyg_data = graph.to_pyg_data()

# 4. Run GNN
new_A = model.predict_adjacency(pyg_data.x, pyg_data.edge_index, len(agents))

# 5. Update routing
graph.update_communication(A_com=new_A)

# 6. Execute
result = runner.run_round(graph)