jrubyagents 0.2.1
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/.ruby-version +1 -0
- data/CHANGELOG.md +31 -0
- data/LICENSE +21 -0
- data/README.md +255 -0
- data/ROADMAP.md +56 -0
- data/Rakefile +6 -0
- data/examples/custom_tool.rb +24 -0
- data/examples/fibonacci.rb +7 -0
- data/examples/with_tools.rb +12 -0
- data/exe/rubyagents +6 -0
- data/lib/rubyagents/agent.rb +316 -0
- data/lib/rubyagents/callback.rb +12 -0
- data/lib/rubyagents/cli.rb +146 -0
- data/lib/rubyagents/code_agent.rb +85 -0
- data/lib/rubyagents/errors.rb +21 -0
- data/lib/rubyagents/mcp.rb +128 -0
- data/lib/rubyagents/memory.rb +240 -0
- data/lib/rubyagents/model.rb +99 -0
- data/lib/rubyagents/models/ruby_llm_adapter.rb +158 -0
- data/lib/rubyagents/prompt.rb +123 -0
- data/lib/rubyagents/sandbox.rb +142 -0
- data/lib/rubyagents/tool.rb +124 -0
- data/lib/rubyagents/tool_calling_agent.rb +85 -0
- data/lib/rubyagents/tools/file_read.rb +20 -0
- data/lib/rubyagents/tools/file_write.rb +22 -0
- data/lib/rubyagents/tools/list_gems.rb +15 -0
- data/lib/rubyagents/tools/user_input.rb +16 -0
- data/lib/rubyagents/tools/visit_webpage.rb +44 -0
- data/lib/rubyagents/tools/web_search.rb +43 -0
- data/lib/rubyagents/ui.rb +183 -0
- data/lib/rubyagents/version.rb +5 -0
- data/lib/rubyagents.rb +21 -0
- data/rubyagents.gemspec +44 -0
- metadata +220 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: f365fc9c08f376ff08dcf933c1968829f15a79e518758ba79f8e82e2b8562452
|
|
4
|
+
data.tar.gz: 4e9e8eb4add2dbec0ceb7c2e175133ed8d1ec12fa2bcb6719c124fbf032b3301
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: fbf21991c23fd1418939c1152f67995a1502db87fa08cc29f739c9cb58440a437a3a41d9ffacff21ae098ddfc3ad49d22ae418f72bb50b9a7de5b2a8e047948a
|
|
7
|
+
data.tar.gz: 6afa4e9696415fad82e3969216060b1ef396aaa846ce3fd9e4bafe7c13cef0e6834b8ba18ecaecdb3b54b074c64303816d7abc254d6909ac071c0584e51c1b74
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.4.8
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
Tools, MCP filtering, observability, and code agent improvements.
|
|
6
|
+
|
|
7
|
+
- **FileRead tool** -- Read file contents with path expansion and 50k char truncation
|
|
8
|
+
- **FileWrite tool** -- Write files with automatic parent directory creation
|
|
9
|
+
- **ListGems tool** -- Lists available Ruby gems; auto-included in CodeAgent
|
|
10
|
+
- **`tool_from_mcp`** -- Load a single tool from an MCP server by name
|
|
11
|
+
- **Run export** -- `to_h` / `to_json` on Memory, RunResult, and all step types for serialization
|
|
12
|
+
- **Richer callbacks** -- `Callback` base class with `on_run_start`, `on_step_start`, `on_step_end`, `on_tool_call`, `on_error`, `on_run_end`; backward-compatible with existing `step_callbacks`
|
|
13
|
+
- **`memory.replay`** -- Pretty-print a completed run with syntax-highlighted code and metrics
|
|
14
|
+
- **Code agent prompt** -- Tells the model about available Ruby stdlib and gems so it uses `net/http`, `json`, etc. without being asked
|
|
15
|
+
|
|
16
|
+
## 0.1.0
|
|
17
|
+
|
|
18
|
+
Initial release.
|
|
19
|
+
|
|
20
|
+
- **CodeAgent** -- LLM writes and executes Ruby code in a sandboxed fork
|
|
21
|
+
- **ToolCallingAgent** -- LLM calls tools via structured tool_calls (OpenAI-style)
|
|
22
|
+
- **Model adapters** -- OpenAI, Anthropic, and Ollama out of the box
|
|
23
|
+
- **Tool DSL** -- Define tools as classes or inline blocks
|
|
24
|
+
- **MCP client** -- Load tools from any MCP server via stdio transport
|
|
25
|
+
- **Structured output** -- Validate final answers against JSON Schema or custom procs
|
|
26
|
+
- **Prompt customization** -- Override system prompts, planning prompts, or inject instructions
|
|
27
|
+
- **Final answer checks** -- Validation procs that can reject and retry answers
|
|
28
|
+
- **Step-by-step execution** -- `agent.step()` for debugging and custom UIs
|
|
29
|
+
- **Planning** -- Optional periodic re-planning during long runs
|
|
30
|
+
- **Managed agents** -- Nest agents as tools for multi-agent workflows
|
|
31
|
+
- **CLI** -- `rubyagents` command with interactive mode, tool loading, and MCP support
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Chris Hasiński
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# Rubyagents
|
|
2
|
+
|
|
3
|
+
A radically simple, code-first AI agent framework for Ruby. Inspired by [smolagents](https://github.com/huggingface/smolagents).
|
|
4
|
+
|
|
5
|
+
LLMs write and execute Ruby code -- not JSON blobs. This means tool calls are just method calls, variables persist between steps, and the full power of Ruby is available to the agent at every turn.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
gem install rubyagents
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or add to your Gemfile:
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
gem "rubyagents"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Requires Ruby 3.2+. JRuby 10.0.3.0+ is also supported — the sandbox automatically switches from fork-based to thread-based execution, and platform-specific gems (lipgloss) are skipped gracefully.
|
|
20
|
+
|
|
21
|
+
## Quick start
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
require "rubyagents"
|
|
25
|
+
|
|
26
|
+
agent = Rubyagents::CodeAgent.new(model: "anthropic/claude-sonnet-4-20250514")
|
|
27
|
+
agent.run("What is the 118th Fibonacci number?")
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The agent will think, write Ruby code, execute it in a sandbox, and return the answer.
|
|
31
|
+
|
|
32
|
+
## Model support
|
|
33
|
+
|
|
34
|
+
Pass a model string as `provider/model_name`:
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
# Anthropic
|
|
38
|
+
Rubyagents::CodeAgent.new(model: "anthropic/claude-sonnet-4-20250514")
|
|
39
|
+
|
|
40
|
+
# OpenAI
|
|
41
|
+
Rubyagents::CodeAgent.new(model: "openai/gpt-4o")
|
|
42
|
+
|
|
43
|
+
# Ollama (local)
|
|
44
|
+
Rubyagents::CodeAgent.new(model: "ollama/qwen2.5:3b")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Set API keys via environment variables: `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`.
|
|
48
|
+
|
|
49
|
+
## Agent types
|
|
50
|
+
|
|
51
|
+
**CodeAgent** -- the LLM writes Ruby code that gets executed in a sandboxed environment. Tools are available as methods. Variables persist between steps. On MRI, code runs in a forked child process for full isolation; on JRuby, a thread-based executor is used automatically since fork is unavailable — no configuration needed.
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
agent = Rubyagents::CodeAgent.new(model: "anthropic/claude-sonnet-4-20250514")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**ToolCallingAgent** -- the LLM uses structured tool calls (OpenAI function calling style). Better for models with strong tool_call support.
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
agent = Rubyagents::ToolCallingAgent.new(model: "openai/gpt-4o")
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Custom tools
|
|
64
|
+
|
|
65
|
+
Define tools as classes:
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
class StockPrice < Rubyagents::Tool
|
|
69
|
+
tool_name "stock_price"
|
|
70
|
+
description "Gets the current stock price for a ticker symbol"
|
|
71
|
+
input :ticker, type: :string, description: "Stock ticker symbol (e.g. AAPL)"
|
|
72
|
+
output_type :number
|
|
73
|
+
|
|
74
|
+
def call(ticker:)
|
|
75
|
+
# Your implementation here
|
|
76
|
+
182.52
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
agent = Rubyagents::CodeAgent.new(
|
|
81
|
+
model: "anthropic/claude-sonnet-4-20250514",
|
|
82
|
+
tools: [StockPrice]
|
|
83
|
+
)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Or define them inline:
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
weather = Rubyagents.tool(:weather, "Gets weather for a city", city: "City name") do |city:|
|
|
90
|
+
"72F and sunny in #{city}"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
agent = Rubyagents::CodeAgent.new(model: "anthropic/claude-sonnet-4-20250514", tools: [weather])
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## MCP tools
|
|
97
|
+
|
|
98
|
+
Load tools from any [MCP](https://modelcontextprotocol.io/) server:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
tools = Rubyagents.tools_from_mcp(command: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp"])
|
|
102
|
+
|
|
103
|
+
agent = Rubyagents::CodeAgent.new(
|
|
104
|
+
model: "anthropic/claude-sonnet-4-20250514",
|
|
105
|
+
tools: tools
|
|
106
|
+
)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Structured output
|
|
110
|
+
|
|
111
|
+
Validate final answers against a JSON Schema or custom proc:
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
schema = {
|
|
115
|
+
"type" => "object",
|
|
116
|
+
"required" => ["name", "age"],
|
|
117
|
+
"properties" => {
|
|
118
|
+
"name" => { "type" => "string" },
|
|
119
|
+
"age" => { "type" => "integer" }
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
agent = Rubyagents::CodeAgent.new(
|
|
124
|
+
model: "anthropic/claude-sonnet-4-20250514",
|
|
125
|
+
output_type: schema
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
If the output doesn't match, the agent retries automatically.
|
|
130
|
+
|
|
131
|
+
## Final answer checks
|
|
132
|
+
|
|
133
|
+
Add validation procs that can reject answers and force retries:
|
|
134
|
+
|
|
135
|
+
```ruby
|
|
136
|
+
agent = Rubyagents::CodeAgent.new(
|
|
137
|
+
model: "anthropic/claude-sonnet-4-20250514",
|
|
138
|
+
final_answer_checks: [
|
|
139
|
+
->(answer, memory) { answer.length > 10 },
|
|
140
|
+
->(answer, memory) { !answer.include?("I don't know") }
|
|
141
|
+
]
|
|
142
|
+
)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Prompt customization
|
|
146
|
+
|
|
147
|
+
Inject additional instructions without overriding the full system prompt:
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
agent = Rubyagents::CodeAgent.new(
|
|
151
|
+
model: "anthropic/claude-sonnet-4-20250514",
|
|
152
|
+
instructions: "Always respond in French. Use metric units."
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Or fully replace prompts:
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
templates = Rubyagents::PromptTemplates.new(
|
|
160
|
+
system_prompt: "You are a data analyst. Tools: {{tool_descriptions}}"
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
agent = Rubyagents::CodeAgent.new(
|
|
164
|
+
model: "anthropic/claude-sonnet-4-20250514",
|
|
165
|
+
prompt_templates: templates
|
|
166
|
+
)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Step-by-step execution
|
|
170
|
+
|
|
171
|
+
Run one step at a time for debugging or custom UIs:
|
|
172
|
+
|
|
173
|
+
```ruby
|
|
174
|
+
agent = Rubyagents::CodeAgent.new(model: "anthropic/claude-sonnet-4-20250514")
|
|
175
|
+
|
|
176
|
+
agent.step("What is 2+2?")
|
|
177
|
+
agent.step until agent.done?
|
|
178
|
+
|
|
179
|
+
puts agent.final_answer_value
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Multi-agent workflows
|
|
183
|
+
|
|
184
|
+
Nest agents as tools:
|
|
185
|
+
|
|
186
|
+
```ruby
|
|
187
|
+
researcher = Rubyagents::ToolCallingAgent.new(
|
|
188
|
+
model: "openai/gpt-4o",
|
|
189
|
+
name: "researcher",
|
|
190
|
+
description: "Researches topics on the web",
|
|
191
|
+
tools: [Rubyagents::WebSearch]
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
manager = Rubyagents::CodeAgent.new(
|
|
195
|
+
model: "anthropic/claude-sonnet-4-20250514",
|
|
196
|
+
agents: [researcher]
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
manager.run("Find out when Ruby 3.4 was released and summarize the key features")
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Planning
|
|
203
|
+
|
|
204
|
+
Enable periodic re-planning during long runs:
|
|
205
|
+
|
|
206
|
+
```ruby
|
|
207
|
+
agent = Rubyagents::CodeAgent.new(
|
|
208
|
+
model: "anthropic/claude-sonnet-4-20250514",
|
|
209
|
+
planning_interval: 3, # Re-plan every 3 steps
|
|
210
|
+
max_steps: 15
|
|
211
|
+
)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## CLI
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# Simple query
|
|
218
|
+
rubyagents "What is the 10th prime number?"
|
|
219
|
+
|
|
220
|
+
# With options
|
|
221
|
+
rubyagents -m anthropic/claude-sonnet-4-20250514 -t web_search "Who won the latest Super Bowl?"
|
|
222
|
+
|
|
223
|
+
# Tool-calling agent
|
|
224
|
+
rubyagents -a tool_calling -m openai/gpt-4o "What is 6 * 7?"
|
|
225
|
+
|
|
226
|
+
# With MCP tools
|
|
227
|
+
rubyagents --mcp "npx -y @modelcontextprotocol/server-filesystem /tmp" "List files in /tmp"
|
|
228
|
+
|
|
229
|
+
# Interactive mode
|
|
230
|
+
rubyagents -i
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Configuration
|
|
234
|
+
|
|
235
|
+
| Option | Default | Description |
|
|
236
|
+
|---|---|---|
|
|
237
|
+
| `model:` | -- | Model string (`provider/model_name`) |
|
|
238
|
+
| `tools:` | `[]` | Array of Tool classes or instances |
|
|
239
|
+
| `agents:` | `[]` | Array of Agent instances (become callable tools) |
|
|
240
|
+
| `max_steps:` | `10` | Maximum agent steps before stopping |
|
|
241
|
+
| `planning_interval:` | `nil` | Re-plan every N steps |
|
|
242
|
+
| `instructions:` | `nil` | Extra instructions appended to system prompt |
|
|
243
|
+
| `prompt_templates:` | `nil` | `PromptTemplates` to override system/planning prompts |
|
|
244
|
+
| `output_type:` | `nil` | Hash (JSON Schema) or Proc for output validation |
|
|
245
|
+
| `final_answer_checks:` | `[]` | Array of procs `(answer, memory) -> bool` |
|
|
246
|
+
| `step_callbacks:` | `[]` | Array of procs `(step, agent:) -> void` |
|
|
247
|
+
|
|
248
|
+
## Credits
|
|
249
|
+
|
|
250
|
+
- [@khasinski](https://github.com/khasinski) — creator and maintainer of rubyagents
|
|
251
|
+
- [@parolkar](https://github.com/parolkar) — JRuby compatibility support
|
|
252
|
+
|
|
253
|
+
## License
|
|
254
|
+
|
|
255
|
+
MIT
|
data/ROADMAP.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
Gaps identified by comparing rubyagents with [smolagents](https://github.com/huggingface/smolagents), prioritized for Ruby developers building agents.
|
|
4
|
+
|
|
5
|
+
## Phase 5 -- Core DX (high impact, low effort)
|
|
6
|
+
|
|
7
|
+
These make the framework usable for real work.
|
|
8
|
+
|
|
9
|
+
- [x] **MCP client for tools** -- Load tools from any MCP server (stdio + HTTP). This is the single biggest ecosystem unlock since MCP servers already exist for databases, APIs, file systems, browsers, etc. Ruby devs shouldn't have to rewrite tools that already exist.
|
|
10
|
+
- [x] **Structured output** -- Let agents return typed results (not just strings). Accept a schema or Data class, validate the final answer against it. Enables agents as reliable building blocks in larger apps.
|
|
11
|
+
- [x] **Prompt customization** -- Expose `PromptTemplates` object (system prompt, planning, managed agent) so users can override prompts without subclassing. Add `instructions:` parameter for injecting custom rules.
|
|
12
|
+
- [x] **`agent.step()` method** -- Single-step execution for debugging and building custom UIs. Returns the step, lets the caller inspect/modify memory before continuing.
|
|
13
|
+
- [x] **`final_answer_checks`** -- List of validation procs run before accepting a final answer. If any returns false, the agent keeps going. Cheap way to add guardrails.
|
|
14
|
+
|
|
15
|
+
## Phase 6 -- Model & tool ecosystem (high impact, medium effort)
|
|
16
|
+
|
|
17
|
+
Broader model support and tool discovery. The RubyLLM migration (replacing 3 hand-rolled adapters with a single wrapper) completed most of the model items here.
|
|
18
|
+
|
|
19
|
+
- [x] **RubyLLM universal adapter** -- Replaced OpenAI, Anthropic, and Ollama adapters with a single RubyLLM wrapper. Supports 800+ models across OpenAI, Anthropic, Gemini, DeepSeek, OpenRouter, Ollama, and any OpenAI-compatible endpoint. Auto-configures from env vars.
|
|
20
|
+
- [x] **Rate limiting (basic)** -- RubyLLM provides built-in `max_retries` and `retry_interval` for 429s. Per-minute quotas are not yet exposed.
|
|
21
|
+
- [x] **More built-in tools** -- File read/write tools. Google search and Wikipedia search remain TODO.
|
|
22
|
+
- [x] **Tool.from_mcp** -- Load a single tool from an MCP server by name (vs loading all tools from a server).
|
|
23
|
+
|
|
24
|
+
## Phase 7 -- Observability & debugging (medium impact, medium effort)
|
|
25
|
+
|
|
26
|
+
Understanding what agents actually do.
|
|
27
|
+
|
|
28
|
+
- [ ] **Structured logging** -- JSON-structured logs per step with run_id, step_number, thought, action, observation, timing, tokens. Emit to any Ruby logger.
|
|
29
|
+
- [x] **`memory.replay`** -- Pretty-print a completed run to the terminal (like smolagents' `agent.replay()`).
|
|
30
|
+
- [x] **Run export** -- Serialize a run (memory + steps + metadata) to JSON for later analysis or replay.
|
|
31
|
+
- [x] **Callbacks for observability** -- Richer callback interface: `on_step_start`, `on_step_end`, `on_tool_call`, `on_error`. Current `step_callbacks` only fires after completion.
|
|
32
|
+
|
|
33
|
+
## Phase 8 -- Sandboxing & security (medium impact, high effort)
|
|
34
|
+
|
|
35
|
+
For production use where agent code can't be trusted.
|
|
36
|
+
|
|
37
|
+
- [ ] **Docker executor** -- Run agent code in a Docker container instead of a fork. Filesystem isolation, network control, resource limits.
|
|
38
|
+
- [ ] **Import/require allowlist** -- Restrict which Ruby gems/stdlib modules agent code can load in the sandbox (like smolagents' `additional_authorized_imports`).
|
|
39
|
+
- [ ] **Operation count limit** -- Cap iterations/operations in the sandbox to prevent infinite loops eating CPU (smolagents caps at 1M operations).
|
|
40
|
+
|
|
41
|
+
## Phase 9 -- Advanced features (lower priority, nice to have)
|
|
42
|
+
|
|
43
|
+
- [ ] **Agent serialization** -- `agent.save(dir)` / `Agent.load(dir)` for persisting agent configuration (tools, prompts, model, settings).
|
|
44
|
+
- [ ] **Media types in tools** -- Support image/audio inputs and outputs for multimodal agents.
|
|
45
|
+
- [ ] **Async/parallel tool calls** -- ToolCallingAgent processes multiple tool calls concurrently (like smolagents' `max_tool_threads`).
|
|
46
|
+
- [ ] **Web UI** -- Lightweight web interface for interactive agent sessions (alternative to CLI). Could be a simple Rack app or use Hotwire.
|
|
47
|
+
- [ ] **Persistent memory** -- Long-term memory across runs (conversation history, learned facts). Could be file-based or backed by SQLite.
|
|
48
|
+
|
|
49
|
+
## Not planned
|
|
50
|
+
|
|
51
|
+
These exist in smolagents but don't fit rubyagents' design goals:
|
|
52
|
+
|
|
53
|
+
- **Hub sharing** -- No equivalent to HuggingFace Hub in Ruby. Gems are the distribution mechanism.
|
|
54
|
+
- **LangChain/Gradio interop** -- Python-specific ecosystems.
|
|
55
|
+
- **WASM executor** -- Ruby WASM support is too immature.
|
|
56
|
+
- **MLX/vLLM adapters** -- Python-only inference runtimes. RubyLLM covers local models via Ollama.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../lib/rubyagents"
|
|
5
|
+
|
|
6
|
+
class StockPrice < Rubyagents::Tool
|
|
7
|
+
tool_name "stock_price"
|
|
8
|
+
description "Gets the current stock price for a ticker symbol"
|
|
9
|
+
input :ticker, type: :string, description: "Stock ticker symbol (e.g. AAPL)"
|
|
10
|
+
output_type :number
|
|
11
|
+
|
|
12
|
+
def call(ticker:)
|
|
13
|
+
# Simulated stock prices for demo
|
|
14
|
+
prices = { "AAPL" => 182.52, "GOOGL" => 141.80, "TSLA" => 248.42, "RIVN" => 14.73 }
|
|
15
|
+
prices.fetch(ticker.upcase, "Unknown ticker: #{ticker}")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
agent = Rubyagents::CodeAgent.new(
|
|
20
|
+
model: "anthropic/claude-sonnet-4-20250514",
|
|
21
|
+
tools: [StockPrice]
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
agent.run("What's the difference in stock price between AAPL and TSLA?")
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../lib/rubyagents"
|
|
5
|
+
require_relative "../lib/rubyagents/tools/web_search"
|
|
6
|
+
|
|
7
|
+
agent = Rubyagents::CodeAgent.new(
|
|
8
|
+
model: "anthropic/claude-sonnet-4-20250514",
|
|
9
|
+
tools: [Rubyagents::WebSearch]
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
agent.run("What year was Ruby created and who created it?")
|