ruby-openai-swarm 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: df437749d299781cdac584185c29c03d6bcdd0ae8ae547395d23656c7a5ff308
4
+ data.tar.gz: ad06764c570c061aab9077ae280bad27b174a740f5721616ab0f3fb052eeb638
5
+ SHA512:
6
+ metadata.gz: 22dff45e435bbe72d598cae52e1924f1921f9d4c07e0795c6b0d58368c72050d33cb63f999c936465fdf5a9bd1065d7dcbeb8696259b9468f8c5b325bfb686d6
7
+ data.tar.gz: c578b9500e861456618f7a576756963cae6bfa53249123b23c7a57363c4cc4993dd796865b42c43d2ff8edd38d9b9d6823ec6b4388da26d43858a38fec9a922f
@@ -0,0 +1,27 @@
1
+ name: RSpec Tests
2
+ on: [push, pull_request]
3
+
4
+ jobs:
5
+ test:
6
+ runs-on: ubuntu-latest
7
+ strategy:
8
+ matrix:
9
+ ruby-version: ['2.7', '3.0', '3.1']
10
+
11
+ steps:
12
+ - uses: actions/checkout@v3
13
+ - name: Set up Ruby ${{ matrix.ruby-version }}
14
+ uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: ${{ matrix.ruby-version }}
17
+ bundler-cache: true
18
+ - name: Install dependencies
19
+ run: bundle install
20
+ - name: Run tests
21
+ run: bundle exec rspec
22
+ - name: Upload test results
23
+ uses: actions/upload-artifact@v3
24
+ if: failure()
25
+ with:
26
+ name: rspec-results
27
+ path: tmp/rspec_results
data/.gitignore ADDED
@@ -0,0 +1,32 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+ .byebug_history
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+ *.bridgesupport
17
+ build-iPhoneOS/
18
+ build-iPhoneSimulator/
19
+ /.yardoc/
20
+ /_yardoc/
21
+ /doc/
22
+ /rdoc/
23
+ /.bundle/
24
+ /vendor/bundle
25
+ /lib/bundler/man/
26
+ .rvmrc
27
+ .ruby-version
28
+ .ruby-gemset
29
+ /tmp
30
+
31
+ # rspec failure tracking
32
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --format documentation
3
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in swarm.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,56 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ruby-openai-swarm (0.1.0)
5
+ ruby-openai (~> 7.3)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ base64 (0.2.0)
11
+ coderay (1.1.3)
12
+ diff-lcs (1.5.1)
13
+ event_stream_parser (1.0.0)
14
+ faraday (2.8.1)
15
+ base64
16
+ faraday-net_http (>= 2.0, < 3.1)
17
+ ruby2_keywords (>= 0.0.4)
18
+ faraday-multipart (1.0.4)
19
+ multipart-post (~> 2)
20
+ faraday-net_http (3.0.2)
21
+ method_source (1.1.0)
22
+ multipart-post (2.4.1)
23
+ pry (0.14.2)
24
+ coderay (~> 1.1)
25
+ method_source (~> 1.0)
26
+ rake (13.2.1)
27
+ rspec (3.13.0)
28
+ rspec-core (~> 3.13.0)
29
+ rspec-expectations (~> 3.13.0)
30
+ rspec-mocks (~> 3.13.0)
31
+ rspec-core (3.13.2)
32
+ rspec-support (~> 3.13.0)
33
+ rspec-expectations (3.13.3)
34
+ diff-lcs (>= 1.2.0, < 2.0)
35
+ rspec-support (~> 3.13.0)
36
+ rspec-mocks (3.13.2)
37
+ diff-lcs (>= 1.2.0, < 2.0)
38
+ rspec-support (~> 3.13.0)
39
+ rspec-support (3.13.1)
40
+ ruby-openai (7.3.1)
41
+ event_stream_parser (>= 0.3.0, < 2.0.0)
42
+ faraday (>= 1)
43
+ faraday-multipart (>= 1)
44
+ ruby2_keywords (0.0.5)
45
+
46
+ PLATFORMS
47
+ ruby
48
+
49
+ DEPENDENCIES
50
+ pry
51
+ rake (~> 13.0)
52
+ rspec (~> 3.0)
53
+ ruby-openai-swarm!
54
+
55
+ BUNDLED WITH
56
+ 2.1.4
data/README.md ADDED
@@ -0,0 +1,141 @@
1
+ ![Swarm Logo](assets/logo-swarm.png)
2
+
3
+ # Ruby OpenAI Swarm
4
+
5
+ [![rspec](https://github.com/graysonchen/ruby-openai-swarm/actions/workflows/rspec.yml/badge.svg)](https://github.com/graysonchen/ruby-openai-swarm/actions)
6
+
7
+ A Ruby-based educational framework adapted from OpenAI’s [Swarm](https://github.com/openai/swarm), exploring ergonomic, lightweight multi-agent orchestration.
8
+
9
+ > The primary goal of Swarm is to showcase the handoff & routines patterns explored in the [Orchestrating Agents: Handoffs & Routines](https://cookbook.openai.com/examples/orchestrating_agents) cookbook. It is not meant as a standalone library, and is primarily for educational purposes.
10
+
11
+ ## Contents
12
+ - [Ruby OpenAI Swarm](#ruby-openai-swarm)
13
+ - [Table of Contents](#table-of-contents)
14
+ - [Installation](#installation)
15
+ - [Bundler](#bundler)
16
+ - [Gem install](#gem-install)
17
+ - [examples](#examples)
18
+ - [Documentation](#documentation)
19
+
20
+ ## Installation
21
+
22
+ ### Bundler
23
+
24
+ Add this line to your application's Gemfile:
25
+
26
+ ```ruby
27
+ gem "ruby-openai-swarm"
28
+ ```
29
+
30
+ And then execute:
31
+
32
+ ```bash
33
+ $ bundle install
34
+ ```
35
+
36
+ ### Gem install
37
+
38
+ Or install with:
39
+
40
+ ```bash
41
+ $ gem install ruby-openai-swarm
42
+ ```
43
+
44
+ and require with:
45
+
46
+ ```ruby
47
+ require "ruby-openai-swarm"
48
+ ```
49
+
50
+ ## Usage
51
+
52
+ ### With Config
53
+
54
+ For a more robust setup, you can configure the gem with your API keys, for example in an `openai.rb` initializer file. Never hardcode secrets into your codebase - instead use something like [dotenv](https://github.com/motdotla/dotenv) to pass the keys safely into your environments.
55
+
56
+ ```ruby
57
+ OpenAI.configure do |config|
58
+ config.access_token = ENV['OPENAI_ACCESS_TOKEN']
59
+ end
60
+ ```
61
+
62
+ OR
63
+
64
+ ```ruby
65
+ # https://openrouter.ai
66
+ OpenAI.configure do |config|
67
+ config.access_token = ENV['OPEN_ROUTER_ACCESS_TOKEN']
68
+ config.uri_base = "https://openrouter.ai/api/v1"
69
+ end
70
+ ```
71
+
72
+ more see: https://github.com/alexrudall/ruby-openai/tree/main?tab=readme-ov-file#ollama
73
+
74
+ Then you can create a client like this:
75
+
76
+ ```ruby
77
+ client = OpenAISwarm.new
78
+
79
+ def spanish_agent
80
+ OpenAISwarm::Agent.new(
81
+ name: "Spanish Agent",
82
+ instructions: "You only speak Spanish.",
83
+ model: "gpt-4o-mini"
84
+ )
85
+ end
86
+
87
+ transfer_to_spanish_agent = OpenAISwarm::FunctionDescriptor.new(
88
+ target_method: :spanish_agent,
89
+ description: 'Transfer spanish speaking users immediately.'
90
+ )
91
+
92
+ english_agent = OpenAISwarm::Agent.new(
93
+ name: "English Agent",
94
+ instructions: "You only speak English.",
95
+ model: "gpt-4o-mini",
96
+ functions: [transfer_to_spanish_agent]
97
+ )
98
+
99
+ messages = [{"role": "user", "content": "Hola. ¿Como estás?"}]
100
+ response = client.run(agent: english_agent, messages: messages, debug: true)
101
+
102
+ pp response.messages.last
103
+ ```
104
+
105
+ ```ruby
106
+ {"role"=>"assistant",
107
+ "content"=>"¡Hola! Estoy bien, gracias. ¿Y tú?",
108
+ "refusal"=>nil,
109
+ :sender=>"Spanish Agent"}
110
+ ```
111
+
112
+ # Examples
113
+
114
+ Check out `/examples` for inspiration! Learn more about each one in its README.
115
+
116
+ - [X] [`basic`](examples/basic): Simple examples of fundamentals like setup, function calling, handoffs, and context variables
117
+ - [X] [`triage_agent`](examples/triage_agent): Simple example of setting up a basic triage step to hand off to the right agent
118
+ - [X] [`weather_agent`](examples/weather_agent): Simple example of function calling
119
+ - [ ] [`airline`](examples/airline): A multi-agent setup for handling different customer service requests in an airline context.
120
+ - [ ] [`support_bot`](examples/support_bot): A customer service bot which includes a user interface agent and a help center agent with several tools
121
+ - [ ] [`personal_shopper`](examples/personal_shopper): A personal shopping agent that can help with making sales and refunding orders
122
+
123
+ link: https://github.com/openai/swarm/tree/main?tab=readme-ov-file#examples
124
+
125
+ ## Documentation
126
+ ![Swarm Diagram](https://raw.githubusercontent.com/openai/swarm/refs/heads/main/assets/swarm_diagram.png)
127
+
128
+
129
+ ## Development
130
+
131
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
132
+
133
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
134
+
135
+ ## Contributing
136
+
137
+ Bug reports and pull requests are welcome on GitHub at https://github.com/graysonchen/ruby-openai-swarm. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/graysonchen/ruby-openai-swarm/blob/main/CODE_OF_CONDUCT.md).
138
+
139
+ ## License
140
+
141
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
Binary file
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ruby-openai-swarm"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ruby-openai-swarm"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
File without changes
@@ -0,0 +1,41 @@
1
+ # link: https://github.com/openai/swarm/blob/main/examples/basic/agent_handoff.py
2
+
3
+ # OpenAI.configure do |config|
4
+ # config.access_token = ENV['OPENAI_ACCESS_TOKEN']
5
+ # end
6
+
7
+ OpenAI.configure do |config|
8
+ config.access_token = ENV['OPEN_ROUTER_ACCESS_TOKEN']
9
+ config.uri_base = "https://openrouter.ai/api/v1"
10
+ end
11
+
12
+ client = OpenAISwarm.new
13
+
14
+ def spanish_agent
15
+ OpenAISwarm::Agent.new(
16
+ name: "Spanish Agent",
17
+ instructions: "You only speak Spanish.",
18
+ model: "gpt-4o-mini"
19
+ )
20
+ end
21
+
22
+ transfer_to_spanish_agent = OpenAISwarm::FunctionDescriptor.new(
23
+ target_method: :spanish_agent,
24
+ description: 'Transfer spanish speaking users immediately.'
25
+ )
26
+
27
+ english_agent = OpenAISwarm::Agent.new(
28
+ name: "English Agent",
29
+ instructions: "You only speak English.",
30
+ model: "gpt-4o-mini",
31
+ functions: [transfer_to_spanish_agent]
32
+ )
33
+
34
+ messages = [{"role": "user", "content": "Hola. ¿Como estás?"}]
35
+ response = client.run(agent: english_agent, messages: messages, debug: true)
36
+
37
+ p response.messages.last
38
+ # => {"role"=>"assistant", "content"=>"¡Hola! Estoy bien, gracias. ¿Y tú?", "refusal"=>nil, :sender=>"Spanish Agent"}
39
+
40
+ msg = response.messages.last
41
+ msg['sender'] == "Spanish Agent"
@@ -0,0 +1,27 @@
1
+ require "bundler/setup"
2
+ require "ruby-openai-swarm"
3
+
4
+ # link: https://github.com/openai/swarm/blob/main/examples/basic/bare_minimum.py
5
+
6
+ # OpenAI.configure do |config|
7
+ # config.access_token = ENV['OPENAI_ACCESS_TOKEN']
8
+ # end
9
+
10
+ OpenAI.configure do |config|
11
+ config.access_token = ENV['OPEN_ROUTER_ACCESS_TOKEN']
12
+ config.uri_base = "https://openrouter.ai/api/v1"
13
+ end
14
+
15
+ client = OpenAISwarm.new
16
+
17
+ agent = OpenAISwarm::Agent.new(
18
+ name: "Agent",
19
+ instructions: "You are a helpful agent.",
20
+ model: "gpt-4o-mini"
21
+ )
22
+ messages = [{"role": "user", "content": "Hi!"}]
23
+ response = client.run(agent: agent, messages: messages)
24
+ p response.messages.last["content"]
25
+ # => "Hello! How can I assist you today?"
26
+ p response.messages
27
+ # => [{"role"=>"assistant", "content"=>"Hello! How can I assist you today?", "refusal"=>nil, :sender=>"Agent"}]
@@ -0,0 +1,67 @@
1
+ # link: https://github.com/openai/swarm/blob/main/examples/basic/context_variables.py
2
+
3
+ # OpenAI.configure do |config|
4
+ # config.access_token = ENV['OPENAI_ACCESS_TOKEN']
5
+ # end
6
+ OpenAI.configure do |config|
7
+ config.access_token = ENV['OPEN_ROUTER_ACCESS_TOKEN']
8
+ config.uri_base = "https://openrouter.ai/api/v1"
9
+ end
10
+
11
+ client = OpenAISwarm.new
12
+
13
+ def instructions(context_variables)
14
+ name = context_variables.fetch(:name, :User)
15
+ "You are a helpful agent. Greet the user by name (#{name})."
16
+ end
17
+
18
+ def print_account_details(context_variables: {})
19
+ puts "print_account_details context_variables: #{context_variables.inspect}"
20
+
21
+ user_id = context_variables[:user_id]
22
+ name = context_variables[:name]
23
+ puts "Account Details: name: #{name}, user_id: #{user_id}"
24
+ "Success"
25
+ end
26
+
27
+ function_instance = OpenAISwarm::FunctionDescriptor.new(
28
+ target_method: :print_account_details,
29
+ )
30
+
31
+ agent = OpenAISwarm::Agent.new(
32
+ name: "Agent",
33
+ instructions: method(:instructions),
34
+ model: "gpt-4o-mini",
35
+ functions: [function_instance]
36
+ )
37
+
38
+ context_variables = { 'name': 'James', 'user_id': 123 }
39
+
40
+ # debugger logger: {:model=>"gpt-4o-mini", :messages=>[{:role=>"system", :content=>"You are a helpful agent. Greet the user by name (James)."}, {:role=>"user", :content=>"Hi!"}], :tools=>[{:type=>"function", :function=>{:name=>"print_account_details", :description=>"", :parameters=>{:type=>"object", :properties=>{}, :required=>[]}}}], :stream=>false, :parallel_tool_calls=>true}
41
+ response = client.run(
42
+ messages: [{"role": "user", "content": "Hi!"}],
43
+ agent: agent,
44
+ context_variables: context_variables,
45
+ debug: true,
46
+ )
47
+ msg = response.messages.last
48
+ # Hello, James! How can I assist you today?
49
+
50
+ msg['content'].include?('James')
51
+
52
+ # debugger logger: {:model=>"gpt-4o-mini", :messages=>[{:role=>"system", :content=>"You are a helpful agent. Greet the user by name (James)."}, {:role=>"user", :content=>"Print my account details!"}], :tools=>[{:type=>"function", :function=>{:name=>"print_account_details", :description=>"", :parameters=>{:type=>"object", :properties=>{}, :required=>[]}}}], :stream=>false, :parallel_tool_calls=>true
53
+ response = client.run(
54
+ messages: [{"role": "user", "content": "Print my account details!"}],
55
+ agent: agent,
56
+ context_variables: context_variables,
57
+ debug: true,
58
+ )
59
+ msg = response.messages.last
60
+ msg['content']
61
+ response.context_variables == {:name=>"James", :user_id=>123}
62
+
63
+ # print(response.messages[-1]["content"])
64
+ # Hello, James! Your account details have been printed successfully. If you need anything else, just let me know!
65
+ #
66
+ # print_account_details context_variables: {:name=>"James", :user_id=>123}
67
+ # Account Details: name: James, user_id: 123
@@ -0,0 +1,32 @@
1
+
2
+ OpenAI.configure do |config|
3
+ config.access_token = ENV['OPEN_ROUTER_ACCESS_TOKEN']
4
+ config.uri_base = "https://openrouter.ai/api/v1"
5
+ end
6
+
7
+ client = OpenAISwarm.new
8
+
9
+ def get_weather(location:)
10
+ "{'temp':67, 'unit':'F'}"
11
+ end
12
+
13
+ function_instance = OpenAISwarm::FunctionDescriptor.new(
14
+ target_method: :get_weather,
15
+ description: 'Simulate fetching weather data'
16
+ )
17
+
18
+ agent = OpenAISwarm::Agent.new(
19
+ name: "Agent",
20
+ instructions: "You are a helpful agent.",
21
+ model: "gpt-4o-mini",
22
+ functions: [function_instance]
23
+ )
24
+ # debugger logger: {:model=>"gpt-4o-mini", :messages=>[{:role=>"system", :content=>"You are a helpful agent."}, {"role"=>"user", "content"=>"What's the weather in NYC?"}], :tools=>[{:type=>"function", :function=>{:name=>"get_weather", :description=>"", :parameters=>{:type=>"object", :properties=>{:location=>{:type=>"string"}}, :required=>["location"]}}}], :stream=>false, :parallel_tool_calls=>true}
25
+ response = client.run(
26
+ messages: [{"role" => "user", "content" => "What's the weather in NYC?"}],
27
+ agent: agent,
28
+ debug: true,
29
+ )
30
+
31
+ # print(response.messages[-1]["content"])
32
+ # The current temperature in New York City is 67°F. => nil
@@ -0,0 +1,38 @@
1
+
2
+ OpenAI.configure do |config|
3
+ config.access_token = ENV['OPEN_ROUTER_ACCESS_TOKEN']
4
+ config.uri_base = "https://openrouter.ai/api/v1"
5
+ end
6
+
7
+ client = OpenAISwarm.new
8
+
9
+ agent = OpenAISwarm::Agent.new(
10
+ name: "Agent",
11
+ instructions: "You are a helpful agent.",
12
+ model: "gpt-4o-mini",
13
+ )
14
+
15
+ def pretty_print_messages(messages)
16
+ messages.each do |message|
17
+ next if message["content"].nil?
18
+ puts "#{message["sender"]}: #{message["content"]}"
19
+ end
20
+ end
21
+
22
+ messages = []
23
+ agent = my_agent
24
+ loop do
25
+ print "> "
26
+ user_input = gets.chomp
27
+
28
+ break if user_input.downcase == "exit"
29
+
30
+ messages << { "role": "user", "content": user_input }
31
+ response = client.run(agent: agent, messages: messages)
32
+
33
+ messages.concat(response.messages)
34
+ agent = response.agent
35
+
36
+ pretty_print_messages(response.messages)
37
+ end
38
+ puts "Goodbye!"
@@ -0,0 +1,34 @@
1
+ # Triage agent
2
+
3
+ This example is a Swarm containing a triage agent, which takes in user inputs and chooses whether to respond directly, or triage the request
4
+ to a sales or refunds agent.
5
+
6
+ ## Setup
7
+
8
+ To run the triage agent Swarm:
9
+
10
+ 1. Run
11
+
12
+ ```shell
13
+ ruby main.rb
14
+ ```
15
+ or
16
+
17
+ ```shell
18
+ ruby examples/triage_agent/main.rb
19
+ ```
20
+
21
+ ## Evals (TODO)
22
+
23
+ > [!NOTE]
24
+ > These evals are intended to be examples to demonstrate functionality, but will have to be updated and catered to your particular use case.
25
+
26
+ This example uses `Pytest` to run eval unit tests. We have two tests in the `evals.py` file, one which
27
+ tests if we call the correct triage function when expected, and one which assesses if a conversation
28
+ is 'successful', as defined in our prompt in `evals.py`.
29
+
30
+ To run the evals, run
31
+
32
+ ```shell
33
+ ruby evals.rb
34
+ ```
@@ -0,0 +1,84 @@
1
+ require "bundler/setup"
2
+ require "ruby-openai-swarm"
3
+
4
+ OpenAI.configure do |config|
5
+ config.access_token = ENV['OPEN_ROUTER_ACCESS_TOKEN']
6
+ config.uri_base = "https://openrouter.ai/api/v1"
7
+ end
8
+
9
+ def client
10
+ OpenAISwarm.new
11
+ end
12
+
13
+ def process_refund(item_id, reason = "NOT SPECIFIED")
14
+ # Refund an item. Make sure you have the item_id of the form item_...
15
+ # Ask for user confirmation before processing the refund.
16
+ puts "[mock] Refunding item #{item_id} because #{reason}..."
17
+ "Success!"
18
+ end
19
+
20
+ def process_refund_function_instance
21
+ OpenAISwarm::FunctionDescriptor.new(
22
+ target_method: :process_refund,
23
+ description: "Refund an item. Make sure you have the item_id of the form item_...Ask for user confirmation before processing the refund."
24
+ )
25
+ end
26
+
27
+ def apply_discount
28
+ # Apply a discount to the user's cart.
29
+ puts "[mock] Applying discount..."
30
+ "Applied discount of 11%"
31
+ end
32
+
33
+ def apply_discount_function_instance
34
+ OpenAISwarm::FunctionDescriptor.new(
35
+ target_method: :apply_discount,
36
+ description: "Apply a discount to the user's cart."
37
+ )
38
+ end
39
+
40
+ def triage_agent
41
+ @triage_agent ||=
42
+ OpenAISwarm::Agent.new(
43
+ name: "Triage Agent",
44
+ instructions: "Determine which agent is best suited to handle the user's request, and transfer the conversation to that agent."
45
+ )
46
+ end
47
+
48
+ def sales_agent
49
+ @sales_agent ||=
50
+ OpenAISwarm::Agent.new(
51
+ name: "Sales Agent",
52
+ instructions: "Be super enthusiastic about selling bees."
53
+ )
54
+ end
55
+
56
+ def refunds_agent
57
+ @refunds_agent ||=
58
+ OpenAISwarm::Agent.new(
59
+ name: "Refunds Agent",
60
+ instructions: "Help the user with a refund. If the reason is that it was too expensive, offer the user a refund code. If they insist, then process the refund.",
61
+ functions: [
62
+ process_refund_function_instance,
63
+ apply_discount_function_instance
64
+ ]
65
+ )
66
+ end
67
+
68
+ transfer_back_to_triage = OpenAISwarm::FunctionDescriptor.new(
69
+ target_method: :triage_agent,
70
+ description: "Call this function if a user is asking about a topic that is not handled by the current agent."
71
+ )
72
+
73
+ def transfer_to_sales
74
+ sales_agent
75
+ end
76
+
77
+ def transfer_to_refunds
78
+ refunds_agent
79
+ end
80
+
81
+ # Assign functions to agents
82
+ triage_agent.functions = [method(:transfer_to_sales), method(:transfer_to_refunds)]
83
+ sales_agent.functions << transfer_back_to_triage
84
+ refunds_agent.functions << transfer_back_to_triage
@@ -0,0 +1,3 @@
1
+ require_relative "agents"
2
+
3
+ OpenAISwarm::Repl.run_demo_loop(triage_agent)
File without changes