Skip to content
Back to skills

Dr Mas

ASecurity

Enable stable multi-agent reinforcement learning by normalizing advantages per-agent rather than globally, preventing gradient-norm inflation in heterogeneous multi-agent systems.

  • 6 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 9, 2026
ai-agentspython

Works with

  • terminal

Security analysis

A100/100

Scanned September 9, 2026

npx -y skills add ADu2021/skillXiv --skill dr-mas --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dr Mas?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dr Mas
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/adu2021-dr-mas/badge)](https://www.skillsdirectory.com/skills/adu2021-dr-mas)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: dr-mas
title: "Dr. MAS: Stable RL for Multi-Agent LLM Systems"
version: 0.0.2
engine: skillxiv-v0.0.2-claude-opus-4.6
license: MIT
url: "https://arxiv.org/abs/2602.08847"
keywords: [Multi-Agent RL, GRPO, Advantage Normalization, Agent Orchestration, Gradient Stability]
description: "Enable stable multi-agent reinforcement learning by normalizing advantages per-agent rather than globally, preventing gradient-norm inflation in heterogeneous multi-agent systems."
---

# Dr. MAS: Stable RL for Multi-Agent LLM Systems

## Problem Context

When applying GRPO (Group Relative Policy Optimization) to multi-agent systems, agents with different reward distributions experience **gradient-norm inflation**. A global reward baseline poorly aligned with some agents' reward statistics causes their gradients to explode, destabilizing training. This is especially severe in heterogeneous setups where agents play specialized roles.

## Core Concept

**Agent-Wise Advantage Normalization (Dr. MAS)** replaces global advantage normalization with per-agent normalization. Each agent normalizes advantages using its own reward statistics (μₖ, σₖ) rather than a global baseline, preventing gradient scaling mismatches while enabling stable co-training of heterogeneous agents.

## Architecture Overview

- **Multi-Agent Orchestration**: Flexible framework supporting different agent architectures and roles
- **Per-Agent Reward Tracking**: Partition experiences by agent; compute agent-specific reward statistics
- **Advantage Normalization**: Normalize each agent's advantages using its own mean/variance
- **Shared Resource Pooling**: Optional model weight sharing and efficient GPU scheduling
- **Gradient Stability**: Prevent norm inflation through per-agent normalization

## Implementation

**Phase 1: Multi-Agent Experience Collection**

```python
class MultiAgentOrchestrator:
    """Coordinate multiple LLM agents with per-agent reward tracking"""

    def __init__(self, agents, shared_model=None):
        self.agents = agents  # List of agent configurations
        self.shared_model = shared_model  # Optional shared LLM
        self.experience_buffer = defaultdict(list)

    def collect_trajectory(self, task, max_steps=10):
        """
        Collect multi-agent trajectory for a task.
        Different agents may activate at different steps.
        """

        state = task.initial_state()
        trajectory = {
            'task': task,
            'steps': [],
            'agent_assignments': []  # Which agent acted at each step
        }

        for step in range(max_steps):
            # Determine which agent should act (e.g., via task router)
            agent_id = select_agent_for_step(self.agents, state, step)
            agent = self.agents[agent_id]

            # Agent generates action
            action = agent.act(state)

            # Execute action in environment
            next_state, reward = task.step(action)

            trajectory['steps'].append({
                'agent_id': agent_id,
                'state': state,
                'action': action,
                'reward': reward,
                'next_state': next_state
            })
            trajectory['agent_assignments'].append(agent_id)

            state = next_state

            if task.is_terminal(state):
                break

        return trajectory

    def partition_by_agent(self, trajectory):
        """
        Partition trajectory steps by agent for per-agent normalization.
        Returns: dict[agent_id] -> list of (state, action, reward) tuples
        """

        agent_experiences = defaultdict(list)

        for step in trajectory['steps']:
            agent_id = step['agent_id']
            agent_experiences[agent_id].append({
                'state': step['state'],
                'action': step['action'],
                'reward': step['reward']
            })

        return agent_experiences
```

**Phase 2: Per-Agent Reward Statistics**

```python
def compute_per_agent_statistics(experiences, agents):
    """
    Compute reward mean and variance for each agent separately.

    experiences: dict[agent_id] -> list of reward values
    """

    agent_stats = {}

    for agent_id, agent_exps in experiences.items():
        rewards = [exp['reward'] for exp in agent_exps]

        # Compute mean and std
        mean = np.mean(rewards) if rewards else 0.0
        std = np.std(rewards) if rewards else 1.0

        # Add small epsilon to prevent division by zero
        std = max(std, 1e-8)

        agent_stats[agent_id] = {
            'mean': mean,
            'std': std,
            'count': len(rewards)
        }

    return agent_stats
```

**Phase 3: Per-Agent Advantage Normalization**

```python
def compute_advantages_per_agent(trajectory, value_fn, agents,
                                agent_stats):
    """
    Compute advantages normalized per-agent using per-agent statistics.
    """

    advantages = []
    agent_assignments = trajectory['agent_assignments']

    for step_idx, step in enumerate(trajectory['steps']):
        agent_id = step['agent_id']
        state = step['state']
        reward = step['reward']
        next_state = step['next_state']

        # Compute TD residual
        value_current = value_fn(state)
        value_next = value_fn(next_state)
        td_residual = reward + 0.99 * value_next - value_current

        # Normalize using agent-specific statistics
        stats = agent_stats[agent_id]
        advantage = (td_residual - stats['mean']) / stats['std']

        advantages.append(advantage)

    return advantages

def per_agent_advantage_normalization(trajectory, value_fn, agents):
    """
    Full pipeline for per-agent normalization.
    """

    # Partition trajectory by agent
    agent_experiences = defaultdict(list)
    for step_idx, step in enumerate(trajectory['steps']):
        agent_id = step['agent_id']
        agent_experiences[agent_id].append({
            'step_idx': step_idx,
            'state': step['state'],
            'reward': step['reward'],
            'next_state': step['next_state']
        })

    # Compute per-agent statistics
    agent_stats = {}
    for agent_id, exps in agent_experiences.items():
        rewards = [exp['reward'] for exp in exps]
        mean = np.mean(rewards)
        std = np.std(rewards) + 1e-8
        agent_stats[agent_id] = {'mean': mean, 'std': std}

    # Compute advantages with per-agent normalization
    advantages = []
    for step_idx, step in enumerate(trajectory['steps']):
        agent_id = step['agent_id']
        reward = step['reward']

        value_curr = value_fn(step['state'])
        value_next = value_fn(step['next_state'])
        td = reward + 0.99 * value_next - value_curr

        # Apply per-agent normalization
        stats = agent_stats[agent_id]
        advantage = (td - stats['mean']) / stats['std']

        advantages.append(advantage)

    return advantages
```

**Phase 4: GRPO Update with Per-Agent Advantages**

```python
def grpo_update_per_agent(model, trajectories, value_fn, agents):
    """
    Group Relative Policy Optimization with per-agent advantage normalization.
    """

    for group in trajectories:  # Batch of trajectories
        # Compute per-agent advantages
        advantages = per_agent_advantage_normalization(
            group, value_fn, agents
        )

        # Compute log probabilities
        logprobs = []
        for step_idx, step in enumerate(group['steps']):
            agent_id = step['agent_id']
            state = step['state']
            action = step['action']

            agent = agents[agent_id]
            logprob = agent.log_probability(state, action)
            logprobs.append(logprob)

        logprobs = torch.stack(logprobs)
        advantages = torch.tensor(advantages)

        # GRPO loss (simplified)
        # Compare trajectories within group
        advantage_mean = advantages.mean()
        advantage_std = advantages.std() + 1e-8

        normalized_advantages = (advantages - advantage_mean) / advantage_std

        # Policy loss
        loss = -torch.mean(normalized_advantages * logprobs)

        loss.backward()
        optimizer.step()

        # Value function update
        returns = compute_returns(group)
        value_loss = mse_loss(value_fn(group['states']), returns)
        value_loss.backward()
        value_optimizer.step()
```

**Phase 5: Optional Model Sharing**

```python
class SharedLLMMultiAgent:
    """
    Multi-agent system with shared LLM backbone.
    Each agent has task-specific prompt/prefix.
    """

    def __init__(self, base_model, agent_configs):
        self.base_model = base_model
        self.agent_configs = agent_configs

    def act(self, agent_id, state):
        """Agent-specific action generation via prompting"""
        agent_config = self.agent_configs[agent_id]
        prompt = agent_config['system_prompt']

        # Append state context
        full_prompt = f"{prompt}\n\nState: {state}"

        # Generate action from shared model
        action = self.base_model.generate(full_prompt)

        return action
```

## Practical Guidance

**When to use**: Deploy for heterogeneous multi-agent systems (e.g., planner agent, executor agent, verifier agent) where agents have different roles and reward distributions.

**Agent design**: Define clear responsibilities per agent to ensure meaningful per-agent reward statistics. Agents with similar reward distributions can be grouped together.

**Shared models**: Model sharing reduces memory footprint but may introduce competition during training. Start without sharing; add if memory is tight.

**Agent configuration**: Each agent needs learning rate, entropy coefficient, and other hyperparameters. Can reuse across agents or tune per-agent.

**Reward signal design**: Ensure reward signals are agent-specific (e.g., planner rewarded for quality plan, executor for execution fidelity). Misaligned rewards prevent benefits of per-agent normalization.

## Reference

Dr. MAS achieves +5.6% average improvement over vanilla GRPO while dramatically reducing gradient spikes, enabling stable co-training of heterogeneous agents. The key insight is that per-agent normalization prevents gradient scaling mismatches arising from different reward distributions, crucial for multi-agent systems where agents have specialized roles and different learning curves.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…