Class: Agents::Agent
- Inherits:
-
Object
- Object
- Agents::Agent
- Defined in:
- lib/agents/agent.rb
Instance Attribute Summary collapse
-
#assume_model_exists ⇒ Object
readonly
Returns the value of attribute assume_model_exists.
-
#handoff_agents ⇒ Object
readonly
Returns the value of attribute handoff_agents.
-
#headers ⇒ Object
readonly
Returns the value of attribute headers.
-
#instructions ⇒ Object
readonly
Returns the value of attribute instructions.
-
#model ⇒ Object
readonly
Returns the value of attribute model.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#params ⇒ Object
readonly
Returns the value of attribute params.
-
#provider ⇒ Object
readonly
Returns the value of attribute provider.
-
#response_schema ⇒ Object
readonly
Returns the value of attribute response_schema.
-
#temperature ⇒ Object
readonly
Returns the value of attribute temperature.
-
#tools ⇒ Object
readonly
Returns the value of attribute tools.
Instance Method Summary collapse
-
#all_tools ⇒ Array<Agents::Tool>
Get all tools available to this agent, including any auto-generated handoff tools.
-
#as_tool(name: nil, description: nil, output_extractor: nil) ⇒ Agents::AgentTool
Transform this agent into a tool, callable by other agents.
-
#clone(**changes) ⇒ Agents::Agent
Creates a new agent instance with modified attributes while preserving immutability.
-
#get_system_prompt(context) ⇒ String?
Get the system prompt for the agent, potentially customized based on runtime context.
-
#initialize(name:, instructions: nil, model: "gpt-4.1-mini", provider: nil, assume_model_exists: false, tools: [], handoff_agents: [], temperature: 0.7, response_schema: nil, headers: nil, params: nil) ⇒ Agent
constructor
Initialize a new Agent instance.
-
#register_handoffs(*agents) ⇒ self
Register agents that this agent can hand off to.
Constructor Details
#initialize(name:, instructions: nil, model: "gpt-4.1-mini", provider: nil, assume_model_exists: false, tools: [], handoff_agents: [], temperature: 0.7, response_schema: nil, headers: nil, params: nil) ⇒ Agent
Initialize a new Agent instance
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 |
# File 'lib/agents/agent.rb', line 69 def initialize(name:, instructions: nil, model: "gpt-4.1-mini", provider: nil, assume_model_exists: false, tools: [], handoff_agents: [], temperature: 0.7, response_schema: nil, headers: nil, params: nil) @name = name @instructions = instructions @model = model @provider = provider&.to_sym @assume_model_exists = assume_model_exists @tools = tools.dup @handoff_agents = [] @temperature = temperature @response_schema = response_schema @headers = Helpers::HashNormalizer.normalize(headers, label: "headers", freeze_result: true) @params = Helpers::HashNormalizer.normalize(params, label: "params", freeze_result: true) # Mutex for thread-safe handoff registration # While agents are typically configured at startup, we want to ensure # that concurrent handoff registrations don't result in lost data. # For example, in a web server with multiple threads initializing # different parts of the system, we might have: # Thread 1: triage.register_handoffs(billing) # Thread 2: triage.register_handoffs(support) # Without synchronization, one registration could overwrite the other. @mutex = Mutex.new # Register initial handoff agents if provided register_handoffs(*handoff_agents) unless handoff_agents.empty? end |
Instance Attribute Details
#assume_model_exists ⇒ Object (readonly)
Returns the value of attribute assume_model_exists.
53 54 55 |
# File 'lib/agents/agent.rb', line 53 def assume_model_exists @assume_model_exists end |
#handoff_agents ⇒ Object (readonly)
Returns the value of attribute handoff_agents.
53 54 55 |
# File 'lib/agents/agent.rb', line 53 def handoff_agents @handoff_agents end |
#headers ⇒ Object (readonly)
Returns the value of attribute headers.
53 54 55 |
# File 'lib/agents/agent.rb', line 53 def headers @headers end |
#instructions ⇒ Object (readonly)
Returns the value of attribute instructions.
53 54 55 |
# File 'lib/agents/agent.rb', line 53 def instructions @instructions end |
#model ⇒ Object (readonly)
Returns the value of attribute model.
53 54 55 |
# File 'lib/agents/agent.rb', line 53 def model @model end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
53 54 55 |
# File 'lib/agents/agent.rb', line 53 def name @name end |
#params ⇒ Object (readonly)
Returns the value of attribute params.
53 54 55 |
# File 'lib/agents/agent.rb', line 53 def params @params end |
#provider ⇒ Object (readonly)
Returns the value of attribute provider.
53 54 55 |
# File 'lib/agents/agent.rb', line 53 def provider @provider end |
#response_schema ⇒ Object (readonly)
Returns the value of attribute response_schema.
53 54 55 |
# File 'lib/agents/agent.rb', line 53 def response_schema @response_schema end |
#temperature ⇒ Object (readonly)
Returns the value of attribute temperature.
53 54 55 |
# File 'lib/agents/agent.rb', line 53 def temperature @temperature end |
#tools ⇒ Object (readonly)
Returns the value of attribute tools.
53 54 55 |
# File 'lib/agents/agent.rb', line 53 def tools @tools end |
Instance Method Details
#all_tools ⇒ Array<Agents::Tool>
Get all tools available to this agent, including any auto-generated handoff tools
100 101 102 103 104 105 106 |
# File 'lib/agents/agent.rb', line 100 def all_tools @mutex.synchronize do # Compute handoff tools dynamically handoff_tools = @handoff_agents.map { |agent| HandoffTool.new(agent) } @tools + handoff_tools end end |
#as_tool(name: nil, description: nil, output_extractor: nil) ⇒ Agents::AgentTool
Transform this agent into a tool, callable by other agents. This enables agent-to-agent collaboration without conversation handoffs.
Agent-as-tool is different from handoffs in two key ways:
-
The wrapped agent receives generated input, not conversation history
-
The wrapped agent returns a result to the calling agent, rather than taking over
248 249 250 251 252 253 254 255 |
# File 'lib/agents/agent.rb', line 248 def as_tool(name: nil, description: nil, output_extractor: nil) AgentTool.new( agent: self, name: name, description: description, output_extractor: output_extractor ) end |
#clone(**changes) ⇒ Agents::Agent
Creates a new agent instance with modified attributes while preserving immutability. The clone method is used when you need to create variations of agents without mutating the original. This can be used for runtime agent modifications, say in a multi-tenant environment we can do something like the following:
The key insight to note here is that clone ensures immutability - you never accidentally modify a shared agent instance that other requests might be using. This is critical for thread safety in concurrent environments.
This also ensures we also get to leverage the syntax sugar defining a class provides us with.
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/agents/agent.rb', line 170 def clone(**changes) self.class.new( name: changes.fetch(:name, @name), instructions: changes.fetch(:instructions, @instructions), model: changes.fetch(:model, @model), provider: changes.fetch(:provider, @provider), assume_model_exists: changes.fetch(:assume_model_exists, @assume_model_exists), tools: changes.fetch(:tools, @tools.dup), handoff_agents: changes.fetch(:handoff_agents, @handoff_agents), temperature: changes.fetch(:temperature, @temperature), response_schema: changes.fetch(:response_schema, @response_schema), headers: changes.fetch(:headers, @headers), params: changes.fetch(:params, @params) ) end |
#get_system_prompt(context) ⇒ String?
Get the system prompt for the agent, potentially customized based on runtime context. We will allow setting up a Proc for instructions. This will allow us the inject context in runtime.
211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/agents/agent.rb', line 211 def get_system_prompt(context) # TODO: Add string interpolation support for instructions # Allow instructions like "You are helping %{customer_name}" that automatically # get state values injected from context[:state] using Ruby's % formatting case instructions when String instructions when Proc instructions.call(context) end end |
#register_handoffs(*agents) ⇒ self
Register agents that this agent can hand off to. This method can be called after agent creation to set up handoff relationships. Thread-safe: Multiple threads can safely call this method concurrently.
124 125 126 127 128 129 130 |
# File 'lib/agents/agent.rb', line 124 def register_handoffs(*agents) @mutex.synchronize do @handoff_agents.concat(agents) @handoff_agents.uniq! # Prevent duplicates end self end |