rubyrana 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 +9 -0
- data/LICENSE +190 -0
- data/NOTICE +4 -0
- data/README.md +179 -0
- data/REPORT.md +156 -0
- data/docs/CHECKLIST.md +32 -0
- data/docs/RELEASE.md +16 -0
- data/docs/USAGE.md +54 -0
- data/examples/mcp.rb +22 -0
- data/examples/quick_start.rb +23 -0
- data/examples/streaming.rb +19 -0
- data/examples/tools_loader.rb +18 -0
- data/lib/rubyrana/agent.rb +153 -0
- data/lib/rubyrana/config.rb +15 -0
- data/lib/rubyrana/errors.rb +11 -0
- data/lib/rubyrana/mcp/client.rb +124 -0
- data/lib/rubyrana/multi_agent.rb +21 -0
- data/lib/rubyrana/persistence/base.rb +15 -0
- data/lib/rubyrana/persistence/file_store.rb +38 -0
- data/lib/rubyrana/persistence/redis_store.rb +36 -0
- data/lib/rubyrana/providers/anthropic.rb +176 -0
- data/lib/rubyrana/providers/base.rb +25 -0
- data/lib/rubyrana/providers/bedrock.rb +11 -0
- data/lib/rubyrana/providers/openai.rb +11 -0
- data/lib/rubyrana/routing/keyword_router.rb +20 -0
- data/lib/rubyrana/safety/filter.rb +28 -0
- data/lib/rubyrana/tool.rb +30 -0
- data/lib/rubyrana/tool_registry.rb +26 -0
- data/lib/rubyrana/tooling.rb +33 -0
- data/lib/rubyrana/tools/code_interpreter.rb +68 -0
- data/lib/rubyrana/tools/loader.rb +20 -0
- data/lib/rubyrana/tools/mcp_web_search.rb +36 -0
- data/lib/rubyrana/tools/web_search.rb +79 -0
- data/lib/rubyrana/tools.rb +22 -0
- data/lib/rubyrana/version.rb +5 -0
- data/lib/rubyrana.rb +33 -0
- metadata +149 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a23b823b6f21c5d8093c355b4c0a4fdcb8e5268b075163708d4e3d0042e556b0
|
|
4
|
+
data.tar.gz: f3b7ecd4ff79260a1d24fde0c8028dd496a89973212c356949fee339b9e612f4
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a540d2da6e926c6b9abd75761a978000785fb4b0951a95f6df641b222e34df7e62fb202013eb331f975422c7d55bea5ce7266ac667662119c3f5ce2deb1aa85d
|
|
7
|
+
data.tar.gz: 986c64f68ea2fab6cee3851649b28aa8c8fb14356bad86aa84962e2e01748e656671773c17f5b1664b22a6827009f4828c160737f14983343ef5b5448befc691
|
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
Copyright 2026 Rubyrana Contributors
|
|
179
|
+
|
|
180
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
181
|
+
you may not use this file except in compliance with the License.
|
|
182
|
+
You may obtain a copy of the License at
|
|
183
|
+
|
|
184
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
185
|
+
|
|
186
|
+
Unless required by applicable law or agreed to in writing, software
|
|
187
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
188
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
189
|
+
See the License for the specific language governing permissions and
|
|
190
|
+
limitations under the License.
|
data/NOTICE
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<div>
|
|
3
|
+
<img src="https://placehold.co/80x80" alt="Rubyrana" width="80" height="80">
|
|
4
|
+
</div>
|
|
5
|
+
|
|
6
|
+
<h1>Rubyrana</h1>
|
|
7
|
+
<h2>Build production-ready AI agents in Ruby with just a few lines of code.</h2>
|
|
8
|
+
|
|
9
|
+
<div align="center">
|
|
10
|
+
<img alt="Gem version" src="https://img.shields.io/gem/v/rubyrana" />
|
|
11
|
+
<img alt="Ruby" src="https://img.shields.io/badge/ruby-%3E%3D%203.1-brightgreen" />
|
|
12
|
+
<img alt="License" src="https://img.shields.io/badge/license-Apache%202.0-blue" />
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<p>
|
|
16
|
+
<a href="#quick-start">Quick Start</a>
|
|
17
|
+
◆ <a href="#features">Features</a>
|
|
18
|
+
◆ <a href="#tools">Tools</a>
|
|
19
|
+
◆ <a href="#model-providers">Model Providers</a>
|
|
20
|
+
◆ <a href="#mcp">MCP</a>
|
|
21
|
+
</p>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
Rubyrana is a lightweight, model-driven Ruby SDK for building AI agents. Start with a simple conversational assistant, then scale to multi-tool workflows and production deployments.
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Install Rubyrana
|
|
30
|
+
bundle add rubyrana
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
require "rubyrana"
|
|
35
|
+
|
|
36
|
+
Rubyrana.configure do |config|
|
|
37
|
+
config.default_provider = Rubyrana::Providers::Anthropic.new(
|
|
38
|
+
api_key: ENV.fetch("ANTHROPIC_API_KEY"),
|
|
39
|
+
model: ENV.fetch("ANTHROPIC_MODEL", "claude-3-haiku-20240307")
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
agent = Rubyrana::Agent.new
|
|
44
|
+
puts agent.call("What is the square root of 1764?")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
> **Note:** Configure your Anthropic credentials before running.
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
|
|
51
|
+
- **Simple agent loop** with a clean Ruby API
|
|
52
|
+
- **Anthropic-first** provider integration with tool calling and streaming
|
|
53
|
+
- **Tooling-first design** for structured, safe function calls
|
|
54
|
+
- **Streaming-ready** architecture (planned)
|
|
55
|
+
- **MCP support** to connect thousands of tools (planned)
|
|
56
|
+
|
|
57
|
+
## Tools
|
|
58
|
+
|
|
59
|
+
Create tools with a Ruby DSL:
|
|
60
|
+
|
|
61
|
+
```ruby
|
|
62
|
+
require "rubyrana"
|
|
63
|
+
|
|
64
|
+
word_count = Rubyrana::Tool.new("word_count") do |text:|
|
|
65
|
+
text.split.size
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
agent = Rubyrana::Agent.new(tools: [word_count])
|
|
69
|
+
puts agent.call("How many words are in this sentence?")
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Built-in Tools
|
|
73
|
+
|
|
74
|
+
Rubyrana ships with optional built-in tools:
|
|
75
|
+
|
|
76
|
+
```ruby
|
|
77
|
+
require "rubyrana"
|
|
78
|
+
|
|
79
|
+
tools = [
|
|
80
|
+
Rubyrana::Tools.code_interpreter,
|
|
81
|
+
Rubyrana::Tools.web_search
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
agent = Rubyrana::Agent.new(tools: tools)
|
|
85
|
+
puts agent.call("Search Ruby 3.3 release highlights and summarize.")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
> **Note:** `web_search` requires users to bring their own `WEB_SEARCH_API_KEY` (Serper). `code_interpreter` runs code in a local process.
|
|
89
|
+
|
|
90
|
+
### Tool Decorators + Loader
|
|
91
|
+
|
|
92
|
+
Define tools with a simple Ruby decorator and load them from a directory:
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
require "rubyrana"
|
|
96
|
+
|
|
97
|
+
Rubyrana.tool("hello", description: "Greet a user", schema: {
|
|
98
|
+
type: "object",
|
|
99
|
+
properties: { name: { type: "string" } },
|
|
100
|
+
required: ["name"]
|
|
101
|
+
}) do |name:|
|
|
102
|
+
"Hello, #{name}!"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
agent = Rubyrana::Agent.new(load_tools_from: "./tools")
|
|
106
|
+
puts agent.call("Use the hello tool to greet Ajay")
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Web Search via MCP (Preferred)
|
|
110
|
+
|
|
111
|
+
If you want a Strands-style approach, delegate web search to an MCP server:
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
require "rubyrana"
|
|
115
|
+
|
|
116
|
+
web_search = Rubyrana::Tools.web_search_mcp(
|
|
117
|
+
command: "uvx",
|
|
118
|
+
args: ["awslabs.aws-documentation-mcp-server@latest"],
|
|
119
|
+
tool_name: "search_documentation"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
agent = Rubyrana::Agent.new(tools: [web_search])
|
|
123
|
+
puts agent.call("Search Bedrock docs and summarize the key points.")
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Hot-reload tools from a folder:
|
|
127
|
+
|
|
128
|
+
```ruby
|
|
129
|
+
agent = Rubyrana::Agent.new(load_tools_from: "./tools")
|
|
130
|
+
agent.call("Use any tools you find in the tools directory")
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## MCP (Experimental)
|
|
134
|
+
|
|
135
|
+
Connect Model Context Protocol servers:
|
|
136
|
+
|
|
137
|
+
```ruby
|
|
138
|
+
require "rubyrana"
|
|
139
|
+
|
|
140
|
+
mcp = Rubyrana::MCP::Client.new(command: "uvx", args: ["awslabs.aws-documentation-mcp-server@latest"])
|
|
141
|
+
|
|
142
|
+
mcp.with_session do |tools|
|
|
143
|
+
agent = Rubyrana::Agent.new(tools: tools)
|
|
144
|
+
puts agent.call("Tell me about Amazon Bedrock and how to use it with Ruby")
|
|
145
|
+
end
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Model Provider
|
|
149
|
+
|
|
150
|
+
Rubyrana is Anthropic-native today.
|
|
151
|
+
|
|
152
|
+
Example:
|
|
153
|
+
|
|
154
|
+
```ruby
|
|
155
|
+
require "rubyrana"
|
|
156
|
+
|
|
157
|
+
model = Rubyrana::Providers::Anthropic.new(
|
|
158
|
+
api_key: ENV.fetch("ANTHROPIC_API_KEY"),
|
|
159
|
+
model: ENV.fetch("ANTHROPIC_MODEL", "claude-3-haiku-20240307")
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
agent = Rubyrana::Agent.new(model: model)
|
|
163
|
+
puts agent.call("Explain agentic workflows in simple terms")
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Documentation
|
|
167
|
+
|
|
168
|
+
- Getting Started
|
|
169
|
+
- Core Concepts
|
|
170
|
+
- Tools & MCP
|
|
171
|
+
- Production Deployment
|
|
172
|
+
|
|
173
|
+
## Contributing
|
|
174
|
+
|
|
175
|
+
Contributions are welcome. Please open issues and PRs with clear reproduction steps and context.
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
Apache 2.0
|
data/REPORT.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Rubyrana Feasibility & Implementation Report
|
|
2
|
+
|
|
3
|
+
This report evaluates whether the README goal is buildable and outlines what is required to deliver it as a Ruby gem. The README is treated as the target product spec.
|
|
4
|
+
|
|
5
|
+
## Executive Summary
|
|
6
|
+
|
|
7
|
+
Yes, this is buildable. Rubyrana can be implemented as a Ruby gem with a small, composable core plus optional provider and MCP integrations. The main complexity is in provider adapters and streaming/MCP support. A staged build plan can deliver a usable v0.1 quickly, then layer advanced features.
|
|
8
|
+
|
|
9
|
+
## Target Capabilities (from README)
|
|
10
|
+
|
|
11
|
+
1. **Simple agent loop** with clean Ruby API
|
|
12
|
+
2. **Anthropic-only** model support
|
|
13
|
+
3. **Tools system** with a Ruby DSL and directory hot-reload
|
|
14
|
+
4. **Streaming** support
|
|
15
|
+
5. **MCP support** via external servers
|
|
16
|
+
|
|
17
|
+
## What We Need to Build
|
|
18
|
+
|
|
19
|
+
### 1) Core Gem Structure
|
|
20
|
+
**Deliverables**
|
|
21
|
+
- Gem skeleton (gemspec, lib/ directory, versioning)
|
|
22
|
+
- `Rubyrana::Agent` API
|
|
23
|
+
- `Rubyrana::Tool` and tool registry
|
|
24
|
+
- Logging + configuration
|
|
25
|
+
|
|
26
|
+
**Suggested File Structure**
|
|
27
|
+
```
|
|
28
|
+
lib/
|
|
29
|
+
rubyrana.rb
|
|
30
|
+
rubyrana/version.rb
|
|
31
|
+
rubyrana/agent.rb
|
|
32
|
+
rubyrana/tool.rb
|
|
33
|
+
rubyrana/tool_registry.rb
|
|
34
|
+
rubyrana/config.rb
|
|
35
|
+
rubyrana/errors.rb
|
|
36
|
+
rubyrana/serialization.rb
|
|
37
|
+
rubyrana/streaming/
|
|
38
|
+
rubyrana/providers/
|
|
39
|
+
rubyrana/mcp/
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 2) Agent Loop
|
|
43
|
+
**Core responsibilities**
|
|
44
|
+
- Accept a prompt and optional conversation history
|
|
45
|
+
- Call selected model provider
|
|
46
|
+
- Parse tool calls, invoke tools, and return a final response
|
|
47
|
+
- Provide a streaming mode
|
|
48
|
+
|
|
49
|
+
**What to implement**
|
|
50
|
+
- `Rubyrana::Agent#call(prompt, **opts)`
|
|
51
|
+
- `Rubyrana::Agent#stream(prompt, **opts)`
|
|
52
|
+
- Minimal memory: request + response history
|
|
53
|
+
|
|
54
|
+
### 3) Tooling System
|
|
55
|
+
**Requirements**
|
|
56
|
+
- A Ruby DSL to define tools
|
|
57
|
+
- Type/shape for tool inputs
|
|
58
|
+
- Tool invocation engine
|
|
59
|
+
|
|
60
|
+
**Implementation notes**
|
|
61
|
+
- Use `Rubyrana::Tool.new(name, description: ..., schema: ...) { |**args| ... }`
|
|
62
|
+
- For schema validation: use JSON Schema or a simple Ruby contract system
|
|
63
|
+
- Tool registry in `Rubyrana::ToolRegistry`
|
|
64
|
+
|
|
65
|
+
**Hot Reloading**
|
|
66
|
+
- Watch a `./tools` directory and load tools
|
|
67
|
+
- Use `listen` gem for filesystem events
|
|
68
|
+
|
|
69
|
+
### 4) Model Provider
|
|
70
|
+
**Implementation**
|
|
71
|
+
- Provider base class: `Rubyrana::Provider::Base`
|
|
72
|
+
- `#complete(prompt, tools:, stream:)` interface
|
|
73
|
+
|
|
74
|
+
**Required adapter**
|
|
75
|
+
- Anthropic (HTTP API)
|
|
76
|
+
|
|
77
|
+
**Dependencies**
|
|
78
|
+
- `faraday` or `httpx` for HTTP
|
|
79
|
+
|
|
80
|
+
### 5) MCP Integration
|
|
81
|
+
**Goal**
|
|
82
|
+
- Connect to MCP servers via stdio or HTTP
|
|
83
|
+
|
|
84
|
+
**Implementation**
|
|
85
|
+
- Add `Rubyrana::MCP::Client` that manages MCP lifecycle
|
|
86
|
+
- Use `mcp` protocol JSON-RPC style
|
|
87
|
+
- Provide `list_tools` and convert MCP tool defs into `Rubyrana::Tool`
|
|
88
|
+
|
|
89
|
+
**Dependencies**
|
|
90
|
+
- If using stdio: spawn a process and read/write JSON
|
|
91
|
+
- Ruby JSON-RPC support (custom or existing gem)
|
|
92
|
+
|
|
93
|
+
### 6) Streaming
|
|
94
|
+
**Goal**
|
|
95
|
+
- Return tokens incrementally
|
|
96
|
+
|
|
97
|
+
**Implementation**
|
|
98
|
+
- Provider adapters must support streaming
|
|
99
|
+
- Agent exposes `#stream` returning an enumerator or block callback
|
|
100
|
+
|
|
101
|
+
### 7) Error Handling & Telemetry
|
|
102
|
+
**Deliverables**
|
|
103
|
+
- Standard error types
|
|
104
|
+
- Retriable failures
|
|
105
|
+
- Optional logging and tracing hooks
|
|
106
|
+
|
|
107
|
+
### 8) Tests & CI
|
|
108
|
+
**Required**
|
|
109
|
+
- Unit tests for agent, tools, providers
|
|
110
|
+
- Integration tests with mock HTTP
|
|
111
|
+
- CI workflow (GitHub Actions)
|
|
112
|
+
|
|
113
|
+
## Feasibility Notes
|
|
114
|
+
|
|
115
|
+
- **Core agent + tools**: straightforward; Ruby is well-suited for this.
|
|
116
|
+
- **Provider adapter**: ensure request/response formats and tool use are correct.
|
|
117
|
+
- **MCP**: feasible but requires careful process IO handling and tool conversion.
|
|
118
|
+
- **Streaming**: depends on provider support; implement per-provider streaming.
|
|
119
|
+
|
|
120
|
+
## Proposed Delivery Plan
|
|
121
|
+
|
|
122
|
+
### Phase 0 — Foundations (1–2 weeks)
|
|
123
|
+
- Gem skeleton
|
|
124
|
+
- Agent loop (non-streaming)
|
|
125
|
+
- Tool system
|
|
126
|
+
- Anthropic adapter
|
|
127
|
+
- Minimal README
|
|
128
|
+
|
|
129
|
+
### Phase 1 — Streaming & Hardening (2–3 weeks)
|
|
130
|
+
- Streaming interface
|
|
131
|
+
- Robust errors
|
|
132
|
+
|
|
133
|
+
### Phase 2 — MCP Integration (2–3 weeks)
|
|
134
|
+
- MCP client via stdio
|
|
135
|
+
- Tool conversion + lifecycle
|
|
136
|
+
- Examples
|
|
137
|
+
|
|
138
|
+
### Phase 3 — Production Readiness (ongoing)
|
|
139
|
+
- CI, tests, docs site
|
|
140
|
+
- Performance and retries
|
|
141
|
+
|
|
142
|
+
## Gaps to Resolve Before Implementation
|
|
143
|
+
|
|
144
|
+
1. **Exact API design** for tools and agent history
|
|
145
|
+
2. **Anthropic model selection**
|
|
146
|
+
3. **Streaming interface**: enumerator vs callback
|
|
147
|
+
4. **MCP client spec**: confirm protocol requirements
|
|
148
|
+
5. **Gem naming** and branding assets
|
|
149
|
+
|
|
150
|
+
## Recommendation
|
|
151
|
+
|
|
152
|
+
Proceed with an Anthropic-native SDK that mirrors the README and emphasizes tool use, streaming, and MCP.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
If you want, I can now scaffold the gem, implement the Phase 0 core, and evolve the README to match the actual API as we build.
|
data/docs/CHECKLIST.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Rubyrana Product Checklist
|
|
2
|
+
|
|
3
|
+
## Core Capabilities
|
|
4
|
+
- [x] Anthropic provider integration
|
|
5
|
+
- [x] Tool calling loop
|
|
6
|
+
- [x] Streaming support
|
|
7
|
+
- [x] Conversation memory
|
|
8
|
+
- [x] Safety filters
|
|
9
|
+
- [x] Persistence (file + Redis)
|
|
10
|
+
- [x] Multi-agent routing
|
|
11
|
+
|
|
12
|
+
## Tooling Framework
|
|
13
|
+
- [x] Tool registry
|
|
14
|
+
- [x] Tool decorator (`Rubyrana.tool`)
|
|
15
|
+
- [x] Tool loader (directory)
|
|
16
|
+
- [x] MCP client integration
|
|
17
|
+
- [x] MCP-based web search tool
|
|
18
|
+
|
|
19
|
+
## Built-in Tools
|
|
20
|
+
- [x] Code interpreter
|
|
21
|
+
- [x] Web search (Serper)
|
|
22
|
+
|
|
23
|
+
## Developer Experience
|
|
24
|
+
- [x] Examples
|
|
25
|
+
- [x] Usage docs
|
|
26
|
+
- [x] Release checklist
|
|
27
|
+
- [x] Tests + CI
|
|
28
|
+
|
|
29
|
+
## Packaging
|
|
30
|
+
- [x] Gem metadata
|
|
31
|
+
- [x] License + NOTICE
|
|
32
|
+
- [x] Changelog
|
data/docs/RELEASE.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Release Checklist
|
|
2
|
+
|
|
3
|
+
## Pre-release
|
|
4
|
+
- Ensure tests pass on Ruby 3.1, 3.2, 3.3
|
|
5
|
+
- Update CHANGELOG.md with release notes
|
|
6
|
+
- Verify README and docs reflect the current API
|
|
7
|
+
- Confirm gemspec metadata (homepage, authors, email)
|
|
8
|
+
|
|
9
|
+
## Release
|
|
10
|
+
- Tag release in git (e.g., v0.1.0)
|
|
11
|
+
- Build gem: `gem build rubyrana.gemspec`
|
|
12
|
+
- Push gem: `gem push rubyrana-0.1.0.gem`
|
|
13
|
+
|
|
14
|
+
## Post-release
|
|
15
|
+
- Update any version references
|
|
16
|
+
- Announce the release
|
data/docs/USAGE.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Rubyrana Usage
|
|
2
|
+
|
|
3
|
+
## Quick Start
|
|
4
|
+
|
|
5
|
+
1) Install the gem:
|
|
6
|
+
|
|
7
|
+
- Add to your Gemfile:
|
|
8
|
+
- gem "rubyrana"
|
|
9
|
+
|
|
10
|
+
2) Configure a provider:
|
|
11
|
+
|
|
12
|
+
- Set an environment variable (e.g., ANTHROPIC_API_KEY)
|
|
13
|
+
- Configure Rubyrana:
|
|
14
|
+
- Rubyrana.configure { |c| c.default_provider = Rubyrana::Providers::Anthropic.new(...) }
|
|
15
|
+
|
|
16
|
+
3) Create an agent and call it:
|
|
17
|
+
|
|
18
|
+
- agent = Rubyrana::Agent.new
|
|
19
|
+
- agent.call("Hello")
|
|
20
|
+
|
|
21
|
+
## Tools
|
|
22
|
+
|
|
23
|
+
Define tools with a Ruby block and pass them to the agent:
|
|
24
|
+
|
|
25
|
+
- word_count = Rubyrana::Tool.new("word_count") { |text:| text.split.size }
|
|
26
|
+
- agent = Rubyrana::Agent.new(tools: [word_count])
|
|
27
|
+
|
|
28
|
+
### Built-in Tools
|
|
29
|
+
|
|
30
|
+
- code_interpreter: execute Ruby code in a temporary process
|
|
31
|
+
- web_search: Serper-backed web search (users must supply WEB_SEARCH_API_KEY)
|
|
32
|
+
- web_search_mcp: MCP-backed web search (users supply MCP server command/args)
|
|
33
|
+
|
|
34
|
+
Example:
|
|
35
|
+
|
|
36
|
+
- tools = [Rubyrana::Tools.code_interpreter, Rubyrana::Tools.web_search]
|
|
37
|
+
- agent = Rubyrana::Agent.new(tools: tools)
|
|
38
|
+
|
|
39
|
+
## Tool Decorators + Loader
|
|
40
|
+
|
|
41
|
+
Define tools anywhere using `Rubyrana.tool`:
|
|
42
|
+
|
|
43
|
+
- Rubyrana.tool("hello") { |name:| "Hello, #{name}!" }
|
|
44
|
+
|
|
45
|
+
Load tools from a directory:
|
|
46
|
+
|
|
47
|
+
- agent = Rubyrana::Agent.new(load_tools_from: "./tools")
|
|
48
|
+
|
|
49
|
+
## MCP (Experimental)
|
|
50
|
+
|
|
51
|
+
Use the MCP client to load tools:
|
|
52
|
+
|
|
53
|
+
- mcp = Rubyrana::MCP::Client.new(command: "uvx", args: ["awslabs.aws-documentation-mcp-server@latest"])
|
|
54
|
+
- mcp.with_session { |tools| Rubyrana::Agent.new(tools: tools).call("...") }
|
data/examples/mcp.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dotenv/load"
|
|
4
|
+
require "rubyrana"
|
|
5
|
+
|
|
6
|
+
mcp = Rubyrana::MCP::Client.new(
|
|
7
|
+
command: "uvx",
|
|
8
|
+
args: ["awslabs.aws-documentation-mcp-server@latest"]
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
mcp.with_session do |tools|
|
|
12
|
+
Rubyrana.configure do |config|
|
|
13
|
+
config.debug = true
|
|
14
|
+
config.default_provider = Rubyrana::Providers::Anthropic.new(
|
|
15
|
+
api_key: ENV.fetch("ANTHROPIC_API_KEY"),
|
|
16
|
+
model: ENV.fetch("ANTHROPIC_MODEL", "claude-3-haiku-20240307")
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
agent = Rubyrana::Agent.new(tools: tools)
|
|
21
|
+
puts agent.call("What is Amazon Bedrock?")
|
|
22
|
+
end
|