ai-agents 0.4.3 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a3f2287a007ce187c91546ee4ef723cadcde40e7102454d4d432c2c2c72e4e45
4
- data.tar.gz: 4c9b810362d923c0fb821491a63fa8647c926e2666e6902383200ca8f988cf10
3
+ metadata.gz: 7f8fa7ec73784bc0fb1e9e6bd4852c6d0295160c4ca28d435c895cba28f5cd58
4
+ data.tar.gz: 3e489f11ae2a5c93b4232ec78e3c7385c83f303c28039ed35fa082669fedaf4b
5
5
  SHA512:
6
- metadata.gz: aaa5ba1612a2551b83d3f779a10301c806f9a95eb082b4c6ab6db56fdc90487093b0a5edd0c5edc16c2a4888e1ada2abc66433bab73c569886b3b66f0c41d528
7
- data.tar.gz: 2669853cd34f497d696fba2ccf02ed384057ea144b7ffdd0c390aa28c1c4bf830929723f181a0bfd130e206707fc80f9c2a0e12259da53099ef8ab92c5f681d8
6
+ metadata.gz: ba5050ba743466993826d888673d90696d27f422df3d3972027fa141de05d6436c45cd44dba0836dc6350ad83c0ff1628ba43bbce6d93e5e49e8efc450554e91
7
+ data.tar.gz: efed7a181a6f52c4c8feb8b84e1bbb2309b5216a85569dae69dd4038cde0cdad7a283e066181414e50657aee063e79935573799fdc24abc6253b02bcb8e5d09f
data/.rubocop.yml CHANGED
@@ -10,20 +10,18 @@ Style/StringLiterals:
10
10
  Style/StringLiteralsInInterpolation:
11
11
  EnforcedStyle: double_quotes
12
12
 
13
+ Metrics/MethodLength:
14
+ Max: 20
15
+ Metrics/ClassLength:
16
+ Enabled: false
17
+
18
+ RSpec/MultipleDescribes:
19
+ Enabled: false
13
20
  RSpec/MultipleExpectations:
14
21
  Max: 10
15
-
16
22
  RSpec/ExampleLength:
17
23
  Max: 20
18
-
19
24
  RSpec/MultipleMemoizedHelpers:
20
25
  Max: 15
21
-
22
26
  RSpec/SpecFilePathFormat:
23
27
  Enabled: false
24
-
25
- Metrics/MethodLength:
26
- Max: 20
27
-
28
- RSpec/MultipleDescribes:
29
- Enabled: false
data/CHANGELOG.md CHANGED
@@ -5,6 +5,33 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.6.0] - 2025-10-16
9
+
10
+ ### Added
11
+ - **Custom HTTP Headers Support**: Agents can now specify custom HTTP headers for LLM requests
12
+ - Added `headers` parameter to `Agent#initialize` for setting agent-level default headers
13
+ - Runtime headers can be passed via `headers` parameter in `AgentRunner#run` method
14
+ - Runtime headers take precedence over agent-level headers when keys overlap
15
+ - Headers are automatically normalized (symbolized keys) and validated
16
+ - Full support for headers across agent handoffs with proper merging logic
17
+ - New `Agents::Helpers::Headers` module for header normalization and merging
18
+ - Comprehensive test coverage for header functionality
19
+
20
+ ### Changed
21
+ - **Code Organization**: Refactored internal helpers into dedicated module structure
22
+ - Moved `MessageExtractor` to `Agents::Helpers::MessageExtractor` module
23
+ - Converted `MessageExtractor` from class-based to module-function pattern
24
+ - Created `lib/agents/helpers/` directory for helper modules
25
+ - All helper modules now use consistent flat naming convention (`Agents::Helpers::ModuleName`)
26
+
27
+ ## [0.5.0] - 2025-08-20
28
+
29
+ ### Added
30
+ - Tool halting functionality for enhanced agent control
31
+
32
+ ### Removed
33
+ - Removed chat.rb component that made the codebase brittle
34
+
8
35
  ## [0.4.3] - 2025-08-04
9
36
 
10
37
  ### Fixed
data/CLAUDE.md CHANGED
@@ -63,7 +63,6 @@ This will start a command-line interface where you can interact with the multi-a
63
63
  - **Agent**: An AI assistant with a specific role, instructions, and tools.
64
64
  - **Tool**: A custom function that an agent can use to perform actions (e.g., look up customer data, send an email).
65
65
  - **Handoff**: The process of transferring a conversation from one agent to another. This is a core feature of the SDK.
66
- - **AgentRunner**: The thread-safe execution manager that coordinates multi-agent conversations and provides the main API.
67
66
  - **Runner**: Internal component that manages individual conversation turns (used by AgentRunner).
68
67
  - **Context**: A shared state object that stores conversation history and agent information, fully serializable for persistence.
69
68
  - **Callbacks**: Event hooks for monitoring agent execution, including agent thinking, tool start/complete, and handoffs.
@@ -114,7 +113,6 @@ ruby examples/isp-support/interactive.rb
114
113
  ### Core Components
115
114
 
116
115
  - **Agents::Agent**: Individual AI agents with specific roles, instructions, and tools
117
- - **Agents::AgentRunner**: Thread-safe execution manager with callback support
118
116
  - **Agents::Runner**: Orchestrates multi-agent conversations with automatic handoffs
119
117
  - **Agents::Tool**: Base class for custom tools that agents can execute
120
118
  - **Agents::Context**: Shared state management across agent interactions
@@ -174,7 +172,7 @@ support = Agent.new(name: "Support", instructions: "Technical support...")
174
172
  triage.register_handoffs(billing, support)
175
173
 
176
174
  # Create thread-safe runner (first agent is default entry point)
177
- runner = Agents::AgentRunner.with_agents(triage, billing, support)
175
+ runner = Agents::Runner.with_agents(triage, billing, support)
178
176
 
179
177
  # Add real-time callbacks for monitoring
180
178
  runner.on_agent_thinking { |agent_name, input| puts "🧠 #{agent_name} is thinking..." }
@@ -26,7 +26,7 @@ The SDK provides four types of callbacks that give you visibility into different
26
26
  Callbacks are registered on the AgentRunner using chainable methods:
27
27
 
28
28
  ```ruby
29
- runner = Agents::AgentRunner.with_agents(triage, support)
29
+ runner = Agents::Runner.with_agents(triage, support)
30
30
  .on_agent_thinking { |agent, input| puts "#{agent} thinking..." }
31
31
  .on_tool_start { |tool, args| puts "Using #{tool}" }
32
32
  .on_tool_complete { |tool, result| puts "#{tool} completed" }
@@ -23,7 +23,7 @@ billing_agent = Agents::Agent.new(
23
23
  )
24
24
 
25
25
  support_agent = Agents::Agent.new(
26
- name: "Support",
26
+ name: "Support",
27
27
  instructions: "Provide technical troubleshooting and product support."
28
28
  )
29
29
 
@@ -37,7 +37,7 @@ triage_agent = Agents::Agent.new(
37
37
  triage_agent.register_handoffs(billing_agent, support_agent)
38
38
 
39
39
  # Create runner with triage as entry point
40
- runner = Agents::AgentRunner.with_agents(triage_agent, billing_agent, support_agent)
40
+ runner = Agents::Runner.with_agents(triage_agent, billing_agent, support_agent)
41
41
  ```
42
42
 
43
43
  ### Dynamic Instructions
@@ -52,7 +52,7 @@ support_agent = Agents::Agent.new(
52
52
  <<~INSTRUCTIONS
53
53
  You are a technical support specialist for #{customer_tier} tier customers.
54
54
  #{customer_tier == "premium" ? "Provide priority white-glove service." : ""}
55
-
55
+
56
56
  Available tools: diagnostics, escalation
57
57
  INSTRUCTIONS
58
58
  }
@@ -73,7 +73,7 @@ sales_agent = Agents::Agent.new(
73
73
  )
74
74
 
75
75
  support_agent = Agents::Agent.new(
76
- name: "Support",
76
+ name: "Support",
77
77
  instructions: "Handle technical issues and product troubleshooting. Transfer sales questions to sales team."
78
78
  )
79
79
  ```
@@ -108,7 +108,7 @@ The first agent in `AgentRunner.with_agents()` becomes the default entry point:
108
108
 
109
109
  ```ruby
110
110
  # Triage agent handles all initial conversations
111
- runner = Agents::AgentRunner.with_agents(triage_agent, billing_agent, support_agent)
111
+ runner = Agents::Runner.with_agents(triage_agent, billing_agent, support_agent)
112
112
 
113
113
  # Start conversation
114
114
  result = runner.run("I need help with my account")
@@ -168,9 +168,9 @@ triage_agent = Agents::Agent.new(
168
168
  name: "Triage",
169
169
  instructions: ->(context) {
170
170
  business_hours = context[:business_hours] || false
171
-
171
+
172
172
  base_instructions = "Route users to appropriate departments."
173
-
173
+
174
174
  if business_hours
175
175
  base_instructions + " All departments are available."
176
176
  else
@@ -189,8 +189,8 @@ Test each agent in isolation:
189
189
  ```ruby
190
190
  RSpec.describe "BillingAgent" do
191
191
  let(:agent) { create_billing_agent }
192
- let(:runner) { Agents::AgentRunner.with_agents(agent) }
193
-
192
+ let(:runner) { Agents::Runner.with_agents(agent) }
193
+
194
194
  it "handles payment inquiries" do
195
195
  result = runner.run("What payment methods do you accept?")
196
196
  expect(result.output).to include("credit card", "bank transfer")
@@ -205,13 +205,13 @@ Test complete workflows:
205
205
  ```ruby
206
206
  RSpec.describe "Customer Support Workflow" do
207
207
  let(:runner) { create_support_runner } # Creates triage + specialists
208
-
208
+
209
209
  it "routes billing questions correctly" do
210
210
  result = runner.run("I have a billing question")
211
-
211
+
212
212
  # Verify handoff occurred
213
213
  expect(result.context[:current_agent]).to eq("Billing")
214
-
214
+
215
215
  # Test continued conversation
216
216
  followup = runner.run("What are your payment terms?", context: result.context)
217
217
  expect(followup.output).to include("payment terms")
@@ -258,4 +258,4 @@ threads = users.map do |user|
258
258
  # Handle result...
259
259
  end
260
260
  end
261
- ```
261
+ ```
@@ -49,7 +49,7 @@ class CreateConversations < ActiveRecord::Migration[7.0]
49
49
  t.string :current_agent
50
50
  t.timestamps
51
51
  end
52
-
52
+
53
53
  add_index :conversations, [:user_id, :created_at]
54
54
  end
55
55
  end
@@ -61,25 +61,25 @@ Define the Conversation model:
61
61
  # app/models/conversation.rb
62
62
  class Conversation < ApplicationRecord
63
63
  belongs_to :user
64
-
64
+
65
65
  # Serialize context as JSON
66
66
  serialize :context, JSON
67
-
67
+
68
68
  validates :context, presence: true
69
-
69
+
70
70
  def self.for_user(user)
71
71
  where(user: user).order(:created_at)
72
72
  end
73
-
73
+
74
74
  def self.latest_for_user(user)
75
75
  for_user(user).last
76
76
  end
77
-
77
+
78
78
  # Convert to agent context hash
79
79
  def to_agent_context
80
80
  context.deep_symbolize_keys
81
81
  end
82
-
82
+
83
83
  # Create from agent result
84
84
  def self.from_agent_result(user, result)
85
85
  create!(
@@ -102,26 +102,26 @@ class AgentConversationService
102
102
  @user = user
103
103
  @runner = create_agent_runner
104
104
  end
105
-
105
+
106
106
  def send_message(message)
107
107
  # Get existing conversation context
108
108
  context = load_conversation_context
109
-
109
+
110
110
  # Run agent with message
111
111
  result = @runner.run(message, context: context)
112
-
112
+
113
113
  # Persist updated conversation
114
114
  save_conversation(result)
115
-
115
+
116
116
  result
117
117
  end
118
-
118
+
119
119
  def reset_conversation
120
120
  Conversation.where(user: @user).destroy_all
121
121
  end
122
-
122
+
123
123
  private
124
-
124
+
125
125
  def create_agent_runner
126
126
  # Create your agents here
127
127
  triage_agent = Agents::Agent.new(
@@ -129,52 +129,52 @@ class AgentConversationService
129
129
  instructions: build_triage_instructions,
130
130
  tools: [CustomerLookupTool.new]
131
131
  )
132
-
132
+
133
133
  billing_agent = Agents::Agent.new(
134
134
  name: "Billing",
135
135
  instructions: "Handle billing and payment inquiries.",
136
136
  tools: [BillingTool.new, PaymentTool.new]
137
137
  )
138
-
138
+
139
139
  support_agent = Agents::Agent.new(
140
140
  name: "Support",
141
141
  instructions: "Provide technical support and troubleshooting.",
142
142
  tools: [TechnicalTool.new]
143
143
  )
144
-
144
+
145
145
  triage_agent.register_handoffs(billing_agent, support_agent)
146
-
147
- Agents::AgentRunner.with_agents(triage_agent, billing_agent, support_agent)
146
+
147
+ Agents::Runner.with_agents(triage_agent, billing_agent, support_agent)
148
148
  end
149
-
149
+
150
150
  def build_triage_instructions
151
151
  ->(context) {
152
152
  user_info = context[:user_info] || {}
153
-
153
+
154
154
  <<~INSTRUCTIONS
155
155
  You are a customer service triage agent for #{@user.name}.
156
-
156
+
157
157
  Customer Details:
158
158
  - Name: #{@user.name}
159
159
  - Email: #{@user.email}
160
160
  - Account Type: #{user_info[:account_type] || 'standard'}
161
-
161
+
162
162
  Route customers to the appropriate department:
163
163
  - Billing: Payment issues, account billing, refunds
164
164
  - Support: Technical problems, product questions
165
-
165
+
166
166
  Always be professional and helpful.
167
167
  INSTRUCTIONS
168
168
  }
169
169
  end
170
-
170
+
171
171
  def load_conversation_context
172
172
  latest_conversation = Conversation.latest_for_user(@user)
173
173
  return initial_context unless latest_conversation
174
-
174
+
175
175
  latest_conversation.to_agent_context
176
176
  end
177
-
177
+
178
178
  def initial_context
179
179
  {
180
180
  user_id: @user.id,
@@ -185,7 +185,7 @@ class AgentConversationService
185
185
  }
186
186
  }
187
187
  end
188
-
188
+
189
189
  def save_conversation(result)
190
190
  Conversation.from_agent_result(@user, result)
191
191
  end
@@ -200,13 +200,13 @@ Create a controller for handling agent conversations:
200
200
  # app/controllers/agent_conversations_controller.rb
201
201
  class AgentConversationsController < ApplicationController
202
202
  before_action :authenticate_user!
203
-
203
+
204
204
  def create
205
205
  service = AgentConversationService.new(current_user)
206
-
206
+
207
207
  begin
208
208
  result = service.send_message(params[:message])
209
-
209
+
210
210
  render json: {
211
211
  response: result.output,
212
212
  agent: result.context[:current_agent],
@@ -217,19 +217,19 @@ class AgentConversationsController < ApplicationController
217
217
  render json: { error: "Unable to process your request" }, status: 500
218
218
  end
219
219
  end
220
-
220
+
221
221
  def reset
222
222
  service = AgentConversationService.new(current_user)
223
223
  service.reset_conversation
224
-
224
+
225
225
  render json: { message: "Conversation reset successfully" }
226
226
  end
227
-
227
+
228
228
  def history
229
229
  conversations = Conversation.for_user(current_user)
230
230
  .includes(:user)
231
231
  .limit(50)
232
-
232
+
233
233
  render json: conversations.map do |conv|
234
234
  {
235
235
  id: conv.id,
@@ -252,13 +252,13 @@ class CustomerLookupTool < Agents::Tool
252
252
  name "lookup_customer"
253
253
  description "Look up customer information by email or ID"
254
254
  param :identifier, type: "string", desc: "Email address or customer ID"
255
-
255
+
256
256
  def perform(tool_context, identifier:)
257
257
  # Access Rails models safely
258
258
  customer = User.find_by(email: identifier) || User.find_by(id: identifier)
259
-
259
+
260
260
  return "Customer not found" unless customer
261
-
261
+
262
262
  {
263
263
  name: customer.name,
264
264
  email: customer.email,
@@ -274,13 +274,13 @@ class BillingTool < Agents::Tool
274
274
  name "get_billing_info"
275
275
  description "Retrieve billing information for a customer"
276
276
  param :user_id, type: "integer", desc: "Customer user ID"
277
-
277
+
278
278
  def perform(tool_context, user_id:)
279
279
  user = User.find(user_id)
280
280
  billing_info = user.billing_profile
281
-
281
+
282
282
  return "No billing information found" unless billing_info
283
-
283
+
284
284
  {
285
285
  plan: billing_info.plan_name,
286
286
  status: billing_info.status,
@@ -301,13 +301,13 @@ For longer conversations, use background jobs:
301
301
  # app/jobs/agent_conversation_job.rb
302
302
  class AgentConversationJob < ApplicationJob
303
303
  queue_as :default
304
-
304
+
305
305
  def perform(user_id, message, conversation_id = nil)
306
306
  user = User.find(user_id)
307
307
  service = AgentConversationService.new(user)
308
-
308
+
309
309
  result = service.send_message(message)
310
-
310
+
311
311
  # Broadcast result via ActionCable
312
312
  ActionCable.server.broadcast(
313
313
  "agent_conversation_#{user_id}",
@@ -327,7 +327,7 @@ def create_async
327
327
  params[:message],
328
328
  params[:conversation_id]
329
329
  )
330
-
330
+
331
331
  render json: { job_id: job_id }
332
332
  end
333
333
  ```
@@ -341,12 +341,12 @@ Implement comprehensive error handling:
341
341
  class AgentConversationService
342
342
  class AgentError < StandardError; end
343
343
  class ContextError < StandardError; end
344
-
344
+
345
345
  def send_message(message)
346
346
  validate_message(message)
347
-
347
+
348
348
  context = load_conversation_context
349
-
349
+
350
350
  begin
351
351
  result = @runner.run(message, context: context)
352
352
  save_conversation(result)
@@ -359,9 +359,9 @@ class AgentConversationService
359
359
  raise ContextError, "Conversation context corrupted"
360
360
  end
361
361
  end
362
-
362
+
363
363
  private
364
-
364
+
365
365
  def validate_message(message)
366
366
  raise ArgumentError, "Message cannot be blank" if message.blank?
367
367
  raise ArgumentError, "Message too long" if message.length > 5000
@@ -378,26 +378,26 @@ Test Rails integration with RSpec:
378
378
  RSpec.describe AgentConversationService do
379
379
  let(:user) { create(:user) }
380
380
  let(:service) { described_class.new(user) }
381
-
381
+
382
382
  describe '#send_message' do
383
383
  it 'creates a conversation record' do
384
384
  expect {
385
385
  service.send_message("Hello")
386
386
  }.to change(Conversation, :count).by(1)
387
387
  end
388
-
388
+
389
389
  it 'persists context correctly' do
390
390
  result = service.send_message("Hello")
391
391
  conversation = Conversation.last
392
-
392
+
393
393
  expect(conversation.user).to eq(user)
394
394
  expect(conversation.context).to include('user_id' => user.id)
395
395
  end
396
396
  end
397
-
397
+
398
398
  describe '#reset_conversation' do
399
399
  before { service.send_message("Hello") }
400
-
400
+
401
401
  it 'destroys all conversations for user' do
402
402
  expect {
403
403
  service.reset_conversation
@@ -437,4 +437,4 @@ add_index :conversations, :created_at
437
437
  every 1.day, at: '2:00 am' do
438
438
  runner "Conversation.where('created_at < ?', 30.days.ago).destroy_all"
439
439
  end
440
- ```
440
+ ```
@@ -0,0 +1,91 @@
1
+ ---
2
+ layout: default
3
+ title: Custom Request Headers
4
+ parent: Guides
5
+ nav_order: 6
6
+ ---
7
+
8
+ # Custom Request Headers
9
+
10
+ Custom HTTP headers allow you to pass additional metadata with your LLM API requests. This is useful for authentication, request tracking, A/B testing, and provider-specific features.
11
+
12
+ ## Basic Usage
13
+
14
+ ### Agent-Level Headers
15
+
16
+ Set default headers when creating an agent that will be applied to all requests:
17
+
18
+ ```ruby
19
+ agent = Agents::Agent.new(
20
+ name: "Assistant",
21
+ instructions: "You are a helpful assistant",
22
+ headers: {
23
+ "X-Custom-ID" => "agent-123",
24
+ "X-Environment" => "production"
25
+ }
26
+ )
27
+
28
+ runner = Agents::Runner.with_agents(agent)
29
+ result = runner.run("Hello!")
30
+ # All requests will include the custom headers
31
+ ```
32
+
33
+ ### Runtime Headers
34
+
35
+ Override or add headers for specific requests:
36
+
37
+ ```ruby
38
+ agent = Agents::Agent.new(
39
+ name: "Assistant",
40
+ instructions: "You are a helpful assistant"
41
+ )
42
+
43
+ runner = Agents::Runner.with_agents(agent)
44
+
45
+ # Pass headers at runtime
46
+ result = runner.run(
47
+ "What's the weather?",
48
+ headers: {
49
+ "X-Request-ID" => "req-456",
50
+ "X-User-ID" => "user-789"
51
+ }
52
+ )
53
+ ```
54
+
55
+ ### Header precedence
56
+
57
+ When both agent-level and runtime headers are provided, **runtime headers take precedence**:
58
+
59
+ ```ruby
60
+ agent = Agents::Agent.new(
61
+ name: "Assistant",
62
+ instructions: "You are a helpful assistant",
63
+ headers: {
64
+ "X-Environment" => "staging",
65
+ "X-Agent-ID" => "agent-001"
66
+ }
67
+ )
68
+
69
+ runner = Agents::Runner.with_agents(agent)
70
+
71
+ result = runner.run(
72
+ "Hello!",
73
+ headers: {
74
+ "X-Environment" => "production", # Overrides agent's staging value
75
+ "X-Request-ID" => "req-123" # Additional header
76
+ }
77
+ )
78
+
79
+ # Final headers sent to LLM API:
80
+ # {
81
+ # "X-Environment" => "production", # Runtime value wins
82
+ # "X-Agent-ID" => "agent-001", # From agent
83
+ # "X-Request-ID" => "req-123" # From runtime
84
+ # }
85
+ ```
86
+
87
+ ## See Also
88
+
89
+ - [Multi-Agent Systems](multi-agent-systems.html) - Using headers across agent handoffs
90
+ - [Rails Integration](rails-integration.html) - Request tracking in Rails applications
91
+ - [State Persistence](state-persistence.html) - Combining headers with conversation state
@@ -30,7 +30,7 @@ extraction_agent = Agents::Agent.new(
30
30
  }
31
31
  )
32
32
 
33
- runner = Agents::AgentRunner.with_agents(extraction_agent)
33
+ runner = Agents::Runner.with_agents(extraction_agent)
34
34
  result = runner.run("I love the new product features, especially the API and dashboard!")
35
35
 
36
36
  # Response will be valid JSON matching the schema:
@@ -62,7 +62,7 @@ contact_agent = Agents::Agent.new(
62
62
  response_schema: ContactSchema
63
63
  )
64
64
 
65
- runner = Agents::AgentRunner.with_agents(contact_agent)
65
+ runner = Agents::Runner.with_agents(contact_agent)
66
66
  result = runner.run("Hi, I'm Sarah Johnson from TechCorp. You can reach me at sarah@techcorp.com or 555-0123. I'm interested in AI and automation solutions.")
67
67
 
68
68
  # Returns structured contact data:
data/docs/guides.md CHANGED
@@ -17,3 +17,4 @@ Practical guides for building real-world applications with the AI Agents library
17
17
  - **[Rails Integration](guides/rails-integration.html)** - Integrating agents with Ruby on Rails applications and ActiveRecord persistence
18
18
  - **[State Persistence](guides/state-persistence.html)** - Managing conversation state and context across sessions and processes
19
19
  - **[Structured Output](guides/structured-output.html)** - Enforcing JSON schema validation for reliable agent responses
20
+ - **[Custom Request Headers](guides/request-headers.html)** - Adding custom HTTP headers for authentication, tracking, and provider-specific features
data/docs/index.md CHANGED
@@ -81,7 +81,7 @@ support = Agents::Agent.new(
81
81
  triage.register_handoffs(support)
82
82
 
83
83
  # Create runner and start conversation
84
- runner = Agents::AgentRunner.with_agents(triage, support)
84
+ runner = Agents::Runner.with_agents(triage, support)
85
85
  result = runner.run("I need help with a technical issue")
86
86
 
87
87
  puts result.output