# Emergent Behavior

When multi-agent systems exhibit behaviors not explicitly programmed: self-organization, specialization, and collective intelligence.

---

## What is Emergent Behavior?

> **Emergence**: System-level properties arising from local interactions that cannot be predicted from individual agent rules alone.

> "More is different" — P.W. Anderson

### Characteristics
| Property | Description |
|---|---|
| **Non-linearity** | Small changes → large effects |
| **Self-organization** | Order without central control |
| **Adaptivity** | System adapts to environment |
| **Robustness** | Graceful degradation |
| **Scalability** | Properties hold at scale |

---

## Types of Emergence

### 1. Self-Organization

#### Task Allocation
```python
# Agents self-organize task allocation without central coordinator
class SelfOrganizingAllocation:
    def __init__(self, agents: list[Agent]):
        self.agents = {a.name: a for a in agents}
    
    async def run(self, tasks: list[Task]) -> AllocationResult:
        # Agents bid based on local knowledge
        for task in tasks:
            bids = await asyncio.gather(*[
                a.bid(task) for a in self.agents.values()
            ])
            
            # Winner takes task
            winner = max(bids, key=lambda b: b.score)
            await self.agents[winner.agent_id].assign(task)
        
        return AllocationResult(allocations=self.get_allocations())
```

#### Role Specialization
```python
# Agents naturally specialize based on performance
class SpecializationEmergence:
    def __init__(self, agents: list[Agent]):
        self.agents = {a.name: a for a in agents}
        self.performance_history: dict[str, list[float]] = defaultdict(list)
    
    async def run_episode(self, tasks: list[Task]):
        # Agents self-select tasks
        for task in tasks:
            # Agents evaluate their fitness
            fitness = await asyncio.gather(*[
                a.evaluate_fitness(task) for a in self.agents.values()
            ])
            
            # Best fit takes task
            best_idx = max(range(len(fitness)), key=lambda i: fitness[i])
            agent = list(self.agents.values())[best_idx]
            result = await agent.execute(task)
            
            # Record performance
            self.performance_history[agent.name].append(result.score)
    
    def get_specializations(self) -> dict[str, str]:
        """Infer specialization from performance"""
        specializations = {}
        for agent_id, scores in self.performance_history.items():
            if len(scores) > 10:
                # Agent consistently good at certain task types
                pass  # Analysis would go here
        return specializations
```

#### Flocking / Swarming
```python
class FlockingBehavior:
    """
    Reynolds' Boids rules applied to agent coordination
    """
    def __init__(self, agents: list[Agent]):
        self.agents = {a.name: a for a in agents}
    
    def compute_velocity(self, agent_id: str, neighbors: list[Agent]) -> Vector:
        # Separation: avoid crowding
        separation = self.separation(agent_id, neighbors)
        
        # Alignment: steer toward average heading
        alignment = self.alignment(neighbors)
        
        # Cohesion: steer toward center of mass
        cohesion = self.cohesion(agent_id, neighbors)
        
        return separation + alignment + cohesion
    
    def separation(self, agent_id: str, neighbors: list[Agent]) -> Vector:
        pos = self.agents[agent_id].position
        force = Vector(0, 0)
        for n in neighbors:
            diff = pos - n.position
            dist = diff.magnitude()
            if dist > 0:
                force += diff.normalize() / (dist ** 2)
        return force
```

### 2. Stigmergy (Environment-Mediated Coordination)

```python
class StigmergicCoordination:
    """
    Indirect coordination through environment modification
    """
    def __init__(self):
        self.environment = StigmergicEnvironment()
    
    def agent_act(self, agent: Agent, action: Action) -> EnvironmentChange:
        # Agent modifies environment
        change = self.environment.apply(action)
        
        # Other agents sense change
        return change
    
    def example_ant_foraging(self):
        # Ant deposits pheromone → other ants follow trail
        # Trail evaporates → suboptimal paths disappear
        # Shortest path gets reinforced → optimal path emerges
        pass

class StigmergicEnvironment:
    def __init__(self):
        self.pheromones = defaultdict(float)
        self.artifacts = {}
        self.evaporation = 0.1
    
    def deposit(self, location: str, strength: float):
        self.pheromones[location] += strength
    
    def sense(self, location: str) -> float:
        return self.pheromones.get(location, 0)
    
    def evaporate(self):
        for loc in list(self.pheromones):
            self.pheromones[loc] *= (1 - self.evaporation)
            if self.pheromones[loc] < 0.01:
                del self.pheromones[loc]
```

### 3. Collective Intelligence

#### Prediction Markets
```python
class AgentPredictionMarket:
    def __init__(self, agents: list[Agent]):
        self.agents = {a.name: a for a in agents}
        self.markets: dict[str, PredictionMarket] = {}
    
    async def create_market(self, question: str, outcomes: list[str]) -> Market:
        market = PredictionMarket(question, outcomes)
        self.markets[question] = market
        return market
    
    async def trade(self, agent: Agent, question: str, 
                    outcome: str, shares: int, price: float) -> TradeResult:
        market = self.markets[question]
        return await market.place_bet(agent, outcome, shares, price)
    
    def get_prediction(self, question: str) -> dict[str, float]:
        """Aggregate prediction from market prices"""
        market = self.markets[question]
        return market.get_probabilities()
```

#### Ensemble Reasoning
```python
class EnsembleReasoning:
    def __init__(self, agents: list[Agent]):
        self.agents = {a.name: a for a in agents}
    
    async def reason(self, question: str) -> EnsembleResult:
        # Each agent reasons independently
        responses = await asyncio.gather(*[
            a.reason(question) for a in self.agents.values()
        ])
        
        # Aggregate
        return self.aggregate(responses)
    
    def aggregate(self, responses: list[ReasoningResult]) -> EnsembleResult:
        # Majority vote
        answers = [r.answer for r in responses]
        final_answer = max(set(answers), key=answers.count)
        
        # Confidence from agreement
        agreement = answers.count(final_answer) / len(answers)
        
        # Weighted by confidence
        weighted = sum(r.confidence for r in responses if r.answer == final_answer)
        
        return EnsembleResult(
            answer=final_answer,
            confidence=weighted / len(responses),
            agreement=agreement,
            individual_responses=responses
        )
```

### 4. Evolutionary Emergence

```python
class EvolutionaryAgentPopulation:
    def __init__(self, initial_agents: list[Agent]):
        self.population = initial_agents
        self.generation = 0
    
    async def evolve(self, generations: int, fitness_fn: FitnessFunction):
        for gen in range(generations):
            self.generation = gen
            
            # Evaluate fitness
            fitness_scores = await asyncio.gather(*[
                fitness_fn(agent) for agent in self.population
            ])
            
            # Selection
            parents = self.select_parents(self.population, fitness_scores)
            
            # Crossover + Mutation
            offspring = await self.crossover_and_mutate(parents)
            
            # Replace population
            self.population = offspring
            
            # Track best
            best_idx = max(range(len(fitness_scores)), key=lambda i: fitness_scores[i])
            logger.info(f"Gen {gen}: Best fitness = {fitness_scores[best_idx]}")
    
    def select_parents(self, population, fitness_scores):
        # Tournament selection
        parents = []
        for _ in range(len(population) // 2):
            tournament = random.sample(list(zip(population, fitness_scores)), 3)
            winner = max(tournament, key=lambda x: x[1])[0]
            parents.append(winner)
        return parents
```

---

## Measuring Emergence

### Metrics
| Metric | Description |
|---|---|
| **Order Parameter** | Degree of organization (0-1) |
| **Mutual Information** | Information shared between agents |
| **Transfer Entropy** | Information flow between agents |
| **Integrated Information (Φ)** | System irreducibility |
| **Complexity** | Balance between order and chaos |

### Measurement
```python
class EmergenceMetrics:
    def __init__(self, agents: list[Agent]):
        self.agents = agents
    
    def compute_order_parameter(self, states: list[AgentState]) -> float:
        """Kuramoto order parameter for synchronization"""
        phases = [s.phase for s in states]
        r = abs(sum(cmath.exp(1j * p) for p in phases)) / len(phases)
        return r  # 0 = incoherent, 1 = synchronized
    
    def compute_mutual_information(self, agent_a: Agent, agent_b: Agent) -> float:
        """MI between agent states over time"""
        # Estimate from state trajectories
        pass
    
    def compute_transfer_entropy(self, source: Agent, target: Agent) -> float:
        """Directed information flow"""
        pass
```

---

## Famous Emergent Systems

| System | Emergence | Mechanism |
|---|---|---|
| **Ant Colony** | Optimal foraging paths | Pheromone stigmergy |
| **Bird Flocks** | Coordinated flight | Local alignment rules |
| **Market Prices** | Efficient allocation | Supply/demand dynamics |
| **Neural Networks** | Pattern recognition | Distributed representations |
| **Blockchain** | Consensus without leader | PoW/PoS + economic incentives |
| **Internet** | Robust routing | Decentralized protocols |
| **LLM Agents** | Tool use, planning | Emergent from training |

---

## Designing for Emergence

### Principles
| Principle | Implementation |
|---|---|
| **Simple local rules** | Each agent follows simple logic |
| **Rich interactions** | Many interaction opportunities |
| **Feedback loops** | Positive + negative feedback |
| **Diversity** | Heterogeneous agents |
| **Redundancy** | Multiple paths to goals |
| **Boundary conditions** | Constraints that guide |

### Anti-Patterns
| Anti-Pattern | Problem |
|---|---|
| **Over-engineering** | Too many rules kill emergence |
| **Central control** | Defeats self-organization |
| **Homogeneity** | No diversity → no adaptation |
| **No feedback** | No adaptation possible |
| **Rigid roles** | Prevents specialization |

---

## Related Notes

- [[MultiAgent/Coordination-Patterns.md]] — Swarm coordination
- [[MultiAgent/Negotiation-Consensus.md]] — Consensus as emergence
- [[MultiAgent/Safety-Coordination.md]] — Controlling emergence
- [[MultiAgent/Communication-Protocols.md]] — Interaction for emergence
- [[Frontiers/Agent-Societies.md]] — Large-scale emergence
- [[Frontiers/Research-Directions.md]] — Emergence research
- [[Frontiers/Self-Improving-Agents.md]] — Evolutionary emergence
- [[Methodologies/Team-Topologies.md]] — Team emergence
- [[Methodologies/Engineering-Culture.md]] — Organizational emergence
- [[Frontiers/Research-Directions.md]] — Emergence research

---

*Sources: "Emergence" (Holland), "Swarm Intelligence" (Bonabeau), "Complexity" (Mitchell), "At Home in the Universe" (Kauffman), Reynolds' Boids, Ant Colony Optimization, Stigmergy (Grassé), Prediction Markets, Ensemble Methods, Distributed Consensus, Blockchain consensus, Complexity Science.*