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.
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
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Agents
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  end
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.0
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.1.0
78
+ version: 3.2.0
77
79
  required_rubygems_version: !ruby/object:Gem::Requirement
78
80
  requirements:
79
81
  - - ">="