ai-agents 0.1.0 → 0.1.2
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/.rubocop.yml +3 -0
- data/CLAUDE.md +146 -137
- data/README.md +42 -20
- data/examples/isp-support/agents_factory.rb +66 -10
- data/examples/isp-support/interactive.rb +28 -6
- data/examples/isp-support/tools/create_checkout_tool.rb +1 -1
- data/examples/isp-support/tools/create_lead_tool.rb +19 -5
- data/examples/isp-support/tools/crm_lookup_tool.rb +14 -2
- data/examples/isp-support/tools/search_docs_tool.rb +1 -1
- data/lib/agents/agent.rb +18 -6
- data/lib/agents/agent_runner.rb +105 -0
- data/lib/agents/chat.rb +143 -0
- data/lib/agents/handoff.rb +4 -12
- data/lib/agents/runner.rb +74 -38
- data/lib/agents/tool.rb +0 -81
- data/lib/agents/tool_context.rb +36 -0
- data/lib/agents/version.rb +1 -1
- data/lib/agents.rb +14 -0
- metadata +4 -2
data/lib/agents/tool.rb
CHANGED
@@ -36,52 +36,8 @@
|
|
36
36
|
# end
|
37
37
|
# end
|
38
38
|
#
|
39
|
-
# @example Using the functional tool definition
|
40
|
-
# # Define a calculator tool
|
41
|
-
# calculator = Agents::Tool.tool(
|
42
|
-
# "calculate",
|
43
|
-
# description: "Perform mathematical calculations"
|
44
|
-
# ) do |tool_context, expression:|
|
45
|
-
# begin
|
46
|
-
# result = eval(expression)
|
47
|
-
# result.to_s
|
48
|
-
# rescue => e
|
49
|
-
# "Calculation error: #{e.message}"
|
50
|
-
# end
|
51
|
-
# end
|
52
|
-
#
|
53
|
-
# # Use the tool in an agent
|
54
|
-
# agent = Agents::Agent.new(
|
55
|
-
# name: "Math Assistant",
|
56
|
-
# instructions: "You are a helpful math assistant",
|
57
|
-
# tools: [calculator]
|
58
|
-
# )
|
59
|
-
#
|
60
|
-
# # During execution, the runner would call it like this:
|
61
|
-
# run_context = Agents::RunContext.new({ user_id: 123 })
|
62
|
-
# tool_context = Agents::ToolContext.new(run_context: run_context)
|
63
|
-
#
|
64
|
-
# result = calculator.execute(tool_context, expression: "2 + 2 * 3")
|
65
|
-
# # => "8"
|
66
39
|
module Agents
|
67
40
|
class Tool < RubyLLM::Tool
|
68
|
-
class << self
|
69
|
-
def param(name, type = String, desc = nil, required: true, **options)
|
70
|
-
# Convert Ruby types to JSON schema types
|
71
|
-
json_type = case type
|
72
|
-
when String, "string" then "string"
|
73
|
-
when Integer, "integer" then "integer"
|
74
|
-
when Float, "number" then "number"
|
75
|
-
when TrueClass, FalseClass, "boolean" then "boolean"
|
76
|
-
when Array, "array" then "array"
|
77
|
-
when Hash, "object" then "object"
|
78
|
-
else "string"
|
79
|
-
end
|
80
|
-
|
81
|
-
# Call parent param method
|
82
|
-
super(name, type: json_type, desc: desc, required: required, **options)
|
83
|
-
end
|
84
|
-
end
|
85
41
|
# Execute the tool with context injection.
|
86
42
|
# This method is called by the runner and handles the thread-safe
|
87
43
|
# execution pattern by passing all state through parameters.
|
@@ -112,42 +68,5 @@ module Agents
|
|
112
68
|
def perform(tool_context, **params)
|
113
69
|
raise NotImplementedError, "Tools must implement #perform(tool_context, **params)"
|
114
70
|
end
|
115
|
-
|
116
|
-
# Create a tool instance using a functional style definition.
|
117
|
-
# This is an alternative to creating a full class for simple tools.
|
118
|
-
# The block becomes the tool's perform method.
|
119
|
-
#
|
120
|
-
# @param name [String] The tool's name (used in function calling)
|
121
|
-
# @param description [String] Brief description of what the tool does
|
122
|
-
# @yield [tool_context, **params] The block that implements the tool's logic
|
123
|
-
# @return [Agents::Tool] A new tool instance
|
124
|
-
# @example Creating a simple tool functionally
|
125
|
-
# math_tool = Agents::Tool.tool(
|
126
|
-
# "add_numbers",
|
127
|
-
# description: "Add two numbers together"
|
128
|
-
# ) do |tool_context, a:, b:|
|
129
|
-
# (a + b).to_s
|
130
|
-
# end
|
131
|
-
#
|
132
|
-
# @example Tool accessing context with error handling
|
133
|
-
# greeting_tool = Agents::Tool.tool("greet", description: "Greet a user") do |tool_context, name:|
|
134
|
-
# language = tool_context.context[:language] || "en"
|
135
|
-
# case language
|
136
|
-
# when "es" then "¡Hola, #{name}!"
|
137
|
-
# when "fr" then "Bonjour, #{name}!"
|
138
|
-
# else "Hello, #{name}!"
|
139
|
-
# end
|
140
|
-
# rescue => e
|
141
|
-
# "Sorry, I couldn't greet you: #{e.message}"
|
142
|
-
# end
|
143
|
-
def self.tool(name, description: "", &block)
|
144
|
-
# Create anonymous class that extends Tool
|
145
|
-
Class.new(Tool) do
|
146
|
-
self.name = name
|
147
|
-
self.description = description
|
148
|
-
|
149
|
-
define_method :perform, &block
|
150
|
-
end.new
|
151
|
-
end
|
152
71
|
end
|
153
72
|
end
|
data/lib/agents/tool_context.rb
CHANGED
@@ -94,5 +94,41 @@ module Agents
|
|
94
94
|
def usage
|
95
95
|
@run_context.usage
|
96
96
|
end
|
97
|
+
|
98
|
+
# Convenient access to the shared state hash within the context.
|
99
|
+
# This provides tools with a dedicated space to store and retrieve
|
100
|
+
# state that persists across agent interactions within a conversation.
|
101
|
+
#
|
102
|
+
# State is automatically initialized as an empty hash if it doesn't exist.
|
103
|
+
# All state modifications are automatically included in context serialization,
|
104
|
+
# making it persist across process boundaries (e.g., Rails with ActiveRecord).
|
105
|
+
#
|
106
|
+
# @return [Hash] The shared state hash
|
107
|
+
# @example Tool storing customer information in state
|
108
|
+
# def perform(tool_context, customer_id:)
|
109
|
+
# customer = Customer.find(customer_id)
|
110
|
+
#
|
111
|
+
# # Store in shared state for other tools/agents to access
|
112
|
+
# tool_context.state[:customer_id] = customer_id
|
113
|
+
# tool_context.state[:customer_name] = customer.name
|
114
|
+
# tool_context.state[:plan_type] = customer.plan
|
115
|
+
#
|
116
|
+
# "Found customer #{customer.name}"
|
117
|
+
# end
|
118
|
+
#
|
119
|
+
# @example Tool reading from shared state
|
120
|
+
# def perform(tool_context)
|
121
|
+
# customer_id = tool_context.state[:customer_id]
|
122
|
+
# plan_type = tool_context.state[:plan_type]
|
123
|
+
#
|
124
|
+
# if customer_id && plan_type
|
125
|
+
# "Current plan: #{plan_type} for customer #{customer_id}"
|
126
|
+
# else
|
127
|
+
# "No customer information available"
|
128
|
+
# end
|
129
|
+
# end
|
130
|
+
def state
|
131
|
+
context[:state] ||= {}
|
132
|
+
end
|
97
133
|
end
|
98
134
|
end
|
data/lib/agents/version.rb
CHANGED
data/lib/agents.rb
CHANGED
@@ -11,6 +11,18 @@ require_relative "agents/version"
|
|
11
11
|
module Agents
|
12
12
|
class Error < StandardError; end
|
13
13
|
|
14
|
+
# OpenAI's recommended system prompt prefix for multi-agent workflows
|
15
|
+
# This helps agents understand they're part of a coordinated system
|
16
|
+
RECOMMENDED_HANDOFF_PROMPT_PREFIX =
|
17
|
+
"# System context\n" \
|
18
|
+
"You are part of a multi-agent system called the Ruby Agents SDK, designed to make agent " \
|
19
|
+
"coordination and execution easy. Agents uses two primary abstraction: **Agents** and " \
|
20
|
+
"**Handoffs**. An agent encompasses instructions and tools and can hand off a " \
|
21
|
+
"conversation to another agent when appropriate. " \
|
22
|
+
"Handoffs are achieved by calling a handoff function, generally named " \
|
23
|
+
"`handoff_to_<agent_name>`. Transfers between agents are handled seamlessly in the background; " \
|
24
|
+
"do not mention or draw attention to these transfers in your conversation with the user.\n"
|
25
|
+
|
14
26
|
class << self
|
15
27
|
# Logger for debugging (can be set by users)
|
16
28
|
attr_accessor :logger
|
@@ -66,5 +78,7 @@ require_relative "agents/handoff"
|
|
66
78
|
require_relative "agents/agent"
|
67
79
|
|
68
80
|
# Execution components
|
81
|
+
require_relative "agents/chat"
|
69
82
|
require_relative "agents/tool_wrapper"
|
83
|
+
require_relative "agents/agent_runner"
|
70
84
|
require_relative "agents/runner"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ai-agents
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shivam Mishra
|
@@ -51,6 +51,8 @@ files:
|
|
51
51
|
- examples/isp-support/tools/search_docs_tool.rb
|
52
52
|
- lib/agents.rb
|
53
53
|
- lib/agents/agent.rb
|
54
|
+
- lib/agents/agent_runner.rb
|
55
|
+
- lib/agents/chat.rb
|
54
56
|
- lib/agents/handoff.rb
|
55
57
|
- lib/agents/result.rb
|
56
58
|
- lib/agents/run_context.rb
|
@@ -73,7 +75,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
73
75
|
requirements:
|
74
76
|
- - ">="
|
75
77
|
- !ruby/object:Gem::Version
|
76
|
-
version: 3.
|
78
|
+
version: 3.2.0
|
77
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
80
|
requirements:
|
79
81
|
- - ">="
|