Class: OmniAgent::Agent

Inherits:
Object
  • Object
show all
Defined in:
lib/omni_agent/agent.rb

Defined Under Namespace

Modules: ImplicitRunEntrypoints

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(provider_override: nil, model_override: nil, options_override: {}, context_override: {}) ⇒ Agent

Returns a new instance of Agent.



140
141
142
143
144
145
146
# File 'lib/omni_agent/agent.rb', line 140

def initialize(provider_override: nil, model_override: nil, options_override: {}, context_override: {})
  target_provider_name = provider_override || self.class.configured_provider_name || OmniAgent.configuration.default_provider
  target_model = model_override || self.class.configured_provider_options[:model]
  @chat_options = self.class.configured_model_options.merge(options_override)
  @provider = resolve_provider(target_provider_name, target_model)
  @default_context = context_override || {}
end

Instance Attribute Details

#providerObject (readonly)

Returns the value of attribute provider.



3
4
5
# File 'lib/omni_agent/agent.rb', line 3

def provider
  @provider
end

Class Method Details

.after_generation(*callbacks) ⇒ Object



67
68
69
# File 'lib/omni_agent/agent.rb', line 67

def after_generation(*callbacks)
  @after_generation_callbacks = configured_after_generation_callbacks + normalize_callbacks(:after_generation, callbacks)
end

.before_generation(*callbacks) ⇒ Object



63
64
65
# File 'lib/omni_agent/agent.rb', line 63

def before_generation(*callbacks)
  @before_generation_callbacks = configured_before_generation_callbacks + normalize_callbacks(:before_generation, callbacks)
end

.configured_after_generation_callbacksObject



105
# File 'lib/omni_agent/agent.rb', line 105

def configured_after_generation_callbacks; @after_generation_callbacks || []; end

.configured_before_generation_callbacksObject



104
# File 'lib/omni_agent/agent.rb', line 104

def configured_before_generation_callbacks; @before_generation_callbacks || []; end

.configured_model_optionsObject



102
# File 'lib/omni_agent/agent.rb', line 102

def configured_model_options; @model_options || {}; end

.configured_provider_nameObject



100
# File 'lib/omni_agent/agent.rb', line 100

def configured_provider_name; @provider_name; end

.configured_provider_optionsObject



101
# File 'lib/omni_agent/agent.rb', line 101

def configured_provider_options; @provider_options || {}; end

.configured_tagsObject



106
# File 'lib/omni_agent/agent.rb', line 106

def configured_tags; tags; end

.configured_with_use_model?Boolean

Returns:

  • (Boolean)


103
# File 'lib/omni_agent/agent.rb', line 103

def configured_with_use_model?; @configured_with_use_model == true; end

.inherited(subclass) ⇒ Object



108
109
110
111
# File 'lib/omni_agent/agent.rb', line 108

def inherited(subclass)
  super
  subclass.extend(ImplicitRunEntrypoints)
end

.options(**options) ⇒ Object



50
51
52
# File 'lib/omni_agent/agent.rb', line 50

def options(**options)
  @model_options = configured_model_options.merge(options)
end

.provider(name, **options) ⇒ Object



41
42
43
44
45
46
47
48
# File 'lib/omni_agent/agent.rb', line 41

def provider(name, **options)
  if configured_with_use_model?
    raise OmniAgent::Error, "Cannot combine `provider` and `use_model` in the same agent. Use either `provider ..., model: ...` or `use_model ...`."
  end

  @provider_name = name
  @provider_options = options
end

.run_aliases(*method_names) ⇒ Object



77
78
79
80
81
82
83
84
85
# File 'lib/omni_agent/agent.rb', line 77

def run_aliases(*method_names)
  aliases = normalize_callbacks(:run_aliases, method_names)

  aliases.each do |method_name|
    define_method(method_name) do |input, context: {}|
      run(input, context: context, prompt_method: method_name)
    end
  end
end

.tags(*tag_names) ⇒ Object



71
72
73
74
75
# File 'lib/omni_agent/agent.rb', line 71

def tags(*tag_names)
  return @configured_tags || [] if tag_names.empty?

  @configured_tags = (tags + normalize_tags(tag_names)).uniq
end

.use_model(name) ⇒ Object



54
55
56
57
58
59
60
61
# File 'lib/omni_agent/agent.rb', line 54

def use_model(name)
  if configured_provider_name || configured_provider_options.any?
    raise OmniAgent::Error, "Cannot combine `provider` and `use_model` in the same agent. Use either `provider ..., model: ...` or `use_model ...`."
  end

  @configured_with_use_model = true
  @provider_options = { model: name }
end

.with(context = nil, provider_override: nil, model_override: nil, options_override: {}, **context_keywords) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/omni_agent/agent.rb', line 87

def with(context = nil, provider_override: nil, model_override: nil, options_override: {}, **context_keywords)
  merged_context = {}
  merged_context.merge!(context) if context.is_a?(Hash)
  merged_context.merge!(context_keywords)

  new(
    provider_override: provider_override,
    model_override: model_override,
    options_override: options_override,
    context_override: merged_context
  )
end

Instance Method Details

#available_toolsObject



213
214
215
216
217
218
219
220
221
# File 'lib/omni_agent/agent.rb', line 213

def available_tools
  tool_namespace = "#{self.class.name}::Tools".safe_constantize
  return [] unless tool_namespace

  tool_namespace.constants.filter_map do |const_name|
    const = tool_namespace.const_get(const_name)
    const if const.is_a?(Class) && const < OmniAgent::Tool
  end
end

#run(input, context: {}, prompt_method: nil) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/omni_agent/agent.rb', line 148

def run(input, context: {}, prompt_method: nil)
  context = @default_context.merge(context || {})

  messages = [
    { role: "system", content: nil },
    { role: "user", content: input }
  ]

  run_before_generation_callbacks(input: input, context: context, messages: messages)
  messages[0][:content] = system_prompt(context: context, prompt_method: prompt_method)

  filtered_tools = tool_filter(tools: available_tools, agent_tags: self.class.tags)

  loop do
    response = provider.chat(messages: messages, tools: filtered_tools, **@chat_options)

    if response.content && !response.tool_calls?
      messages << { role: "assistant", content: response.content }
      run_after_generation_callbacks(input: input, context: context, messages: messages, response: response)
      return response.content
    end

    messages << {
      role: "assistant",
      content: response.content,
      tool_calls: response.raw_response.dig("choices", 0, "message", "tool_calls")
    }

    response.tool_calls.each do |tool_call|
      tool_name = tool_call[:name]
      tool_args = tool_call[:arguments]
      tool_id   = tool_call[:id]

      tool_class = filtered_tools.find { |t| t.name.demodulize == tool_name }

      if tool_class
        begin
          result = tool_class.invoke(tool_args)

          messages << {
            role: "tool",
            tool_call_id: tool_id,
            name: tool_name,
            content: result.to_s
          }
        rescue => e
          messages << {
            role: "tool",
            tool_call_id: tool_id,
            name: tool_name,
            content: "Error executing tool: #{e.message}"
          }
        end
      else
        messages << {
          role: "tool",
          tool_call_id: tool_id,
          name: tool_name,
          content: "Error: Tool #{tool_name} is not registered to this agent."
        }
      end
    end
  end
end