By Sagar Shankaran, Founder of CallSphere
Discover how swarm intelligence principles like stigmergy, ant colony optimization, and particle swarm optimization can be applied to multi-agent AI systems. Includes Python implementations of each pattern.
Key takeaways
Swarm intelligence is the collective behavior that emerges when many simple agents follow local rules without any centralized controller. Ant colonies find shortest paths to food. Bird flocks navigate without a leader. Bee swarms select optimal nesting sites through decentralized voting. None of the individual agents understand the global problem — intelligence emerges from their interactions.
Applied to AI systems, swarm principles let you build agent architectures where sophisticated problem-solving behavior arises from many lightweight agents following simple rules, rather than from a single complex orchestrator.
Stigmergy is indirect communication where agents modify a shared environment, and other agents respond to those modifications. Ants deposit pheromones on trails; subsequent ants follow trails with stronger pheromone concentrations. This is a decentralized coordination mechanism that scales naturally.
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
flowchart TD
INPUT(["Task input"])
SUPER["Supervisor agent<br/>plans plus monitors"]
W1["Worker 1<br/>research"]
W2["Worker 2<br/>code"]
W3["Worker 3<br/>writing"]
CRITIC{"Output meets<br/>rubric?"}
REWORK["Rework or<br/>retry path"]
SHARED[("Shared scratchpad<br/>and memory")]
OUT(["Final result"])
INPUT --> SUPER
SUPER --> W1 --> CRITIC
SUPER --> W2 --> CRITIC
SUPER --> W3 --> CRITIC
W1 --> SHARED
W2 --> SHARED
W3 --> SHARED
SHARED --> SUPER
CRITIC -->|Pass| OUT
CRITIC -->|Fail| REWORK --> SUPER
style SUPER fill:#4f46e5,stroke:#4338ca,color:#fff
style CRITIC fill:#f59e0b,stroke:#d97706,color:#1f2937
style OUT fill:#059669,stroke:#047857,color:#fff
style SHARED fill:#ede9fe,stroke:#7c3aed,color:#1e1b4b
import random
from dataclasses import dataclass, field
@dataclass
class PheromoneTrail:
"""Shared environment that agents communicate through."""
trails: dict[str, float] = field(default_factory=dict)
evaporation_rate: float = 0.05
def deposit(self, path: str, amount: float):
current = self.trails.get(path, 0.0)
self.trails[path] = current + amount
def evaporate(self):
self.trails = {
path: strength * (1 - self.evaporation_rate)
for path, strength in self.trails.items()
if strength * (1 - self.evaporation_rate) > 0.01
}
def get_strength(self, path: str) -> float:
return self.trails.get(path, 0.0)
class StigmergyAgent:
def __init__(self, agent_id: str):
self.agent_id = agent_id
def choose_path(
self, options: list[str], environment: PheromoneTrail
) -> str:
strengths = [
environment.get_strength(opt) + 0.1 for opt in options
]
total = sum(strengths)
probabilities = [s / total for s in strengths]
return random.choices(options, weights=probabilities, k=1)[0]
def report_result(
self, path: str, quality: float, environment: PheromoneTrail
):
environment.deposit(path, quality)
In an LLM-agent context, stigmergy translates to agents leaving metadata annotations — quality scores, usage counts, or success flags — on shared resources (prompts, tool configurations, knowledge base entries). Subsequent agents bias their choices toward resources with stronger positive signals.
ACO uses the stigmergy principle to solve combinatorial optimization problems. A swarm of agents constructs solutions probabilistically, deposits pheromones proportional to solution quality, and the colony converges on high-quality solutions over iterations.
import math
class AntColonyOptimizer:
def __init__(
self,
num_agents: int = 20,
num_iterations: int = 50,
alpha: float = 1.0, # pheromone influence
beta: float = 2.0, # heuristic influence
evaporation: float = 0.1,
):
self.num_agents = num_agents
self.num_iterations = num_iterations
self.alpha = alpha
self.beta = beta
self.evaporation = evaporation
def solve(
self,
nodes: list[str],
cost_fn: callable,
heuristic_fn: callable,
) -> dict:
pheromones = {
(a, b): 1.0 for a in nodes for b in nodes if a != b
}
best_solution = None
best_cost = float("inf")
for iteration in range(self.num_iterations):
solutions = []
for _ in range(self.num_agents):
path = self._build_solution(
nodes, pheromones, heuristic_fn
)
cost = cost_fn(path)
solutions.append((path, cost))
if cost < best_cost:
best_cost = cost
best_solution = path
# Evaporate
pheromones = {
k: v * (1 - self.evaporation)
for k, v in pheromones.items()
}
# Deposit
for path, cost in solutions:
deposit = 1.0 / cost if cost > 0 else 1.0
for i in range(len(path) - 1):
edge = (path[i], path[i + 1])
pheromones[edge] = pheromones.get(edge, 0) + deposit
return {"best_path": best_solution, "best_cost": best_cost}
def _build_solution(self, nodes, pheromones, heuristic_fn):
remaining = list(nodes)
current = random.choice(remaining)
path = [current]
remaining.remove(current)
while remaining:
weights = []
for node in remaining:
pher = pheromones.get((current, node), 0.01)
heur = heuristic_fn(current, node)
weights.append(
(pher ** self.alpha) * (heur ** self.beta)
)
chosen = random.choices(remaining, weights=weights, k=1)[0]
path.append(chosen)
remaining.remove(chosen)
current = chosen
return path
PSO models agents as particles moving through a solution space. Each particle tracks its personal best position and is attracted toward the global best found by the entire swarm.
@dataclass
class Particle:
position: list[float]
velocity: list[float]
personal_best_pos: list[float] = field(default_factory=list)
personal_best_score: float = float("inf")
class ParticleSwarmOptimizer:
def __init__(
self,
num_particles: int = 30,
dimensions: int = 2,
iterations: int = 100,
w: float = 0.7, # inertia
c1: float = 1.5, # cognitive (personal best pull)
c2: float = 1.5, # social (global best pull)
):
self.particles = [
Particle(
position=[random.uniform(-10, 10) for _ in range(dimensions)],
velocity=[random.uniform(-1, 1) for _ in range(dimensions)],
)
for _ in range(num_particles)
]
self.w, self.c1, self.c2 = w, c1, c2
self.iterations = iterations
self.global_best_pos = None
self.global_best_score = float("inf")
def optimize(self, objective_fn: callable) -> dict:
for particle in self.particles:
particle.personal_best_pos = list(particle.position)
for _ in range(self.iterations):
for p in self.particles:
score = objective_fn(p.position)
if score < p.personal_best_score:
p.personal_best_score = score
p.personal_best_pos = list(p.position)
if score < self.global_best_score:
self.global_best_score = score
self.global_best_pos = list(p.position)
for p in self.particles:
for d in range(len(p.position)):
r1, r2 = random.random(), random.random()
p.velocity[d] = (
self.w * p.velocity[d]
+ self.c1 * r1 * (p.personal_best_pos[d] - p.position[d])
+ self.c2 * r2 * (self.global_best_pos[d] - p.position[d])
)
p.position[d] += p.velocity[d]
return {
"best_position": self.global_best_pos,
"best_score": self.global_best_score,
}
These patterns translate to LLM agent systems in concrete ways. Use stigmergy for prompt evolution — agents annotate which prompts produced good results, and the colony converges on effective prompt templates. Use ACO for pipeline optimization — finding the best ordering of agent steps in a multi-agent workflow. Use PSO for hyperparameter tuning — temperature, top-p, and other parameters for each agent in a fleet.
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
No. The key difference is that swarm agents share information. Pheromone trails, personal/global bests, and environmental signals bias the search toward promising regions of the solution space. Random search has no memory and no communication. Swarms converge exponentially faster on good solutions because each agent's exploration benefits all others.
This depends on the problem dimensionality. For ACO, 10-50 agents per iteration works well for most combinatorial problems. For PSO, 20-40 particles suffice for continuous optimization up to about 30 dimensions. Too few agents lead to premature convergence on local optima; too many waste compute without improving solution quality.
Yes, by using lightweight proxies. Instead of calling a full LLM for each "ant" in your colony, use embedding similarity or a small classifier as the heuristic function. Reserve full LLM calls for evaluating the top candidate solutions found by the swarm, not for every step of every agent in every iteration.
#SwarmIntelligence #MultiAgentSystems #EmergentBehavior #Optimization #Python #AgenticAI #LearnAI #AIEngineering

Written by
Sagar Shankaran· Founder, CallSphere
LinkedInSagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
How we built a fault-tolerant HVAC emergency triage and tech-dispatch platform on Kubernetes — three-tier CQRS, 11 micro-agents on the OpenAI Agents SDK + LangGraph, NATS JetStream, DTMF/SMS/WebSocket acceptance, circuit breakers, and an evaluation pipeline that catches regressions before they wake a tech at 3 AM.
Five proven multi-agent architecture patterns built on A2A — orchestrator, peer mesh, hub-and-spoke, marketplace, and tiered specialist.
Langgraph multi-agent supervisor handoffs docs: the supervisor pattern in LangGraph for coordinating specialist agents, with full code, an eval pipeline that scores routing accuracy, and the failure modes to watch for.
Handoffs done right — when one agent should hand control to another, how to preserve context, and how to evaluate the handoff decision itself.
Step-by-step build of a working agent with the OpenAI Agents SDK — Agent class, tools, handoffs, tracing — plus an eval pipeline that catches regressions before merge.
Smolagents lets agents write Python instead of JSON. Why code-as-action reduces tool errors and where the security trade-offs are for production deployments.
© 2026 CallSphere Inc. All rights reserved.
Made within San Francisco