rcrewai 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 +7 -0
- data/CHANGELOG.md +108 -0
- data/LICENSE +21 -0
- data/README.md +328 -0
- data/Rakefile +130 -0
- data/bin/rcrewai +7 -0
- data/docs/_config.yml +59 -0
- data/docs/_layouts/api.html +16 -0
- data/docs/_layouts/default.html +78 -0
- data/docs/_layouts/example.html +24 -0
- data/docs/_layouts/tutorial.html +33 -0
- data/docs/api/configuration.md +327 -0
- data/docs/api/crew.md +345 -0
- data/docs/api/index.md +41 -0
- data/docs/api/tools.md +412 -0
- data/docs/assets/css/style.css +416 -0
- data/docs/examples/human-in-the-loop.md +382 -0
- data/docs/examples/index.md +78 -0
- data/docs/examples/production-ready-crew.md +485 -0
- data/docs/examples/simple-research-crew.md +297 -0
- data/docs/index.md +353 -0
- data/docs/tutorials/getting-started.md +341 -0
- data/examples/async_execution_example.rb +294 -0
- data/examples/hierarchical_crew_example.rb +193 -0
- data/examples/human_in_the_loop_example.rb +233 -0
- data/lib/rcrewai/agent.rb +636 -0
- data/lib/rcrewai/async_executor.rb +248 -0
- data/lib/rcrewai/cli.rb +39 -0
- data/lib/rcrewai/configuration.rb +100 -0
- data/lib/rcrewai/crew.rb +292 -0
- data/lib/rcrewai/human_input.rb +520 -0
- data/lib/rcrewai/llm_client.rb +41 -0
- data/lib/rcrewai/llm_clients/anthropic.rb +127 -0
- data/lib/rcrewai/llm_clients/azure.rb +158 -0
- data/lib/rcrewai/llm_clients/base.rb +82 -0
- data/lib/rcrewai/llm_clients/google.rb +158 -0
- data/lib/rcrewai/llm_clients/ollama.rb +199 -0
- data/lib/rcrewai/llm_clients/openai.rb +124 -0
- data/lib/rcrewai/memory.rb +194 -0
- data/lib/rcrewai/process.rb +421 -0
- data/lib/rcrewai/task.rb +376 -0
- data/lib/rcrewai/tools/base.rb +82 -0
- data/lib/rcrewai/tools/code_executor.rb +333 -0
- data/lib/rcrewai/tools/email_sender.rb +210 -0
- data/lib/rcrewai/tools/file_reader.rb +111 -0
- data/lib/rcrewai/tools/file_writer.rb +115 -0
- data/lib/rcrewai/tools/pdf_processor.rb +342 -0
- data/lib/rcrewai/tools/sql_database.rb +226 -0
- data/lib/rcrewai/tools/web_search.rb +131 -0
- data/lib/rcrewai/version.rb +5 -0
- data/lib/rcrewai.rb +36 -0
- data/rcrewai.gemspec +54 -0
- metadata +365 -0
data/docs/api/tools.md
ADDED
@@ -0,0 +1,412 @@
|
|
1
|
+
---
|
2
|
+
layout: api
|
3
|
+
title: Tools System
|
4
|
+
description: Comprehensive guide to RCrewAI's tool system and built-in tools
|
5
|
+
---
|
6
|
+
|
7
|
+
# Tools System
|
8
|
+
|
9
|
+
RCrewAI's tool system allows agents to interact with external systems, APIs, files, and perform specialized tasks. Tools extend agent capabilities beyond just generating text.
|
10
|
+
|
11
|
+
## Overview
|
12
|
+
|
13
|
+
Tools in RCrewAI are:
|
14
|
+
- **Secure**: Built-in security controls and validation
|
15
|
+
- **Extensible**: Easy to create custom tools
|
16
|
+
- **Integrated**: Seamlessly work with agent reasoning
|
17
|
+
- **Robust**: Error handling and recovery mechanisms
|
18
|
+
|
19
|
+
## Built-in Tools
|
20
|
+
|
21
|
+
### WebSearch
|
22
|
+
|
23
|
+
Search the web for information using DuckDuckGo.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
search_tool = RCrewAI::Tools::WebSearch.new(max_results: 10, timeout: 30)
|
27
|
+
|
28
|
+
# Agent usage
|
29
|
+
agent = RCrewAI::Agent.new(
|
30
|
+
name: "researcher",
|
31
|
+
role: "Research Analyst",
|
32
|
+
goal: "Find information on any topic",
|
33
|
+
tools: [search_tool]
|
34
|
+
)
|
35
|
+
```
|
36
|
+
|
37
|
+
**Parameters:**
|
38
|
+
- `query` (required): Search query string
|
39
|
+
- `max_results` (optional): Maximum number of results (default: 5)
|
40
|
+
|
41
|
+
**Example Agent Usage:**
|
42
|
+
```
|
43
|
+
Agent reasoning: "I need to research AI trends"
|
44
|
+
Agent action: USE_TOOL[websearch](query=AI trends 2024, max_results=5)
|
45
|
+
```
|
46
|
+
|
47
|
+
**Features:**
|
48
|
+
- No API key required (uses DuckDuckGo)
|
49
|
+
- Extracts titles, URLs, and snippets
|
50
|
+
- Handles rate limiting and errors
|
51
|
+
- Clean, formatted results
|
52
|
+
|
53
|
+
### FileReader
|
54
|
+
|
55
|
+
Read contents from files with security controls.
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
reader_tool = RCrewAI::Tools::FileReader.new(
|
59
|
+
max_file_size: 5_000_000, # 5MB limit
|
60
|
+
allowed_extensions: %w[.txt .md .json .csv .log]
|
61
|
+
)
|
62
|
+
|
63
|
+
agent = RCrewAI::Agent.new(
|
64
|
+
name: "analyst",
|
65
|
+
role: "Data Analyst",
|
66
|
+
goal: "Analyze file contents",
|
67
|
+
tools: [reader_tool]
|
68
|
+
)
|
69
|
+
```
|
70
|
+
|
71
|
+
**Parameters:**
|
72
|
+
- `file_path` (required): Path to file to read
|
73
|
+
- `encoding` (optional): File encoding (default: utf-8)
|
74
|
+
- `lines` (optional): Read only N lines
|
75
|
+
|
76
|
+
**Security Features:**
|
77
|
+
- File size limits
|
78
|
+
- Extension restrictions
|
79
|
+
- Directory traversal protection
|
80
|
+
- Working directory enforcement
|
81
|
+
|
82
|
+
**Example Usage:**
|
83
|
+
```
|
84
|
+
USE_TOOL[filereader](file_path=data.csv, lines=100)
|
85
|
+
```
|
86
|
+
|
87
|
+
### FileWriter
|
88
|
+
|
89
|
+
Write content to files with security and validation.
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
writer_tool = RCrewAI::Tools::FileWriter.new(
|
93
|
+
max_file_size: 10_000_000, # 10MB limit
|
94
|
+
allowed_extensions: %w[.txt .md .json .csv],
|
95
|
+
create_directories: true
|
96
|
+
)
|
97
|
+
```
|
98
|
+
|
99
|
+
**Parameters:**
|
100
|
+
- `file_path` (required): Path where to write file
|
101
|
+
- `content` (required): Content to write
|
102
|
+
- `mode` (optional): Write mode ('w', 'a', 'w+', etc.)
|
103
|
+
- `encoding` (optional): File encoding (default: utf-8)
|
104
|
+
|
105
|
+
**Example Usage:**
|
106
|
+
```
|
107
|
+
USE_TOOL[filewriter](file_path=report.md, content=## Report\nThis is my analysis...)
|
108
|
+
```
|
109
|
+
|
110
|
+
**Security Features:**
|
111
|
+
- Content size validation
|
112
|
+
- Path traversal protection
|
113
|
+
- Extension restrictions
|
114
|
+
- Automatic directory creation
|
115
|
+
|
116
|
+
## Creating Custom Tools
|
117
|
+
|
118
|
+
### Basic Custom Tool
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
class MyCustomTool < RCrewAI::Tools::Base
|
122
|
+
def initialize(**options)
|
123
|
+
super()
|
124
|
+
@name = 'mycustomtool'
|
125
|
+
@description = 'Description of what this tool does'
|
126
|
+
@api_key = options[:api_key]
|
127
|
+
end
|
128
|
+
|
129
|
+
def execute(**params)
|
130
|
+
validate_params!(params, required: [:input], optional: [:format])
|
131
|
+
|
132
|
+
input = params[:input]
|
133
|
+
format = params[:format] || 'json'
|
134
|
+
|
135
|
+
begin
|
136
|
+
# Your tool logic here
|
137
|
+
result = process_input(input, format)
|
138
|
+
format_result(result)
|
139
|
+
rescue => e
|
140
|
+
"Tool execution failed: #{e.message}"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def process_input(input, format)
|
147
|
+
# Implement your tool logic
|
148
|
+
"Processed: #{input} in #{format} format"
|
149
|
+
end
|
150
|
+
|
151
|
+
def format_result(result)
|
152
|
+
result.to_s
|
153
|
+
end
|
154
|
+
end
|
155
|
+
```
|
156
|
+
|
157
|
+
### Advanced Custom Tool Example
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
class APIClientTool < RCrewAI::Tools::Base
|
161
|
+
def initialize(**options)
|
162
|
+
super()
|
163
|
+
@name = 'apiclient'
|
164
|
+
@description = 'Make HTTP requests to APIs'
|
165
|
+
@base_url = options[:base_url]
|
166
|
+
@api_key = options[:api_key]
|
167
|
+
@timeout = options.fetch(:timeout, 30)
|
168
|
+
end
|
169
|
+
|
170
|
+
def execute(**params)
|
171
|
+
validate_params!(
|
172
|
+
params,
|
173
|
+
required: [:endpoint, :method],
|
174
|
+
optional: [:data, :headers]
|
175
|
+
)
|
176
|
+
|
177
|
+
endpoint = params[:endpoint]
|
178
|
+
method = params[:method].upcase
|
179
|
+
data = params[:data]
|
180
|
+
headers = params[:headers] || {}
|
181
|
+
|
182
|
+
# Add authentication
|
183
|
+
headers['Authorization'] = "Bearer #{@api_key}" if @api_key
|
184
|
+
headers['Content-Type'] = 'application/json'
|
185
|
+
|
186
|
+
begin
|
187
|
+
response = make_request(method, endpoint, data, headers)
|
188
|
+
format_api_response(response)
|
189
|
+
rescue => e
|
190
|
+
"API request failed: #{e.message}"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
private
|
195
|
+
|
196
|
+
def make_request(method, endpoint, data, headers)
|
197
|
+
url = "#{@base_url}#{endpoint}"
|
198
|
+
|
199
|
+
http_client = Faraday.new do |f|
|
200
|
+
f.adapter Faraday.default_adapter
|
201
|
+
f.options.timeout = @timeout
|
202
|
+
end
|
203
|
+
|
204
|
+
case method
|
205
|
+
when 'GET'
|
206
|
+
http_client.get(url, data, headers)
|
207
|
+
when 'POST'
|
208
|
+
http_client.post(url, data&.to_json, headers)
|
209
|
+
when 'PUT'
|
210
|
+
http_client.put(url, data&.to_json, headers)
|
211
|
+
when 'DELETE'
|
212
|
+
http_client.delete(url, data, headers)
|
213
|
+
else
|
214
|
+
raise ToolError, "Unsupported HTTP method: #{method}"
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def format_api_response(response)
|
219
|
+
result = "Status: #{response.status}\n"
|
220
|
+
result += "Headers: #{response.headers.to_h}\n"
|
221
|
+
result += "Body: #{response.body}"
|
222
|
+
result
|
223
|
+
end
|
224
|
+
end
|
225
|
+
```
|
226
|
+
|
227
|
+
## Tool Integration Patterns
|
228
|
+
|
229
|
+
### Agent with Multiple Tools
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
# Create specialized tools
|
233
|
+
search_tool = RCrewAI::Tools::WebSearch.new
|
234
|
+
file_reader = RCrewAI::Tools::FileReader.new
|
235
|
+
file_writer = RCrewAI::Tools::FileWriter.new
|
236
|
+
api_client = APIClientTool.new(base_url: 'https://api.example.com', api_key: ENV['API_KEY'])
|
237
|
+
|
238
|
+
# Agent with comprehensive toolkit
|
239
|
+
agent = RCrewAI::Agent.new(
|
240
|
+
name: "multi_tool_agent",
|
241
|
+
role: "Full-Stack AI Assistant",
|
242
|
+
goal: "Handle any task requiring web research, file operations, or API calls",
|
243
|
+
tools: [search_tool, file_reader, file_writer, api_client],
|
244
|
+
verbose: true,
|
245
|
+
max_iterations: 10
|
246
|
+
)
|
247
|
+
```
|
248
|
+
|
249
|
+
### Task-Specific Tools
|
250
|
+
|
251
|
+
```ruby
|
252
|
+
# Research task with web search
|
253
|
+
research_task = RCrewAI::Task.new(
|
254
|
+
name: "market_research",
|
255
|
+
description: "Research competitor pricing and features",
|
256
|
+
agent: researcher_agent,
|
257
|
+
tools: [RCrewAI::Tools::WebSearch.new(max_results: 15)] # Task-specific tool
|
258
|
+
)
|
259
|
+
|
260
|
+
# Analysis task with file operations
|
261
|
+
analysis_task = RCrewAI::Task.new(
|
262
|
+
name: "data_analysis",
|
263
|
+
description: "Analyze data files and generate report",
|
264
|
+
agent: analyst_agent,
|
265
|
+
tools: [
|
266
|
+
RCrewAI::Tools::FileReader.new(allowed_extensions: %w[.csv .json .xlsx]),
|
267
|
+
RCrewAI::Tools::FileWriter.new
|
268
|
+
]
|
269
|
+
)
|
270
|
+
```
|
271
|
+
|
272
|
+
### Dynamic Tool Loading
|
273
|
+
|
274
|
+
```ruby
|
275
|
+
class ToolManager
|
276
|
+
def self.create_tool_set(requirements)
|
277
|
+
tools = []
|
278
|
+
|
279
|
+
tools << RCrewAI::Tools::WebSearch.new if requirements.include?(:web_search)
|
280
|
+
tools << RCrewAI::Tools::FileReader.new if requirements.include?(:file_read)
|
281
|
+
tools << RCrewAI::Tools::FileWriter.new if requirements.include?(:file_write)
|
282
|
+
|
283
|
+
if requirements.include?(:api_access)
|
284
|
+
tools << APIClientTool.new(
|
285
|
+
base_url: ENV['API_BASE_URL'],
|
286
|
+
api_key: ENV['API_KEY']
|
287
|
+
)
|
288
|
+
end
|
289
|
+
|
290
|
+
tools
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
# Usage
|
295
|
+
requirements = [:web_search, :file_write, :api_access]
|
296
|
+
agent_tools = ToolManager.create_tool_set(requirements)
|
297
|
+
|
298
|
+
agent = RCrewAI::Agent.new(
|
299
|
+
name: "dynamic_agent",
|
300
|
+
role: "Adaptive Assistant",
|
301
|
+
goal: "Handle tasks based on available tools",
|
302
|
+
tools: agent_tools
|
303
|
+
)
|
304
|
+
```
|
305
|
+
|
306
|
+
## Tool Best Practices
|
307
|
+
|
308
|
+
### Security
|
309
|
+
|
310
|
+
1. **Validate all inputs**: Use `validate_params!` helper
|
311
|
+
2. **Limit resource usage**: Set file size, timeout limits
|
312
|
+
3. **Restrict file access**: Use allowed extensions and path validation
|
313
|
+
4. **Sanitize outputs**: Clean potentially dangerous content
|
314
|
+
|
315
|
+
```ruby
|
316
|
+
def execute(**params)
|
317
|
+
validate_params!(params, required: [:input])
|
318
|
+
|
319
|
+
# Sanitize input
|
320
|
+
input = params[:input].to_s.strip
|
321
|
+
raise ToolError, "Input too long" if input.length > 1000
|
322
|
+
|
323
|
+
# Process safely...
|
324
|
+
end
|
325
|
+
```
|
326
|
+
|
327
|
+
### Error Handling
|
328
|
+
|
329
|
+
```ruby
|
330
|
+
def execute(**params)
|
331
|
+
validate_params!(params, required: [:data])
|
332
|
+
|
333
|
+
begin
|
334
|
+
result = risky_operation(params[:data])
|
335
|
+
return result
|
336
|
+
rescue APITimeoutError => e
|
337
|
+
"Operation timed out: #{e.message}"
|
338
|
+
rescue APIRateLimitError => e
|
339
|
+
"Rate limit exceeded, try again later"
|
340
|
+
rescue => e
|
341
|
+
logger.error "Unexpected error in #{@name}: #{e.message}"
|
342
|
+
"Tool failed: #{e.message}"
|
343
|
+
end
|
344
|
+
end
|
345
|
+
```
|
346
|
+
|
347
|
+
### Performance
|
348
|
+
|
349
|
+
1. **Use connection pooling** for HTTP clients
|
350
|
+
2. **Cache results** when appropriate
|
351
|
+
3. **Stream large files** instead of loading entirely
|
352
|
+
4. **Implement timeouts** for all external calls
|
353
|
+
|
354
|
+
### Testing Tools
|
355
|
+
|
356
|
+
```ruby
|
357
|
+
require 'rspec'
|
358
|
+
|
359
|
+
RSpec.describe MyCustomTool do
|
360
|
+
let(:tool) { MyCustomTool.new(api_key: 'test-key') }
|
361
|
+
|
362
|
+
it 'processes input correctly' do
|
363
|
+
result = tool.execute(input: 'test data', format: 'json')
|
364
|
+
expect(result).to include('Processed: test data')
|
365
|
+
end
|
366
|
+
|
367
|
+
it 'validates required parameters' do
|
368
|
+
expect {
|
369
|
+
tool.execute(format: 'json') # Missing required 'input'
|
370
|
+
}.to raise_error(RCrewAI::Tools::ToolError)
|
371
|
+
end
|
372
|
+
|
373
|
+
it 'handles errors gracefully' do
|
374
|
+
allow(tool).to receive(:process_input).and_raise(StandardError.new('API down'))
|
375
|
+
result = tool.execute(input: 'test')
|
376
|
+
expect(result).to include('Tool execution failed')
|
377
|
+
end
|
378
|
+
end
|
379
|
+
```
|
380
|
+
|
381
|
+
## Available Tool Registry
|
382
|
+
|
383
|
+
```ruby
|
384
|
+
# List all available tool classes
|
385
|
+
puts RCrewAI::Tools::Base.available_tools
|
386
|
+
|
387
|
+
# Create tool by name
|
388
|
+
search_tool = RCrewAI::Tools::Base.create_tool('websearch', max_results: 10)
|
389
|
+
```
|
390
|
+
|
391
|
+
## Tool Debugging
|
392
|
+
|
393
|
+
Enable verbose logging to see tool usage:
|
394
|
+
|
395
|
+
```ruby
|
396
|
+
agent = RCrewAI::Agent.new(
|
397
|
+
name: "debug_agent",
|
398
|
+
role: "Test Agent",
|
399
|
+
goal: "Test tool usage",
|
400
|
+
tools: [RCrewAI::Tools::WebSearch.new],
|
401
|
+
verbose: true # Shows tool calls and results
|
402
|
+
)
|
403
|
+
```
|
404
|
+
|
405
|
+
Tool usage will be logged as:
|
406
|
+
```
|
407
|
+
DEBUG Using tool: websearch with params: {:query=>"AI trends", :max_results=>5}
|
408
|
+
DEBUG Tool websearch result: Search Results:
|
409
|
+
1. Latest AI Trends 2024
|
410
|
+
URL: https://example.com/ai-trends
|
411
|
+
Recent developments in artificial intelligence...
|
412
|
+
```
|