Agentic AI

    Building Intelligent Swarm Agents with Python: A Dive into Multi-Agent Systems

    Swarm agents and multi-agent systems let specialized agents collaborate to solve complex workflows. This article walks through a Python implementation and explores why MAS matter.

    Originsoft TeamEngineering Team
    December 11, 2024
    4 min read
    Building Intelligent Swarm Agents with Python: A Dive into Multi-Agent Systems

    The digital age is no longer defined by single, monolithic systems attempting to solve increasingly complex problems in isolation. Instead, it is being shaped by distributed intelligence — networks of autonomous entities that collaborate, negotiate, specialize, and adapt. Multi-agent systems represent one of the most significant architectural evolutions in this direction. Inspired by biological swarms — ants coordinating without central authority, bees optimizing resource collection, flocks of birds moving as if governed by a shared mind — these systems demonstrate that intelligence does not always emerge from a single powerful brain. Often, it emerges from interaction.

    For decades, software engineering gravitated toward centralization. We built monoliths because they were easier to reason about. We concentrated logic in a single codebase because coordination across boundaries was expensive and fragile. But as systems scaled — across clouds, across regions, across edge devices — the limitations of central control became evident. The more complex the environment, the more brittle centralized decision-making became. Multi-agent systems offer a different philosophy: instead of building one increasingly complex decision engine, build many smaller, focused agents and allow intelligence to emerge from their structured collaboration.

    At its core, a swarm agent is an autonomous entity capable of performing a well-defined task while communicating with peers. Unlike traditional object-oriented components, agents are not merely passive functions waiting to be invoked; they are decision-making units. They receive input, interpret intent, execute specialized logic, and produce outputs that influence the broader system. A multi-agent system extends this idea by orchestrating multiple such agents into a coordinated structure. Each agent may have its own role, capabilities, and boundaries, yet collectively they operate toward shared objectives.

    The motivation for such systems becomes clearer as we examine the landscape of modern computing. Cloud-native architectures, edge devices, real-time data streams, and AI-powered applications demand scalability not only in computation but in decision-making. A single model tasked with planning, executing, validating, and responding becomes overloaded quickly. In contrast, delegating these responsibilities to specialized agents reduces cognitive load per unit. Complexity becomes partitioned rather than accumulated. The system grows not by becoming denser but by becoming more organized.

    To make this concrete, consider a minimal implementation: a swarm of arithmetic agents written in Python. At first glance, arithmetic operations seem trivial. Why would we need multiple agents for addition, subtraction, multiplication, or division? The answer lies not in arithmetic itself but in architecture. The arithmetic example serves as a controlled environment to observe routing, specialization, delegation, and tool invocation — the foundational mechanics of far more sophisticated agentic workflows.

    The environment setup begins simply. We load environment variables, configure a model reference, and establish a client connection. These steps may appear mundane, but they represent an important separation of concerns. The agent logic does not hardcode infrastructure assumptions. It retrieves configuration dynamically, reinforcing modularity. The client acts as the bridge between the swarm orchestration layer and the underlying language model engine, allowing us to swap models or endpoints without rewriting the system’s structural logic.

    from dotenv import load_dotenv
    from openai import OpenAI
    from swarm import Swarm, Agent
    import json
    import os
    
    load_dotenv()
    
    model = os.getenv('LLM_MODEL', 'qwen2.5:latest')
    
    ollama_client = OpenAI(
        base_url="http://localhost:11434/v1",
        api_key="ollama",
    )

    With the environment prepared, we define roles. This is where the philosophical essence of multi-agent design becomes visible. Instead of embedding all arithmetic logic into a single generalist agent, we introduce an orchestrator — a router. The router does not perform arithmetic itself. Its responsibility is to interpret intent and delegate appropriately. This separation mirrors real-world organizational structures. A manager does not execute every task; they assign tasks to specialists.

    def get_arithmetic_router_agent_instructions():
        return """You are an orchestrator of different arithmetic experts and it is your job to
        determine which of the agent is best suited to handle the user's request, and
        transfer the conversation to that agent."""

    The specialized agents, in contrast, have narrow focus. They are not burdened with routing decisions. They do not attempt to interpret ambiguous intent across domains. They receive clear, delegated tasks and execute them deterministically.

    def get_arithmetic_agent_instructions():
        return """You are an arithmetic expert who takes in a request from a user for
        information they want to perform an arithmetic operation, and then invoke the function to
        run the operation with arguments and get the results back to then report to the
        user the information they wanted to know."""
    
    def add_a_and_b(a: int, b: int) -> int:
        return a + b

    When we instantiate an operation agent, we explicitly define its purpose, its accessible functions, and its model context. This explicitness is not accidental. In multi-agent systems, clarity of boundaries is essential. Each agent must know what it is allowed to do and what it must not do.

    add_operation_agent = Agent(
        name="Add Operation Agent",
        instructions=get_arithmetic_agent_instructions()
        + "\n\nHelp the user with performing add operation for two numbers.",
        functions=[add_a_and_b],
        model=model,
    )

    The orchestration logic completes the structure. The router exposes transfer functions that return the appropriate specialist. Rather than embedding conditional logic inside a single procedural flow, the system allows dynamic agent handoff. Control moves from orchestrator to specialist and potentially back again. This is not just a code pattern; it is a coordination paradigm.

    def transfer_add_operation_agent():
        return add_operation_agent
    
    arithmetic_router_agent.functions = [
        transfer_add_operation_agent,
        transfer_subtract_operation_agent,
        transfer_multiply_operation_agent,
        transfer_divide_operation_agent,
    ]

    The modularity of this structure becomes evident immediately. Adding a new capability does not require refactoring existing agents. It requires defining a new specialist and registering a transfer function. The system expands horizontally rather than becoming vertically entangled. This extensibility is one of the defining strengths of multi-agent design.

    Running the system demonstrates how these pieces interact in practice. The swarm client maintains conversational state, forwards user input to the active agent, and handles dynamic switching as required. Notice that the runtime loop itself remains simple. The complexity resides in delegation logic, not in procedural branching.

    def run_demo_loop(starting_agent, context_variables=None, stream=False, debug=False):
        client = Swarm(client=ollama_client)
        print("Starting Ollama Swarm CLI")
    
        messages = []
        agent = starting_agent
    
        while True:
            user_input = input("User: ")
            messages.append({"role": "user", "content": user_input})
    
            response = client.run(
                agent=agent,
                messages=messages,
                context_variables=context_variables or {},
                stream=stream,
                debug=debug,
            )
    
            pretty_print_messages(response.messages)
            messages.extend(response.messages)
            agent = response.agent

    When executed, the swarm behaves intuitively. A multiplication request is routed to the multiply agent. An expression requiring order-of-operations reasoning is handled by the appropriate specialist. The architecture ensures that each agent performs only what it was designed to perform, yet from the user’s perspective, the system feels unified.

    What appears trivial in arithmetic becomes transformative at scale. Imagine replacing arithmetic operations with legal analysis, medical triage, financial modeling, or supply chain optimization. Instead of one monolithic AI attempting to reason across every dimension simultaneously, we deploy planners, validators, executors, critics, and domain experts as separate agents. Each operates within bounded responsibility. Failures are localized. Improvements are incremental. Scaling is additive.

    The broader implications extend beyond software. Multi-agent systems mirror how human institutions function effectively. High-performing organizations are not composed of one hyper-intelligent individual but of coordinated specialists operating under shared objectives. Intelligence emerges not from central dominance but from structured interaction.

    In distributed computing environments — edge networks, IoT ecosystems, autonomous vehicles — such architecture becomes indispensable. Vehicles coordinating traffic flow, sensors collaborating to optimize energy grids, customer support agents triaging requests dynamically — all exemplify collective intelligence in action. The resilience of these systems stems from decentralization. If one agent fails, others continue operating. The scalability emerges from modular growth. The intelligence emerges from interaction patterns rather than singular complexity.

    Ultimately, the arithmetic swarm is not about mathematics. It is about architecture. It demonstrates that intelligence can be decomposed into interacting components. It shows that delegation reduces cognitive overload. It reveals that extensibility is achieved through specialization rather than accumulation.

    We are entering an era where building intelligent systems no longer means building larger models alone. It means designing ecosystems of agents that collaborate coherently. The question is no longer, “How powerful is your model?” but rather, “How well do your agents coordinate?”

    And in that question lies the future of distributed intelligence.

    #Agents#LLM#Swarm#OpenAI#Generative AI Tools#Python#Multi-Agent Systems
    Originsoft Team

    Engineering Team

    The engineering team at Originsoft Consultancy brings together decades of combined experience in software architecture, AI/ML, and cloud-native development. We are passionate about sharing knowledge and helping developers build better software.