Class: Agents::Agent
- Inherits:
-
Object
- Object
- Agents::Agent
- Defined in:
- lib/agents/agent.rb
Instance Attribute Summary collapse
-
#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.
-
#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", 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", tools: [], handoff_agents: [], temperature: 0.7, response_schema: nil, headers: nil, params: nil) ⇒ Agent
Initialize a new Agent instance
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 |
# File 'lib/agents/agent.rb', line 66 def initialize(name:, instructions: nil, model: "gpt-4.1-mini", tools: [], handoff_agents: [], temperature: 0.7, response_schema: nil, headers: nil, params: nil) @name = name @instructions = instructions @model = model @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
#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 |
#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
95 96 97 98 99 100 101 |
# File 'lib/agents/agent.rb', line 95 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
239 240 241 242 243 244 245 246 |
# File 'lib/agents/agent.rb', line 239 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.
163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/agents/agent.rb', line 163 def clone(**changes) self.class.new( name: changes.fetch(:name, @name), instructions: changes.fetch(:instructions, @instructions), model: changes.fetch(:model, @model), 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.
202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/agents/agent.rb', line 202 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.
119 120 121 122 123 124 125 |
# File 'lib/agents/agent.rb', line 119 def register_handoffs(*agents) @mutex.synchronize do @handoff_agents.concat(agents) @handoff_agents.uniq! # Prevent duplicates end self end |