swarm_sdk 2.0.2 → 2.0.3
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 +4 -4
- data/lib/swarm_sdk/agent/builder.rb +17 -6
- data/lib/swarm_sdk/agent/definition.rb +16 -6
- data/lib/swarm_sdk/configuration.rb +8 -0
- data/lib/swarm_sdk/swarm/builder.rb +1 -1
- data/lib/swarm_sdk/swarm/tool_configurator.rb +29 -3
- data/lib/swarm_sdk/tools/registry.rb +1 -0
- data/lib/swarm_sdk/tools/think.rb +95 -0
- data/lib/swarm_sdk/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9aba64a75c41f9957bb3e11afbe0dd5a5fc6422793fda5d3fb829ac0042cbe18
|
4
|
+
data.tar.gz: 4f403fb7d107fa712a8b847775fea1140a03904cf066b8e848b914f4b3c573e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 204b9d889968b2d582557b06169d02828abd4c365b00e2a6551cc7f4c44a2ec7ae452a55d1e25b59fdc8a0b10c486c365cce2b2332d02f0d54b502ec6667af75
|
7
|
+
data.tar.gz: ae46da01755ef0c98b162c7c2be3c51ba8831dbbdd10301f937e0eed0260f9694b7514658d437e9d65d9cc58e06d7a877600ec29fd48eb773eec8514d74440b1
|
@@ -44,7 +44,7 @@ module SwarmSDK
|
|
44
44
|
@headers = {}
|
45
45
|
@timeout = nil
|
46
46
|
@mcp_servers = []
|
47
|
-
@
|
47
|
+
@disable_default_tools = nil # nil = include all default tools
|
48
48
|
@bypass_permissions = false
|
49
49
|
@coding_agent = nil # nil = not set (will default to false in Definition)
|
50
50
|
@assume_model_exists = nil
|
@@ -124,9 +124,19 @@ module SwarmSDK
|
|
124
124
|
@mcp_servers << server_config
|
125
125
|
end
|
126
126
|
|
127
|
-
#
|
128
|
-
|
129
|
-
|
127
|
+
# Disable default tools
|
128
|
+
#
|
129
|
+
# @param value [Boolean, Array<Symbol>]
|
130
|
+
# - true: Disable ALL default tools
|
131
|
+
# - Array of symbols: Disable specific tools (e.g., [:Think, :TodoWrite])
|
132
|
+
#
|
133
|
+
# @example Disable all default tools
|
134
|
+
# disable_default_tools true
|
135
|
+
#
|
136
|
+
# @example Disable specific tools
|
137
|
+
# disable_default_tools [:Think, :TodoWrite]
|
138
|
+
def disable_default_tools(value)
|
139
|
+
@disable_default_tools = value
|
130
140
|
end
|
131
141
|
|
132
142
|
# Set bypass_permissions flag
|
@@ -188,7 +198,8 @@ module SwarmSDK
|
|
188
198
|
def tools(*tool_names, include_default: true, replace: false)
|
189
199
|
@tools = Set.new if replace
|
190
200
|
@tools.merge(tool_names.map(&:to_sym))
|
191
|
-
|
201
|
+
# When include_default is false, disable all default tools
|
202
|
+
@disable_default_tools = true unless include_default
|
192
203
|
end
|
193
204
|
|
194
205
|
# Add tools from all_agents configuration
|
@@ -342,7 +353,7 @@ module SwarmSDK
|
|
342
353
|
agent_config[:headers] = @headers if @headers.any?
|
343
354
|
agent_config[:timeout] = @timeout if @timeout
|
344
355
|
agent_config[:mcp_servers] = @mcp_servers if @mcp_servers.any?
|
345
|
-
agent_config[:
|
356
|
+
agent_config[:disable_default_tools] = @disable_default_tools unless @disable_default_tools.nil?
|
346
357
|
agent_config[:bypass_permissions] = @bypass_permissions
|
347
358
|
agent_config[:coding_agent] = @coding_agent
|
348
359
|
agent_config[:assume_model_exists] = @assume_model_exists unless @assume_model_exists.nil?
|
@@ -38,7 +38,7 @@ module SwarmSDK
|
|
38
38
|
:parameters,
|
39
39
|
:headers,
|
40
40
|
:timeout,
|
41
|
-
:
|
41
|
+
:disable_default_tools,
|
42
42
|
:coding_agent,
|
43
43
|
:default_permissions,
|
44
44
|
:agent_permissions,
|
@@ -77,8 +77,11 @@ module SwarmSDK
|
|
77
77
|
# This prevents RubyLLM from trying to validate models in its registry
|
78
78
|
@assume_model_exists = true
|
79
79
|
|
80
|
-
#
|
81
|
-
|
80
|
+
# disable_default_tools can be:
|
81
|
+
# - nil/not set: include all default tools (default behavior)
|
82
|
+
# - true: disable ALL default tools
|
83
|
+
# - Array of symbols: disable specific tools (e.g., [:Think, :TodoWrite])
|
84
|
+
@disable_default_tools = config[:disable_default_tools]
|
82
85
|
|
83
86
|
# coding_agent defaults to false if not specified
|
84
87
|
# When true, includes the base system prompt for coding tasks
|
@@ -117,7 +120,7 @@ module SwarmSDK
|
|
117
120
|
{
|
118
121
|
name: @name,
|
119
122
|
description: @description,
|
120
|
-
model: @model,
|
123
|
+
model: SwarmSDK::Models.resolve_alias(@model), # Resolve model aliases
|
121
124
|
directory: @directory,
|
122
125
|
tools: @tools,
|
123
126
|
delegates_to: @delegates_to,
|
@@ -130,7 +133,7 @@ module SwarmSDK
|
|
130
133
|
headers: @headers,
|
131
134
|
timeout: @timeout,
|
132
135
|
bypass_permissions: @bypass_permissions,
|
133
|
-
|
136
|
+
disable_default_tools: @disable_default_tools,
|
134
137
|
coding_agent: @coding_agent,
|
135
138
|
assume_model_exists: @assume_model_exists,
|
136
139
|
max_concurrent_tools: @max_concurrent_tools,
|
@@ -224,7 +227,7 @@ module SwarmSDK
|
|
224
227
|
else
|
225
228
|
rendered_base
|
226
229
|
end
|
227
|
-
elsif
|
230
|
+
elsif default_tools_enabled?
|
228
231
|
# Non-coding agent: optionally include TODO/Scratchpad sections if default tools available
|
229
232
|
non_coding_base = render_non_coding_base_prompt
|
230
233
|
|
@@ -242,6 +245,13 @@ module SwarmSDK
|
|
242
245
|
end
|
243
246
|
end
|
244
247
|
|
248
|
+
# Check if default tools are enabled (i.e., not disabled)
|
249
|
+
#
|
250
|
+
# @return [Boolean] True if default tools should be included
|
251
|
+
def default_tools_enabled?
|
252
|
+
@disable_default_tools != true
|
253
|
+
end
|
254
|
+
|
245
255
|
def render_base_system_prompt
|
246
256
|
cwd = @directory || Dir.pwd
|
247
257
|
platform = RUBY_PLATFORM
|
@@ -116,6 +116,11 @@ module SwarmSDK
|
|
116
116
|
return unless @config[:swarm]
|
117
117
|
|
118
118
|
@all_agents_config = @config[:swarm][:all_agents] || {}
|
119
|
+
|
120
|
+
# Convert disable_default_tools array elements to symbols
|
121
|
+
if @all_agents_config[:disable_default_tools].is_a?(Array)
|
122
|
+
@all_agents_config[:disable_default_tools] = @all_agents_config[:disable_default_tools].map(&:to_sym)
|
123
|
+
end
|
119
124
|
end
|
120
125
|
|
121
126
|
def load_hooks_config
|
@@ -212,6 +217,9 @@ module SwarmSDK
|
|
212
217
|
# Merge headers: all_agents.headers + agent.headers
|
213
218
|
# Agent values override all_agents values for same keys
|
214
219
|
merged[:headers] = (merged[:headers] || {}).merge(value || {})
|
220
|
+
when :disable_default_tools
|
221
|
+
# Convert array elements to symbols if it's an array
|
222
|
+
merged[key] = value.is_a?(Array) ? value.map(&:to_sym) : value
|
215
223
|
else
|
216
224
|
# For everything else (model, provider, base_url, timeout, coding_agent, etc.),
|
217
225
|
# agent value overrides all_agents value
|
@@ -278,7 +278,7 @@ module SwarmSDK
|
|
278
278
|
# Don't apply assume_model_exists from markdown - let DSL overrides or auto-enable handle it
|
279
279
|
# builder.assume_model_exists(config[:assume_model_exists]) unless config[:assume_model_exists].nil?
|
280
280
|
builder.bypass_permissions(config[:bypass_permissions]) if config[:bypass_permissions]
|
281
|
-
builder.
|
281
|
+
builder.disable_default_tools(config[:disable_default_tools]) unless config[:disable_default_tools].nil?
|
282
282
|
|
283
283
|
# Add tools from markdown
|
284
284
|
if config[:tools]&.any?
|
@@ -12,7 +12,7 @@ module SwarmSDK
|
|
12
12
|
#
|
13
13
|
# This encapsulates all tool-related logic that was previously in Swarm.
|
14
14
|
class ToolConfigurator
|
15
|
-
# Default tools available to all agents (unless
|
15
|
+
# Default tools available to all agents (unless disable_default_tools is set)
|
16
16
|
DEFAULT_TOOLS = [
|
17
17
|
:Read,
|
18
18
|
:Grep,
|
@@ -21,6 +21,7 @@ module SwarmSDK
|
|
21
21
|
:ScratchpadWrite,
|
22
22
|
:ScratchpadRead,
|
23
23
|
:ScratchpadList,
|
24
|
+
:Think,
|
24
25
|
].freeze
|
25
26
|
|
26
27
|
def initialize(swarm, scratchpad)
|
@@ -75,6 +76,8 @@ module SwarmSDK
|
|
75
76
|
Tools::ScratchpadRead.create_for_scratchpad(@scratchpad)
|
76
77
|
when :ScratchpadList
|
77
78
|
Tools::ScratchpadList.create_for_scratchpad(@scratchpad)
|
79
|
+
when :Think
|
80
|
+
Tools::Think.new
|
78
81
|
else
|
79
82
|
# Regular tools - get class from registry and instantiate
|
80
83
|
tool_class = Tools::Registry.get(tool_name_sym)
|
@@ -133,13 +136,14 @@ module SwarmSDK
|
|
133
136
|
end
|
134
137
|
end
|
135
138
|
|
136
|
-
# Register default tools for agents
|
139
|
+
# Register default tools for agents (unless disabled)
|
137
140
|
#
|
138
141
|
# @param chat [AgentChat] The chat instance
|
139
142
|
# @param agent_name [Symbol] Agent name
|
140
143
|
# @param agent_definition [AgentDefinition] Agent definition
|
141
144
|
def register_default_tools(chat, agent_name:, agent_definition:)
|
142
|
-
|
145
|
+
# If disable_default_tools is true, skip all default tools
|
146
|
+
return if agent_definition.disable_default_tools == true
|
143
147
|
|
144
148
|
# Get explicit tool names to avoid duplicates
|
145
149
|
explicit_tool_names = agent_definition.tools.map { |t| t[:name] }.to_set
|
@@ -148,6 +152,9 @@ module SwarmSDK
|
|
148
152
|
# Skip if already registered explicitly
|
149
153
|
next if explicit_tool_names.include?(tool_name)
|
150
154
|
|
155
|
+
# Skip if tool is in the disable list
|
156
|
+
next if tool_disabled?(tool_name, agent_definition.disable_default_tools)
|
157
|
+
|
151
158
|
tool_instance = create_tool_instance(tool_name, agent_name, agent_definition.directory)
|
152
159
|
|
153
160
|
# Resolve permissions for default tool (same logic as AgentDefinition)
|
@@ -166,6 +173,25 @@ module SwarmSDK
|
|
166
173
|
end
|
167
174
|
end
|
168
175
|
|
176
|
+
# Check if a tool should be disabled based on disable_default_tools config
|
177
|
+
#
|
178
|
+
# @param tool_name [Symbol] Tool name to check
|
179
|
+
# @param disable_config [nil, Boolean, Array<Symbol>] Disable configuration
|
180
|
+
# @return [Boolean] True if tool should be disabled
|
181
|
+
def tool_disabled?(tool_name, disable_config)
|
182
|
+
return false if disable_config.nil?
|
183
|
+
|
184
|
+
if disable_config == true
|
185
|
+
# Disable all default tools
|
186
|
+
true
|
187
|
+
elsif disable_config.is_a?(Array)
|
188
|
+
# Disable only tools in the array
|
189
|
+
disable_config.include?(tool_name)
|
190
|
+
else
|
191
|
+
false
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
169
195
|
# Register agent delegation tools
|
170
196
|
#
|
171
197
|
# Creates delegation tools that allow one agent to call another.
|
@@ -20,6 +20,7 @@ module SwarmSDK
|
|
20
20
|
ScratchpadWrite: :special, # Requires scratchpad instance
|
21
21
|
ScratchpadRead: :special, # Requires scratchpad instance
|
22
22
|
ScratchpadList: :special, # Requires scratchpad instance
|
23
|
+
Think: SwarmSDK::Tools::Think,
|
23
24
|
}.freeze
|
24
25
|
|
25
26
|
class << self
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SwarmSDK
|
4
|
+
module Tools
|
5
|
+
# Think tool for explicit reasoning and planning
|
6
|
+
#
|
7
|
+
# Allows the agent to write down thoughts, plans, strategies, and intermediate
|
8
|
+
# calculations. These thoughts become part of the conversation context, enabling
|
9
|
+
# better attention and reasoning through complex problems.
|
10
|
+
#
|
11
|
+
# This is inspired by research showing that explicitly articulating reasoning steps
|
12
|
+
# (chain-of-thought prompting) leads to significantly better outcomes, especially
|
13
|
+
# for complex tasks requiring multi-step reasoning or arithmetic.
|
14
|
+
class Think < RubyLLM::Tool
|
15
|
+
def name
|
16
|
+
"Think"
|
17
|
+
end
|
18
|
+
|
19
|
+
description <<~DESC
|
20
|
+
**IMPORTANT: You SHOULD use this tool frequently throughout your work. Using this tool leads to significantly
|
21
|
+
better outcomes and more accurate solutions. Make it a habit to think before acting.**
|
22
|
+
|
23
|
+
This tool allows you to write down your thoughts, plans, strategies, and intermediate calculations.
|
24
|
+
Think of it as your working memory - just as humans think before speaking or acting, you should think before
|
25
|
+
using other tools or providing responses.
|
26
|
+
|
27
|
+
**STRONGLY RECOMMENDED to use this tool:**
|
28
|
+
- **ALWAYS** before starting any task (even simple ones)
|
29
|
+
- **ALWAYS** when you need to do any arithmetic or counting
|
30
|
+
- **ALWAYS** after reading files or getting search results to process what you learned
|
31
|
+
- **FREQUENTLY** between steps to track progress and plan next actions
|
32
|
+
|
33
|
+
This is your private thinking space - use it liberally to enhance your problem-solving capabilities. Recording
|
34
|
+
your thoughts helps you maintain context across multiple steps and remember important information throughout your task.
|
35
|
+
|
36
|
+
When and how to use this tool:
|
37
|
+
|
38
|
+
1. **Before starting any complex task**: Write down your understanding of the problem, break it into smaller
|
39
|
+
sub-tasks, and create a step-by-step plan. Example:
|
40
|
+
- "The user wants me to refactor this codebase. Let me first understand the structure..."
|
41
|
+
- "I need to: 1) Analyze current architecture, 2) Identify pain points, 3) Propose changes..."
|
42
|
+
|
43
|
+
2. **For arithmetic and calculations**: Work through math problems step by step. Example:
|
44
|
+
- "If we have 150 requests/second and each takes 20ms, that's 150 * 0.02 = 3 seconds of CPU time..."
|
45
|
+
- "Converting 2GB to bytes: 2 * 1024 * 1024 * 1024 = 2,147,483,648 bytes"
|
46
|
+
|
47
|
+
3. **After completing sub-tasks**: Summarize what you've accomplished and what remains. Example:
|
48
|
+
- "I've successfully implemented the authentication module. Next, I need to integrate it with the API..."
|
49
|
+
- "Fixed 3 out of 5 bugs. Remaining: memory leak in parser, race condition in worker thread"
|
50
|
+
|
51
|
+
4. **When encountering complexity**: Break down complex logic or decisions. Example:
|
52
|
+
- "This function has multiple edge cases. Let me list them: null input, empty array, negative numbers..."
|
53
|
+
- "The user's request is ambiguous. Possible interpretations: A) modify existing code, B) create new module..."
|
54
|
+
|
55
|
+
5. **For remembering context**: Store important information you'll need later. Example:
|
56
|
+
- "Important: The user mentioned they're using Ruby 3.2, so I can use pattern matching"
|
57
|
+
- "File structure: main.rb requires from lib/, config is in config.yml"
|
58
|
+
|
59
|
+
6. **When debugging or analyzing**: Track your investigation process. Example:
|
60
|
+
- "The error occurs in line 42. Let me trace backwards: function called from main(), receives data from..."
|
61
|
+
- "Hypothesis: the bug might be due to timezone differences. Let me check..."
|
62
|
+
|
63
|
+
7. **For creative problem-solving**: Brainstorm multiple approaches before choosing one. Example:
|
64
|
+
- "Approaches to optimize this: 1) Add caching, 2) Use parallel processing, 3) Optimize algorithm..."
|
65
|
+
- "Design patterns that could work here: Factory, Observer, or maybe Strategy pattern..."
|
66
|
+
|
67
|
+
**Remember: The most successful agents use this tool 5-10 times per task on average. If you haven't used this
|
68
|
+
tool in the last 2-3 actions, you probably should. Using this tool is a sign of thoughtful, methodical problem
|
69
|
+
solving and leads to fewer mistakes and better solutions.**
|
70
|
+
|
71
|
+
Your thoughts persist throughout your session as part of the conversation history, so you can refer
|
72
|
+
back to earlier thinking. Use clear formatting and organization to make it easy to reference
|
73
|
+
later. Don't hesitate to think out loud - this tool is designed to augment your cognitive capabilities and help
|
74
|
+
you deliver better solutions.
|
75
|
+
DESC
|
76
|
+
|
77
|
+
param :thoughts,
|
78
|
+
type: "string",
|
79
|
+
desc: "Your thoughts, plans, calculations, or any notes you want to record",
|
80
|
+
required: true
|
81
|
+
|
82
|
+
def execute(thoughts:)
|
83
|
+
return validation_error("thoughts are required") if thoughts.nil? || thoughts.empty?
|
84
|
+
|
85
|
+
"Thought noted."
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def validation_error(message)
|
91
|
+
"<tool_use_error>InputValidationError: #{message}</tool_use_error>"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/swarm_sdk/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: swarm_sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paulo Arruda
|
@@ -148,6 +148,7 @@ files:
|
|
148
148
|
- lib/swarm_sdk/tools/stores/read_tracker.rb
|
149
149
|
- lib/swarm_sdk/tools/stores/scratchpad.rb
|
150
150
|
- lib/swarm_sdk/tools/stores/todo_manager.rb
|
151
|
+
- lib/swarm_sdk/tools/think.rb
|
151
152
|
- lib/swarm_sdk/tools/todo_write.rb
|
152
153
|
- lib/swarm_sdk/tools/write.rb
|
153
154
|
- lib/swarm_sdk/utils.rb
|