Class: RailsAi::Agents::BaseAgent

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_ai/agents/base_agent.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, role:, capabilities: [], memory_size: 1000, **opts) ⇒ BaseAgent

Returns a new instance of BaseAgent.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/rails_ai/agents/base_agent.rb', line 8

def initialize(name:, role:, capabilities: [], memory_size: 1000, **opts)
  @name = name
  @role = role
  @capabilities = Array(capabilities)
  @memory = Memory.new(max_size: memory_size)
  @state = :idle
  @created_at = Time.now
  @last_activity = Time.now
  @config = opts
  @message_queue = []
  @active_tasks = []
  @completed_tasks = []
  @failed_tasks = []
end

Instance Attribute Details

#active_tasksObject (readonly)

Returns the value of attribute active_tasks.



6
7
8
# File 'lib/rails_ai/agents/base_agent.rb', line 6

def active_tasks
  @active_tasks
end

#capabilitiesObject (readonly)

Returns the value of attribute capabilities.



6
7
8
# File 'lib/rails_ai/agents/base_agent.rb', line 6

def capabilities
  @capabilities
end

#completed_tasksObject (readonly)

Returns the value of attribute completed_tasks.



6
7
8
# File 'lib/rails_ai/agents/base_agent.rb', line 6

def completed_tasks
  @completed_tasks
end

#created_atObject (readonly)

Returns the value of attribute created_at.



6
7
8
# File 'lib/rails_ai/agents/base_agent.rb', line 6

def created_at
  @created_at
end

#failed_tasksObject (readonly)

Returns the value of attribute failed_tasks.



6
7
8
# File 'lib/rails_ai/agents/base_agent.rb', line 6

def failed_tasks
  @failed_tasks
end

#last_activityObject (readonly)

Returns the value of attribute last_activity.



6
7
8
# File 'lib/rails_ai/agents/base_agent.rb', line 6

def last_activity
  @last_activity
end

#memoryObject (readonly)

Returns the value of attribute memory.



6
7
8
# File 'lib/rails_ai/agents/base_agent.rb', line 6

def memory
  @memory
end

#nameObject (readonly)

Returns the value of attribute name.



6
7
8
# File 'lib/rails_ai/agents/base_agent.rb', line 6

def name
  @name
end

#roleObject (readonly)

Returns the value of attribute role.



6
7
8
# File 'lib/rails_ai/agents/base_agent.rb', line 6

def role
  @role
end

#stateObject (readonly)

Returns the value of attribute state.



6
7
8
# File 'lib/rails_ai/agents/base_agent.rb', line 6

def state
  @state
end

Instance Method Details

#accept_delegated_task(delegation) ⇒ Object



239
240
241
242
243
244
245
246
247
# File 'lib/rails_ai/agents/base_agent.rb', line 239

def accept_delegated_task(delegation)
  task = delegation[:delegation][:task]
  return false unless can_handle_task?(task)

  assign_task(task.merge(
    delegated_from: delegation[:from],
    delegation_id: delegation[:delegation][:id]
  ))
end

#assign_task(task) ⇒ Object

Task management



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/rails_ai/agents/base_agent.rb', line 53

def assign_task(task)
  return false unless can_handle_task?(task)

  @active_tasks << task.merge(
    assigned_at: Time.now,
    status: :in_progress
  )
  @last_activity = Time.now
  
  defined?(Rails) && Rails.logger && Rails.logger.info("Agent #{@name} assigned task: #{task[:description]}")
  true
end

#can_handle_task?(task) ⇒ Boolean

Capability checks

Returns:

  • (Boolean)


164
165
166
167
168
169
170
# File 'lib/rails_ai/agents/base_agent.rb', line 164

def can_handle_task?(task)
  return false unless @state == :active
  return false if @active_tasks.length >= max_concurrent_tasks

  required_capabilities = task[:required_capabilities] || []
  required_capabilities.all? { |cap| @capabilities.include?(cap) }
end

#collaborate_with(other_agent, task, context: {}) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/rails_ai/agents/base_agent.rb', line 146

def collaborate_with(other_agent, task, context: {})
  return "[stubbed] Collaboration between #{@name} and #{other_agent.name}" if RailsAi.config.stub_responses

  collaboration_prompt = build_collaboration_prompt(other_agent, task, context)
  response = think(collaboration_prompt, context: context)
  
  # Send collaboration result to other agent
  send_message(other_agent.name, {
    type: :collaboration_result,
    task: task,
    result: response,
    from_agent: @name
  })
  
  response
end

#complete_task(task_id, result) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rails_ai/agents/base_agent.rb', line 66

def complete_task(task_id, result)
  task = @active_tasks.find { |t| t[:id] == task_id }
  return false unless task

  @active_tasks.delete(task)
  @completed_tasks << task.merge(
    completed_at: Time.now,
    status: :completed,
    result: result
  )
  @last_activity = Time.now
  
  defined?(Rails) && Rails.logger && Rails.logger.info("Agent #{@name} completed task: #{task[:description]}")
  true
end

#decide_next_action(context: {}) ⇒ Object



137
138
139
140
141
142
143
144
# File 'lib/rails_ai/agents/base_agent.rb', line 137

def decide_next_action(context: {})
  return { action: :wait, reason: "Stubbed response" } if RailsAi.config.stub_responses

  decision_prompt = build_decision_prompt(context)
  response = think(decision_prompt, context: context)
  
  parse_decision(response)
end

#delegate_task(task, target_agent, reason: nil) ⇒ Object

Task delegation



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/rails_ai/agents/base_agent.rb', line 217

def delegate_task(task, target_agent, reason: nil)
  return false unless can_delegate_task?(task, target_agent)

  delegation = {
    task: task,
    from_agent: @name,
    to_agent: target_agent.name,
    reason: reason,
    delegated_at: Time.now,
    status: :pending
  }

  send_message(target_agent.name, {
    type: :task_delegation,
    delegation: delegation
  })

  @last_activity = Time.now
  defined?(Rails) && Rails.logger && Rails.logger.info("Agent #{@name} delegated task to #{target_agent.name}")
  delegation
end

#fail_task(task_id, error) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/rails_ai/agents/base_agent.rb', line 82

def fail_task(task_id, error)
  task = @active_tasks.find { |t| t[:id] == task_id }
  return false unless task

  @active_tasks.delete(task)
  @failed_tasks << task.merge(
    failed_at: Time.now,
    status: :failed,
    error: error
  )
  @last_activity = Time.now
  
  defined?(Rails) && Rails.logger && Rails.logger.error("Agent #{@name} failed task: #{task[:description]} - #{error}")
  true
end

#forget(key) ⇒ Object



211
212
213
214
# File 'lib/rails_ai/agents/base_agent.rb', line 211

def forget(key)
  @memory.remove(key)
  @last_activity = Time.now
end

#get_messages(from_agent = nil) ⇒ Object



121
122
123
124
125
# File 'lib/rails_ai/agents/base_agent.rb', line 121

def get_messages(from_agent = nil)
  messages = @message_queue
  messages = messages.select { |m| m[:from] == from_agent } if from_agent
  messages
end

#has_capability?(capability) ⇒ Boolean

Returns:

  • (Boolean)


172
173
174
# File 'lib/rails_ai/agents/base_agent.rb', line 172

def has_capability?(capability)
  @capabilities.include?(capability.to_sym)
end

#health_checkObject



192
193
194
195
196
197
198
199
# File 'lib/rails_ai/agents/base_agent.rb', line 192

def health_check
  {
    state: @state,
    memory_healthy: @memory.usage_percentage < 90,
    no_stuck_tasks: @active_tasks.none? { |t| Time.now - t[:assigned_at] > max_task_duration },
    last_activity_recent: Time.now - @last_activity < 5 * 60
  }
end

#pause!Object



38
39
40
41
42
43
# File 'lib/rails_ai/agents/base_agent.rb', line 38

def pause!
  @state = :paused
  @last_activity = Time.now
  defined?(Rails) && Rails.logger && Rails.logger.info("Agent #{@name} paused")
  self
end

#recall(key) ⇒ Object



207
208
209
# File 'lib/rails_ai/agents/base_agent.rb', line 207

def recall(key)
  @memory.get(key)
end

#receive_message(message) ⇒ Object



115
116
117
118
119
# File 'lib/rails_ai/agents/base_agent.rb', line 115

def receive_message(message)
  @memory.add(:message, message)
  @last_activity = Time.now
  defined?(Rails) && Rails.logger && Rails.logger.info("Agent #{@name} received message from #{message[:from]}")
end

#remember(key, value, importance: :normal) ⇒ Object

Memory management



202
203
204
205
# File 'lib/rails_ai/agents/base_agent.rb', line 202

def remember(key, value, importance: :normal)
  @memory.add(key, value, importance: importance)
  @last_activity = Time.now
end

#resume!Object



45
46
47
48
49
50
# File 'lib/rails_ai/agents/base_agent.rb', line 45

def resume!
  @state = :active
  @last_activity = Time.now
  defined?(Rails) && Rails.logger && Rails.logger.info("Agent #{@name} resumed")
  self
end

#send_message(to_agent, message) ⇒ Object

Communication methods



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/rails_ai/agents/base_agent.rb', line 99

def send_message(to_agent, message)
  message_obj = {
    from: @name,
    to: to_agent,
    content: message,
    timestamp: Time.now,
    id: SecureRandom.uuid
  }
  
  @message_queue << message_obj
  @last_activity = Time.now
  
  defined?(Rails) && Rails.logger && Rails.logger.info("Agent #{@name} sent message to #{to_agent}")
  message_obj
end

#start!Object

Core agent lifecycle methods



24
25
26
27
28
29
# File 'lib/rails_ai/agents/base_agent.rb', line 24

def start!
  @state = :active
  @last_activity = Time.now
  defined?(Rails) && Rails.logger && Rails.logger.info("Agent #{@name} started")
  self
end

#statusObject

Status and monitoring



177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/rails_ai/agents/base_agent.rb', line 177

def status
  {
    name: @name,
    role: @role,
    state: @state,
    capabilities: @capabilities,
    active_tasks: @active_tasks.length,
    completed_tasks: @completed_tasks.length,
    failed_tasks: @failed_tasks.length,
    memory_usage: @memory.usage_percentage,
    last_activity: @last_activity,
    uptime: Time.now - @created_at
  }
end

#stop!Object



31
32
33
34
35
36
# File 'lib/rails_ai/agents/base_agent.rb', line 31

def stop!
  @state = :stopped
  @last_activity = Time.now
  defined?(Rails) && Rails.logger && Rails.logger.info("Agent #{@name} stopped")
  self
end

#think(prompt, context: {}) ⇒ Object

AI-powered decision making



128
129
130
131
132
133
134
135
# File 'lib/rails_ai/agents/base_agent.rb', line 128

def think(prompt, context: {})
  return "[stubbed] Agent #{@name} thinking: #{prompt}" if RailsAi.config.stub_responses

  full_context = build_context(context)
  enhanced_prompt = build_agent_prompt(prompt, full_context)
  
  RailsAi.chat(enhanced_prompt, model: RailsAi.config.default_model)
end