How to Build a Swarm of Agents#

python-icon Download Python Script

Python script/notebook for this guide.

Swarm how-to script

Prerequisites

This guide assumes familiarity with Agents.

The Swarm pattern is a type of agentic pattern that takes inspiration from Swarm intelligence. It is often observed in biological systems such as ant colonies, bee hives, and bird flocks. In this agentic pattern, each agent is assigned a specific responsibility and can delegate tasks to other specialized agents to improve overall performance.

When to use the Swarm pattern?

Compared to using a hierarchical multi-agent pattern, the communication in Swarm pattern reduces the number of LLM calls as showcased in the diagram below.

How the Swarm pattern compares to hierachical multi-agent pattern

In the hierarchical pattern, a route User → Agent K → User will require:

  1. All intermediate agent to call the correct sub-agent to go down to the Agent K.

  2. The Agent K to generate its answer.

  3. All intermediate agents to relay the answer back to the user.

In the swarm pattern, a route User → Agent K → User will require:

  1. The first agent to call or handoff the conversation the Agent K (provided that the developer allows the connection between the two agents).

  2. The Agent K to generate its answer.

  3. The first agent to relay the answer (only when NOT using handoff; with handoff the Agent K replaces the first agent and is thus directly communicating with the human user)


This guide presents an example of a simple Swarm of agents applied to a medical use case.

Example of a Swarm agent pattern for medical application

This guide will walk you through the following steps:

  1. Defining agents equipped with tools

  2. Assembling a Swarm using the defined agents

  3. Executing the Swarm of agents

It also covers how to enable handoff when building the Swarm.

Warning

The Swarm agentic pattern is currently in beta (e.g., it cannot yet be used in a Flow). Its API and behavior are not guaranteed to be stable and may evolve in future versions.

For more information about Swarm and other agentic patterns in WayFlow, contact the AgentSpec development team.

Basic implementation#

First import what is needed for this guide:

1from typing import List
2from wayflowcore.agentspec import AgentSpecExporter, AgentSpecLoader
3from wayflowcore.executors.executionstatus import (
4    FinishedStatus,
5    UserMessageRequestStatus,
6)
7from wayflowcore.agent import Agent
8from wayflowcore.swarm import Swarm
9from wayflowcore.tools import tool

To follow this guide, you will need access to a large language model (LLM). WayFlow supports several LLM API providers. Select an LLM from the options below:

from wayflowcore.models import OCIGenAIModel

if __name__ == "__main__":

    llm = OCIGenAIModel(
        model_id="provider.model-id",
        service_endpoint="https://url-to-service-endpoint.com",
        compartment_id="compartment-id",
        auth_type="API_KEY",
    )

In this section, you will define the agents that will later be used to build the Swarm of agents.

Creating the tools#

The Swarm in this example consists of three Agents, each equipped with a single Tool.

# tools for doctor
medical_knowledge = {
    "fever": ["flu", "infection"],
    "runny nose": ["cold", "allergies"],
    "fatigue": ["cold"],
    "cough": ["cold", "allergies"],
    "headache": ["tension headache", "migraine"],
}

@tool(description_mode="only_docstring")
def symptoms_checker(symptoms: List[str]) -> List[str]:
    """
    Checks symptoms against the medical knowledge base.
    Existing entries for "fever", "cough" and "headache".
    For other symptoms, you may need to refer to a specialist.

    Parameters:
    symptoms (list): List of symptoms reported by the patient.

    Returns:
    list: Possible conditions based on the symptoms.
    """
    possible_conditions = []
    for symptom in symptoms:
        if symptom in medical_knowledge:
            possible_conditions.extend(medical_knowledge[symptom])
    return list(set(possible_conditions))


medication_info = {
    "medicationA": "Available. For a mild cold, take two tablets every 6 hours for 3 days.",
    "medicationB": "Available.",
    "medicationC": "Not available.",
    "creamA": "Available. For exczema, apply the cream twice a day for the next 2 weeks.",
}


@tool(description_mode="only_docstring")
def get_medication_info(drug_name: str) -> str:
    """
    Provides availability and information about a medication.
    Known information for "medicationA", "medicationB", "medicationC" and "creamA".

    Parameters:
    drug_name (str): Name of the drug.

    Returns:
    str: Information about the drug.
    """
    return medication_info.get(drug_name, "Drug not found.")


dermatologist_knowledge = {
    "eczema": "Apply creamA twice a day for 2 weeks.",
    "acne": "Apply creamB once a day for 1 week.",
}


@tool(description_mode="only_docstring")
def knowledge_tool(condition: str) -> str:
    """
    Provides diagnosis and treatment information for skin conditions.
    Existing entries for "eczema" and "acne".

    Parameters:
    condition (str): Name of the skin condition.

    Returns:
    str: Diagnosis and treatment information.
    """
    return dermatologist_knowledge.get(condition, "Condition not found.")

API Reference: tool

Defining the agents#

The three agents need to be given the following elements:

  • A name

  • A description

  • A system prompt (the instruction to give to the LLM to solve a given task)

  • A LLM

  • Some optional tools

General Practitioner Agent#

The first agent the user interacts with is the General Practitioner Agent.

This agent is equipped with the symptoms checker tool, and can interact with the Pharmacist Agent as well as the Dermatologist Agent.

Prompt for the General Practitioner Agent
general_practitioner_system_prompt = """
You are an helpful general practitioner LLM doctor responsible for handling patient consultations.
Your goal is to assess patients' symptoms, provide initial diagnoses, pescribe medication for
mild conditions or refer to other specialists as needed.

## When to Use Each Tool
- symptoms_checker: Use this to look up possible conditions based on symptoms reported by the patient.

## When to query other Agents
- Pharmacist: Every time you need to prescribe some medication, give the condition description and prescription to the Pharmacist.
- Dermatologist: If the patient has a skin condition, ask expert advice/diagnosis to the Dermatologist after the initial exchange.

# Specific instructions
## Initial exchange
When a patient first shares symptoms ask about for exactly 1 round of questions, consisting of asking about medical history and
simple questions (e.g. do they have known allergies, when did the symptoms started, did they already tried some treatment/medication, etc)).
Always ask for this one round of information to the user before prescribing medication / referring to other agents.

## Identifying condition
Use the symptoms checker to confirm the condition (for mild conditions only. For other conditions, refer to specialists).

## Mild conditions
* If the patient has a mild cold, prescribe medicationA.
    - Give the condition description and prescription to the Pharmacist.

## Skin conditions
* If the patient has a skin condition, ask for expert advice/diagnosis from the Dermatologist.
Here, you don't need to ask for the user confirmation. Directly call the Dermatologist
    - Provide the patient's symptoms/initial hypothesis to the Dermatologist and ask for a diagnosis.
    - The Dermatologist may query the Pharmacist to confirm the availability of the prescribed medication.
    - Once the treatment is confirmed, pass on the prescription to the patient and ask them to follow the instructions.
""".strip()

The General Practitioner Agent can be configured as follows:

general_practitioner = Agent(
    name="GeneralPractitioner",
    description="General Practitioner. Primary point of contact for patients, handles general medical inquiries, provides initial diagnoses, and manages referrals.",
    llm=llm,
    tools=[symptoms_checker],
    custom_instruction=general_practitioner_system_prompt,
)

Pharmacist Agent#

The Pharmacist Agent is equipped with the tool to obtain medication information. This agent cannot initiate a discussion with the other agents in the Swarm.

Prompt for the Pharmacist Agent
pharmacist_system_prompt = """
You are an helpful Pharmacist LLM Agent responsible for giving information about medication.
Your goal is to answer queries from the General Practitioner Doctor about medication information
and availabilities.

## When to Use Each Tool
- get_medication_info: Use this to look up availability and information about a specific medication.
""".strip()
pharmacist = Agent(
    name="Pharmacist",
    description="Pharmacist. Gives availability and information about specific medication.",
    llm=llm,
    tools=[get_medication_info],
    custom_instruction=pharmacist_system_prompt,
)

Dermatologist Agent#

The final agent in the Swarm is the Dermatologist agent which is equipped with a tool to query a skin condition knowledge base. This agent can initiate a discussion with the Pharmacist Agent.

Prompt for the Dermatologist Agent
dermatologist_system_prompt = """
You are an helpful Dermatologist LLM Agent responsible for diagnosing and treating skin conditions.
Your goal is to assess patients' symptoms, provide accurate diagnoses, and prescribe effective treatments.

## When to Use Each Tool
- knowledge_tool: Use this to look up diagnosis and treatment information for specific skin conditions.

## When to query other Agents
- Pharmacist: Every time you need to prescribe some medication, give the condition description and prescription to the Pharmacist.

# Specific instructions
## Initial exchange
When a patient's symptoms are referred to you by the General Practitioner, review the symptoms and use the knowledge tool to confirm the diagnosis.
## Prescription
Prescribe the recommended treatment for the diagnosed condition and query the Pharmacist to confirm the availability of the prescribed medication.

When answering back to the General Practitioner, describe your diagnosis and the prescription.
Tell the General Practitioner that you already checked with the pharmacist for availability.
""".strip()
dermatologist = Agent(
    name="Dermatologist",
    description="Dermatologist. Diagnoses and treats skin conditions.",
    llm=llm,
    tools=[knowledge_tool],
    custom_instruction=dermatologist_system_prompt,
)

Creating the Swarm#

assistant = Swarm(
    name="Swarm",
    first_agent=general_practitioner,
    relationships=[
        (general_practitioner, pharmacist),
        (general_practitioner, dermatologist),
        (dermatologist, pharmacist),
    ],
)

API Reference: Swarm

The Swarm has two main parameters:

  • The first_agent — the initial agent the user interacts with (in this example, the General Practitioner Agent).

  • A list of relationships between agents.

Additionally, the list of “relationships” between the agents must be defined.

Each relationship is defined as a tuple of Caller Agent and Recipient Agent.

In this example, the General Practitioner Doctor Agent can initiate discussions with both the Pharmacist and the Dermatologist. The Dermatologist can also initiate discussions with the Pharmacist.

When invoked, each agent can either respond to its caller (a human user or another agent) or choose to initiate a discussion with another agent if they are given the capability to do so.

Executing the Swarm#

Now that the Swarm is defined, you can execute it using an example user query.

# With a linear conversation
conversation = assistant.start_conversation()

conversation.append_user_message(
    "My skin has been itching for some about a week, can you help me understand what is going on?"
)
status = conversation.execute()
if isinstance(status, UserMessageRequestStatus):
    assistant_reply = conversation.get_last_message()
    print(f"---\nAssistant >>> {assistant_reply.content}\n---")
else:
    print(f"Invalid execution status, expected UserMessageRequestStatus, received {type(status)}")

# then continue the conversation

We recommend to implement an execution loop to execute the Swarm, such as the following:

1# run_swarm_in_command_line(assistant)
2# ^ uncomment and execute

Advanced usage#

Enabling handoff in the Swarm#

By default, communication in the Swarm pattern is done with agent sending blocking messages/requests to each other.

The handoff mechanism provides an alternative: when enabled, agents can handoff the conversation — that is, transfer the message history between the user and one agent to another agent within the Swarm. Agents can still communicate with each other as they do when handoff=False.

A key benefit of using handoff is reduced response latency. Talking to other agents increases the “distance” between the human user and the current agent. Transferring a conversation to another agent keeps this distance unchanged (in other words, the agent interacting with the user is different, but the user is still the same).

assistant = Swarm(
    name="Swarm",
    first_agent=general_practitioner,
    relationships=[
        (general_practitioner, pharmacist),
        (general_practitioner, dermatologist),
        (dermatologist, pharmacist),
    ],
    handoff=True,  # <-- Add this
)

To enable handoff in a Swarm, set the handoff parameter to True.

Agent Spec Exporting/Loading#

You can export the assistant configuration to its Agent Spec configuration using the AgentSpecExporter and the Swarm plugin. Using the plugin ensures the proper serialization of the custom Swarm component.

from wayflowcore.agentspec import AgentSpecExporter

serialized_assistant = AgentSpecExporter().to_json(assistant)

Here is what the Agent Spec representation will look like ↓

Click here to see the assistant configuration.
{
  "component_type": "PluginSwarm",
  "id": "e6dd83c1-7c17-42f8-874d-e6e174f18424",
  "name": "Swarm",
  "description": null,
  "metadata": {
    "__metadata_info__": {}
  },
  "inputs": [],
  "outputs": [],
  "first_agent": {
    "$component_ref": "04597246-9a76-45a7-b4e8-b17730bf90b9"
  },
  "relationships": [
    [
      {
        "$component_ref": "04597246-9a76-45a7-b4e8-b17730bf90b9"
      },
      {
        "$component_ref": "aa80404a-dfc8-49e3-868a-dcfc4892b551"
      }
    ],
    [
      {
        "$component_ref": "04597246-9a76-45a7-b4e8-b17730bf90b9"
      },
      {
        "$component_ref": "6377f21e-7b6b-4e11-b05b-029980adf932"
      }
    ],
    [
      {
        "$component_ref": "6377f21e-7b6b-4e11-b05b-029980adf932"
      },
      {
        "$component_ref": "aa80404a-dfc8-49e3-868a-dcfc4892b551"
      }
    ]
  ],
  "handoff": true,
  "component_plugin_name": "SwarmPlugin",
  "component_plugin_version": "25.4.0.dev0",
  "$referenced_components": {
    "04597246-9a76-45a7-b4e8-b17730bf90b9": {
      "component_type": "Agent",
      "id": "04597246-9a76-45a7-b4e8-b17730bf90b9",
      "name": "GeneralPractitioner",
      "description": "General Practitioner. Primary point of contact for patients, handles general medical inquiries, provides initial diagnoses, and manages referrals.",
      "metadata": {
        "__metadata_info__": {}
      },
      "inputs": [],
      "outputs": [],
      "llm_config": {
        "$component_ref": "0f34179f-02fa-4392-98ac-cc6e0dcff7b7"
      },
      "system_prompt": "You are an helpful general practitioner LLM doctor responsible for handling patient consultations.\nYour goal is to assess patients' symptoms, provide initial diagnoses, pescribe medication for\nmild conditions or refer to other specialists as needed.\n\n## When to Use Each Tool\n- symptoms_checker: Use this to look up possible conditions based on symptoms reported by the patient.\n\n## When to query other Agents\n- Pharmacist: Every time you need to prescribe some medication, give the condition description and prescription to the Pharmacist.\n- Dermatologist: If the patient has a skin condition, ask expert advice/diagnosis to the Dermatologist after the initial exchange.\n\n# Specific instructions\n## Initial exchange\nWhen a patient first shares symptoms ask about for exactly 1 round of questions, consisting of asking about medical history and\nsimple questions (e.g. do they have known allergies, when did the symptoms started, did they already tried some treatment/medication, etc)).\nAlways ask for this one round of information to the user before prescribing medication / referring to other agents.\n\n## Identifying condition\nUse the symptoms checker to confirm the condition (for mild conditions only. For other conditions, refer to specialists).\n\n## Mild conditions\n* If the patient has a mild cold, prescribe medicationA.\n    - Give the condition description and prescription to the Pharmacist.\n\n## Skin conditions\n* If the patient has a skin condition, ask for expert advice/diagnosis from the Dermatologist.\nHere, you don't need to ask for the user confirmation. Directly call the Dermatologist\n    - Provide the patient's symptoms/initial hypothesis to the Dermatologist and ask for a diagnosis.\n    - The Dermatologist may query the Pharmacist to confirm the availability of the prescribed medication.\n    - Once the treatment is confirmed, pass on the prescription to the patient and ask them to follow the instructions.",
      "tools": [
        {
          "component_type": "ServerTool",
          "id": "232a7ff6-a97e-49ce-8d62-b415d288a18a",
          "name": "symptoms_checker",
          "description": "Checks symptoms against the medical knowledge base.\nExisting entries for \"fever\", \"cough\" and \"headache\".\nFor other symptoms, you may need to refer to a specialist.\n\nParameters:\nsymptoms (list): List of symptoms reported by the patient.\n\nReturns:\nlist: Possible conditions based on the symptoms.",
          "metadata": {
            "__metadata_info__": {}
          },
          "inputs": [
            {
              "type": "array",
              "items": {
                "type": "string"
              },
              "title": "symptoms"
            }
          ],
          "outputs": [
            {
              "type": "array",
              "items": {
                "type": "string"
              },
              "title": "tool_output"
            }
          ]
        }
      ]
    },
    "0f34179f-02fa-4392-98ac-cc6e0dcff7b7": {
      "component_type": "VllmConfig",
      "id": "0f34179f-02fa-4392-98ac-cc6e0dcff7b7",
      "name": "LLAMA_MODEL_ID",
      "description": null,
      "metadata": {
        "__metadata_info__": {}
      },
      "default_generation_parameters": null,
      "url": "LLAMA_API_URL",
      "model_id": "LLAMA_MODEL_ID"
    },
    "aa80404a-dfc8-49e3-868a-dcfc4892b551": {
      "component_type": "Agent",
      "id": "aa80404a-dfc8-49e3-868a-dcfc4892b551",
      "name": "Pharmacist",
      "description": "Pharmacist. Gives availability and information about specific medication.",
      "metadata": {
        "__metadata_info__": {}
      },
      "inputs": [],
      "outputs": [],
      "llm_config": {
        "$component_ref": "0f34179f-02fa-4392-98ac-cc6e0dcff7b7"
      },
      "system_prompt": "You are an helpful Pharmacist LLM Agent responsible for giving information about medication.\nYour goal is to answer queries from the General Practitioner Doctor about medication information\nand availabilities.\n\n## When to Use Each Tool\n- get_medication_info: Use this to look up availability and information about a specific medication.",
      "tools": [
        {
          "component_type": "ServerTool",
          "id": "57b84c13-a61b-4f79-8755-7dc8e2363726",
          "name": "get_medication_info",
          "description": "Provides availability and information about a medication.\nKnown information for \"medicationA\", \"medicationB\", \"medicationC\" and \"creamA\".\n\nParameters:\ndrug_name (str): Name of the drug.\n\nReturns:\nstr: Information about the drug.",
          "metadata": {
            "__metadata_info__": {}
          },
          "inputs": [
            {
              "type": "string",
              "title": "drug_name"
            }
          ],
          "outputs": [
            {
              "type": "string",
              "title": "tool_output"
            }
          ]
        }
      ]
    },
    "6377f21e-7b6b-4e11-b05b-029980adf932": {
      "component_type": "Agent",
      "id": "6377f21e-7b6b-4e11-b05b-029980adf932",
      "name": "Dermatologist",
      "description": "Dermatologist. Diagnoses and treats skin conditions.",
      "metadata": {
        "__metadata_info__": {}
      },
      "inputs": [],
      "outputs": [],
      "llm_config": {
        "$component_ref": "0f34179f-02fa-4392-98ac-cc6e0dcff7b7"
      },
      "system_prompt": "You are an helpful Dermatologist LLM Agent responsible for diagnosing and treating skin conditions.\nYour goal is to assess patients' symptoms, provide accurate diagnoses, and prescribe effective treatments.\n\n## When to Use Each Tool\n- knowledge_tool: Use this to look up diagnosis and treatment information for specific skin conditions.\n\n## When to query other Agents\n- Pharmacist: Every time you need to prescribe some medication, give the condition description and prescription to the Pharmacist.\n\n# Specific instructions\n## Initial exchange\nWhen a patient's symptoms are referred to you by the General Practitioner, review the symptoms and use the knowledge tool to confirm the diagnosis.\n## Prescription\nPrescribe the recommended treatment for the diagnosed condition and query the Pharmacist to confirm the availability of the prescribed medication.\n\nWhen answering back to the General Practitioner, describe your diagnosis and the prescription.\nTell the General Practitioner that you already checked with the pharmacist for availability.",
      "tools": [
        {
          "component_type": "ServerTool",
          "id": "c7b805df-39c5-4643-b4e7-352145fa5537",
          "name": "knowledge_tool",
          "description": "Provides diagnosis and treatment information for skin conditions.\nExisting entries for \"eczema\" and \"acne\".\n\nParameters:\ncondition (str): Name of the skin condition.\n\nReturns:\nstr: Diagnosis and treatment information.",
          "metadata": {
            "__metadata_info__": {}
          },
          "inputs": [
            {
              "type": "string",
              "title": "condition"
            }
          ],
          "outputs": [
            {
              "type": "string",
              "title": "tool_output"
            }
          ]
        }
      ]
    }
  },
  "agentspec_version": "25.4.1"
}

You can then load the configuration back to an assistant using the AgentSpecLoader.

Similar to the serialization, use the swarm deserialization plugin to ensure the proper deserialization of the custom Swarm component.

from wayflowcore.agentspec import AgentSpecLoader

TOOL_REGISTRY = {
    "symptoms_checker": symptoms_checker,
    "get_medication_info": get_medication_info,
    "knowledge_tool": knowledge_tool,
}
assistant: Swarm = AgentSpecLoader(
    tool_registry=TOOL_REGISTRY
).load_json(serialized_assistant)

Note

This guide uses the following extension/plugin Agent Spec components:

  • PluginSwarm

See the list of available Agent Spec extension/plugin components in the API Reference

Next steps#

Now that you have learned how to define a Swarm, you may proceed to How to Build Multi-Agent System.

Full code#

Click on the card at the top of this page to download the full code for this guide or copy the code below.

  1# Copyright © 2025 Oracle and/or its affiliates.
  2#
  3# This software is under the Universal Permissive License
  4# %%[markdown]
  5# Code Example - Build a Swarm of Agents
  6# --------------------------------------
  7
  8# How to use:
  9# Create a new Python virtual environment and install the latest WayFlow version.
 10# ```bash
 11# python -m venv venv-wayflowcore
 12# source venv-wayflowcore/bin/activate
 13# pip install --upgrade pip
 14# pip install "wayflowcore==26.1" 
 15# ```
 16
 17# You can now run the script
 18# 1. As a Python file:
 19# ```bash
 20# python howto_swarm.py
 21# ```
 22# 2. As a Notebook (in VSCode):
 23# When viewing the file,
 24#  - press the keys Ctrl + Enter to run the selected cell
 25#  - or Shift + Enter to run the selected cell and move to the cell below# (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl) or Apache License
 26# 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0), at your option.
 27
 28
 29
 30
 31# %%[markdown]
 32## Imports for this guide
 33
 34# %%
 35from typing import List
 36from wayflowcore.agentspec import AgentSpecExporter, AgentSpecLoader
 37from wayflowcore.executors.executionstatus import (
 38    FinishedStatus,
 39    UserMessageRequestStatus,
 40)
 41from wayflowcore.agent import Agent
 42from wayflowcore.swarm import Swarm
 43from wayflowcore.tools import tool
 44
 45# %%[markdown]
 46## Configure your LLM
 47
 48# %%
 49from wayflowcore.models import VllmModel
 50
 51llm = VllmModel(
 52    model_id="LLAMA_MODEL_ID",
 53    host_port="LLAMA_API_URL",
 54)
 55
 56# %%[markdown]
 57## Creating the tools
 58
 59# %%
 60# tools for doctor
 61medical_knowledge = {
 62    "fever": ["flu", "infection"],
 63    "runny nose": ["cold", "allergies"],
 64    "fatigue": ["cold"],
 65    "cough": ["cold", "allergies"],
 66    "headache": ["tension headache", "migraine"],
 67}
 68
 69@tool(description_mode="only_docstring")
 70def symptoms_checker(symptoms: List[str]) -> List[str]:
 71    """
 72    Checks symptoms against the medical knowledge base.
 73    Existing entries for "fever", "cough" and "headache".
 74    For other symptoms, you may need to refer to a specialist.
 75
 76    Parameters:
 77    symptoms (list): List of symptoms reported by the patient.
 78
 79    Returns:
 80    list: Possible conditions based on the symptoms.
 81    """
 82    possible_conditions = []
 83    for symptom in symptoms:
 84        if symptom in medical_knowledge:
 85            possible_conditions.extend(medical_knowledge[symptom])
 86    return list(set(possible_conditions))
 87
 88
 89medication_info = {
 90    "medicationA": "Available. For a mild cold, take two tablets every 6 hours for 3 days.",
 91    "medicationB": "Available.",
 92    "medicationC": "Not available.",
 93    "creamA": "Available. For exczema, apply the cream twice a day for the next 2 weeks.",
 94}
 95
 96
 97@tool(description_mode="only_docstring")
 98def get_medication_info(drug_name: str) -> str:
 99    """
100    Provides availability and information about a medication.
101    Known information for "medicationA", "medicationB", "medicationC" and "creamA".
102
103    Parameters:
104    drug_name (str): Name of the drug.
105
106    Returns:
107    str: Information about the drug.
108    """
109    return medication_info.get(drug_name, "Drug not found.")
110
111
112dermatologist_knowledge = {
113    "eczema": "Apply creamA twice a day for 2 weeks.",
114    "acne": "Apply creamB once a day for 1 week.",
115}
116
117
118@tool(description_mode="only_docstring")
119def knowledge_tool(condition: str) -> str:
120    """
121    Provides diagnosis and treatment information for skin conditions.
122    Existing entries for "eczema" and "acne".
123
124    Parameters:
125    condition (str): Name of the skin condition.
126
127    Returns:
128    str: Diagnosis and treatment information.
129    """
130    return dermatologist_knowledge.get(condition, "Condition not found.")
131
132# %%[markdown]
133## Prompt for the General Practitioner Agent
134
135# %%
136general_practitioner_system_prompt = """
137You are an helpful general practitioner LLM doctor responsible for handling patient consultations.
138Your goal is to assess patients' symptoms, provide initial diagnoses, pescribe medication for
139mild conditions or refer to other specialists as needed.
140
141## When to Use Each Tool
142- symptoms_checker: Use this to look up possible conditions based on symptoms reported by the patient.
143
144## When to query other Agents
145- Pharmacist: Every time you need to prescribe some medication, give the condition description and prescription to the Pharmacist.
146- Dermatologist: If the patient has a skin condition, ask expert advice/diagnosis to the Dermatologist after the initial exchange.
147
148# Specific instructions
149## Initial exchange
150When a patient first shares symptoms ask about for exactly 1 round of questions, consisting of asking about medical history and
151simple questions (e.g. do they have known allergies, when did the symptoms started, did they already tried some treatment/medication, etc)).
152Always ask for this one round of information to the user before prescribing medication / referring to other agents.
153
154## Identifying condition
155Use the symptoms checker to confirm the condition (for mild conditions only. For other conditions, refer to specialists).
156
157## Mild conditions
158* If the patient has a mild cold, prescribe medicationA.
159    - Give the condition description and prescription to the Pharmacist.
160
161## Skin conditions
162* If the patient has a skin condition, ask for expert advice/diagnosis from the Dermatologist.
163Here, you don't need to ask for the user confirmation. Directly call the Dermatologist
164    - Provide the patient's symptoms/initial hypothesis to the Dermatologist and ask for a diagnosis.
165    - The Dermatologist may query the Pharmacist to confirm the availability of the prescribed medication.
166    - Once the treatment is confirmed, pass on the prescription to the patient and ask them to follow the instructions.
167""".strip()
168
169# %%[markdown]
170## Define the General Practitioner Agent
171
172# %%
173general_practitioner = Agent(
174    name="GeneralPractitioner",
175    description="General Practitioner. Primary point of contact for patients, handles general medical inquiries, provides initial diagnoses, and manages referrals.",
176    llm=llm,
177    tools=[symptoms_checker],
178    custom_instruction=general_practitioner_system_prompt,
179)
180
181# %%[markdown]
182## Prompt for the Pharmacist Agent
183
184# %%
185pharmacist_system_prompt = """
186You are an helpful Pharmacist LLM Agent responsible for giving information about medication.
187Your goal is to answer queries from the General Practitioner Doctor about medication information
188and availabilities.
189
190## When to Use Each Tool
191- get_medication_info: Use this to look up availability and information about a specific medication.
192""".strip()
193
194# %%[markdown]
195## Define the Pharmacist Agent
196
197# %%
198pharmacist = Agent(
199    name="Pharmacist",
200    description="Pharmacist. Gives availability and information about specific medication.",
201    llm=llm,
202    tools=[get_medication_info],
203    custom_instruction=pharmacist_system_prompt,
204)
205
206# %%[markdown]
207## Prompt for the Dermatologist Agent
208
209# %%
210dermatologist_system_prompt = """
211You are an helpful Dermatologist LLM Agent responsible for diagnosing and treating skin conditions.
212Your goal is to assess patients' symptoms, provide accurate diagnoses, and prescribe effective treatments.
213
214## When to Use Each Tool
215- knowledge_tool: Use this to look up diagnosis and treatment information for specific skin conditions.
216
217## When to query other Agents
218- Pharmacist: Every time you need to prescribe some medication, give the condition description and prescription to the Pharmacist.
219
220# Specific instructions
221## Initial exchange
222When a patient's symptoms are referred to you by the General Practitioner, review the symptoms and use the knowledge tool to confirm the diagnosis.
223## Prescription
224Prescribe the recommended treatment for the diagnosed condition and query the Pharmacist to confirm the availability of the prescribed medication.
225
226When answering back to the General Practitioner, describe your diagnosis and the prescription.
227Tell the General Practitioner that you already checked with the pharmacist for availability.
228""".strip()
229
230# %%[markdown]
231## Define the Dermatologist Agent
232
233# %%
234dermatologist = Agent(
235    name="Dermatologist",
236    description="Dermatologist. Diagnoses and treats skin conditions.",
237    llm=llm,
238    tools=[knowledge_tool],
239    custom_instruction=dermatologist_system_prompt,
240)
241
242# %%[markdown]
243## Creating the Swarm
244
245# %%
246assistant = Swarm(
247    name="Swarm",
248    first_agent=general_practitioner,
249    relationships=[
250        (general_practitioner, pharmacist),
251        (general_practitioner, dermatologist),
252        (dermatologist, pharmacist),
253    ],
254)
255
256
257# %%[markdown]
258## Running the Swarm
259
260# %%
261# With a linear conversation
262conversation = assistant.start_conversation()
263
264conversation.append_user_message(
265    "My skin has been itching for some about a week, can you help me understand what is going on?"
266)
267status = conversation.execute()
268if isinstance(status, UserMessageRequestStatus):
269    assistant_reply = conversation.get_last_message()
270    print(f"---\nAssistant >>> {assistant_reply.content}\n---")
271else:
272    print(f"Invalid execution status, expected UserMessageRequestStatus, received {type(status)}")
273
274# then continue the conversation
275# %%
276# Or with an execution loop
277def run_swarm_in_command_line(assistant: Swarm):
278    inputs = {}
279    conversation = assistant.start_conversation(inputs)
280
281    while True:
282        status = assistant.execute(conversation)
283        if isinstance(status, FinishedStatus):
284            break
285        assistant_reply = conversation.get_last_message()
286        if assistant_reply is not None:
287            print("\nAssistant >>>", assistant_reply.content)
288        user_input = input("\nUser >>> ")
289        conversation.append_user_message(user_input)
290
291
292# %%[markdown]
293## Running with the execution loop
294
295# %%
296# run_swarm_in_command_line(assistant)
297# ^ uncomment and execute
298
299# %%[markdown]
300## Enabling handoff in the Swarm
301
302# %%
303assistant = Swarm(
304    name="Swarm",
305    first_agent=general_practitioner,
306    relationships=[
307        (general_practitioner, pharmacist),
308        (general_practitioner, dermatologist),
309        (dermatologist, pharmacist),
310    ],
311    handoff=True,  # <-- Add this
312)
313
314# %%[markdown]
315## Export config to Agent Spec
316
317# %%
318from wayflowcore.agentspec import AgentSpecExporter
319
320serialized_assistant = AgentSpecExporter().to_json(assistant)
321
322# %%[markdown]
323## Load Agent Spec config
324
325# %%
326from wayflowcore.agentspec import AgentSpecLoader
327
328TOOL_REGISTRY = {
329    "symptoms_checker": symptoms_checker,
330    "get_medication_info": get_medication_info,
331    "knowledge_tool": knowledge_tool,
332}
333assistant: Swarm = AgentSpecLoader(
334    tool_registry=TOOL_REGISTRY
335).load_json(serialized_assistant)