Class: ActiveAgent::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/active_agent/base.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(conversation_id:, memory_store: nil) ⇒ Base

Returns a new instance of Base.



45
46
47
48
49
50
51
52
53
54
# File 'lib/active_agent/base.rb', line 45

def initialize(conversation_id:, memory_store: nil)
  @conversation_id = conversation_id

  store = memory_store || ActiveAgent.configuration.memory_store
  @memory = Memory.for(store, conversation_id)

  provider_name = self.class._provider || ActiveAgent.configuration.default_provider
  model_name = self.class._model
  @provider_client = Provider.for(provider_name, model_name)
end

Instance Attribute Details

#conversation_idObject (readonly)

Returns the value of attribute conversation_id.



43
44
45
# File 'lib/active_agent/base.rb', line 43

def conversation_id
  @conversation_id
end

#memoryObject (readonly)

Returns the value of attribute memory.



43
44
45
# File 'lib/active_agent/base.rb', line 43

def memory
  @memory
end

#provider_clientObject (readonly)

Returns the value of attribute provider_client.



43
44
45
# File 'lib/active_agent/base.rb', line 43

def provider_client
  @provider_client
end

Class Method Details

.model(name) ⇒ Object



24
25
26
# File 'lib/active_agent/base.rb', line 24

def model(name)
  self._model = name.to_s
end

.provider(name) ⇒ Object



20
21
22
# File 'lib/active_agent/base.rb', line 20

def provider(name)
  self._provider = name.to_sym
end

.system_prompt(prompt) ⇒ Object



28
29
30
# File 'lib/active_agent/base.rb', line 28

def system_prompt(prompt)
  self._system_prompt = prompt.to_s
end

.tool(name, description: "", &block) ⇒ Object



32
33
34
35
36
# File 'lib/active_agent/base.rb', line 32

def tool(name, description: "", &block)
  # Duplicate to avoid mutating parent class tools
  self._tools = _tools.dup
  self._tools[name.to_s] = Tool.new(name, description: description, &block)
end

.toolsObject



38
39
40
# File 'lib/active_agent/base.rb', line 38

def tools
  _tools.values
end

Instance Method Details

#chat(user_input, &block) ⇒ Object

Core chat loop that handles automatic tool execution



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/active_agent/base.rb', line 57

def chat(user_input, &block)
  memory.add_message(role: :user, content: user_input)

  loop_count = 0
  loop do
    loop_count += 1
    if loop_count > 10
      raise "ActiveAgent Loop Limit: Exceeded 10 iterations of tool execution."
    end

    # Assemble system prompt + chat history
    history = []
    if self.class._system_prompt.present?
      history << { role: :system, content: self.class._system_prompt }
    end
    history += memory.messages

    # Fetch response from provider (passing block for streaming)
    response = provider_client.chat(history, tools: self.class.tools, &block)

    # Store response in memory
    memory.add_message(
      role: response[:role],
      content: response[:content],
      tool_calls: response[:tool_calls]
    )

    if response[:tool_calls]&.any?
      response[:tool_calls].each do |tool_call|
        tool_name = tool_call[:name]
        tool_args = tool_call[:args] || {}
        tool_id = tool_call[:id]

        ActiveAgent.logger.info("[ActiveAgent] Executing tool '#{tool_name}' with args: #{tool_args}")

        output_str = if respond_to?(tool_name)
                       begin
                         # Call the agent instance method
                         result = send(tool_name, **tool_args)
                         result.is_a?(String) ? result : result.to_json
                       rescue StandardError => e
                         ActiveAgent.logger.error("[ActiveAgent] Tool '#{tool_name}' error: #{e.message}")
                         { error: e.message }.to_json
                       end
                     else
                       ActiveAgent.logger.warn("[ActiveAgent] Tool '#{tool_name}' not implemented on #{self.class.name}")
                       { error: "Tool '#{tool_name}' is not implemented on the agent." }.to_json
                     end

        # Store tool response
        memory.add_message(
          role: :tool,
          content: output_str,
          name: tool_name,
          tool_call_id: tool_id
        )
      end
      # Loop again to let LLM process the tool output
    else
      return response[:content]
    end
  end
end