# Swarm_Ex
```elixir
Mix.install(
[
{:instructor, "~> 0.0.5"},
{:openai_ex, "~> 0.8.4"},
{:swarm_ex, git: "https://github.com/nrrso/swarm_ex.git", branch: "main"},
{:jason, "~> 1.4"}
],
config: [
instructor: [
adapter: Instructor.Adapters.OpenAI,
openai: [api_key: System.fetch_env!("LB_OPENAI_API_KEY")]
]
]
)
```
## Define Example Modules
```elixir
# Message Classification Tool
defmodule ClassifyMessageTool do
@behaviour SwarmEx.Tool
@impl true
def execute(%{message: message}) do
# TODO: Replace this with actual LLM call
# Placeholder for LLM classification
# Example API call structure:
# response = OpenAI.chat_completion(
# model: "gpt-3.5-turbo",
# messages: [
# %{role: "system", content: "You are a classifier that determines if messages are Star Wars related. Reply with true or false only."},
# %{role: "user", content: message}
# ]
# )
# For now, simple keyword matching
is_star_wars = String.downcase(message) |> String.contains?(["star wars", "jedi", "sith", "force"])
{:ok, %{is_star_wars: is_star_wars}}
end
@impl true
def validate(%{message: _}), do: :ok
def validate(_), do: {:error, :invalid_args}
@impl true
def cleanup(_), do: :ok
end
```
```elixir
# Star Wars Response Tool
defmodule StarWarsResponseTool do
@behaviour SwarmEx.Tool
@impl true
def execute(_args) do
{:ok, "May the Force be with you!"}
end
@impl true
def validate(_), do: :ok
@impl true
def cleanup(_), do: :ok
end
```
```elixir
defmodule TriageAgent do
use SwarmEx.Agent
@impl true
def init(opts) do
{:ok, opts}
end
@impl true
def terminate(_reason, _state), do: :ok
@impl true
def handle_message(message, state) when is_binary(message) do
# Directly execute the ClassifyMessageTool instead of using execute_tool
case ClassifyMessageTool.execute(%{message: message}) do
{:ok, %{is_star_wars: true}} ->
Logger.info("Message classified as Star Wars related. Handing off to StarWarsAgent.")
handoff_to_star_wars(message, state)
{:ok, %{is_star_wars: false}} ->
Logger.info("Message not Star Wars related. Providing general response.")
{:ok, "Hi, how can I help?", state}
{:error, reason} ->
Logger.error("Classification failed: #{inspect(reason)}")
{:error, "Sorry, I couldn't process your message."}
end
end
@impl true
def handle_tool(:respond, _args, state) do
{:ok, state}
end
defp handoff_to_star_wars(message, state) do
case state[:star_wars_agent] do
nil ->
{:error, "Star Wars agent not configured"}
agent_pid ->
case SwarmEx.send_message_to_pid(agent_pid, message) do
{:ok, response} -> {:ok, response, state}
error -> error
end
end
end
end
```
```elixir
# Star Wars Specialist Agent
defmodule StarWarsAgent do
use SwarmEx.Agent
@impl true
def init(opts) do
{:ok, opts}
end
@impl true
def terminate(_reason, _state), do: :ok
@impl true
def handle_message(message, state) do
case StarWarsResponseTool.execute(%{}) do
{:ok, response} -> {:ok, response, state}
{:error, reason} -> {:error, reason}
end
end
@impl true
def handle_tool(:respond, _args, state) do
{:ok, state}
end
end
```
## Instantiate Tools and Agents
```elixir
# Create network and agents
{:ok, network} = SwarmEx.create_network()
```
```elixir
# Register our tools
SwarmEx.register_tool(ClassifyMessageTool)
SwarmEx.register_tool(StarWarsResponseTool)
```
```elixir
# Create the Star Wars agent first
{:ok, star_wars_agent} = SwarmEx.create_agent(network, StarWarsAgent, name: "star_wars_agent")
```
```elixir
SwarmEx.Client.list_agents(network)
```
```elixir
# Create the triage agent with reference to the Star Wars agent
{:ok, triage_agent} = SwarmEx.create_agent(
network,
TriageAgent,
name: "triage_agent",
star_wars_agent: star_wars_agent
)
```
```elixir
SwarmEx.Client.list_agents(network)
```
## Sending Message
```elixir
# Test with non-Star Wars message
{:ok, regular_response} = SwarmEx.send_message(network, "triage_agent", "Hello, what's the weather like?")
IO.puts("Regular response: #{regular_response}")
```
```elixir
# Test with Star Wars message
{:ok, star_wars_response} = SwarmEx.send_message(network, "triage_agent", "Tell me about the Jedi")
IO.puts("Star Wars response: #{star_wars_response}")
```