ai-agents 0.1.0 → 0.1.2
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 +4 -4
- data/.rubocop.yml +3 -0
- data/CLAUDE.md +146 -137
- data/README.md +42 -20
- data/examples/isp-support/agents_factory.rb +66 -10
- data/examples/isp-support/interactive.rb +28 -6
- data/examples/isp-support/tools/create_checkout_tool.rb +1 -1
- data/examples/isp-support/tools/create_lead_tool.rb +19 -5
- data/examples/isp-support/tools/crm_lookup_tool.rb +14 -2
- data/examples/isp-support/tools/search_docs_tool.rb +1 -1
- data/lib/agents/agent.rb +18 -6
- data/lib/agents/agent_runner.rb +105 -0
- data/lib/agents/chat.rb +143 -0
- data/lib/agents/handoff.rb +4 -12
- data/lib/agents/runner.rb +74 -38
- data/lib/agents/tool.rb +0 -81
- data/lib/agents/tool_context.rb +36 -0
- data/lib/agents/version.rb +1 -1
- data/lib/agents.rb +14 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 004f33c8652e5b8c4d8be7bd84e959c55f6926411d3cac8bd3b3d029b7b21690
|
4
|
+
data.tar.gz: 6592c590cd91809ee47865a25adcf734370695bd4c697b1926aabc95c6e2d574
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0baadd9d0771c8e2bdd345a0a8e00bc792c6a607ec78b8796a6718e4695dc5e92b2fdc2ec11b4384c77ad409af4660be5288b020c6404750a2db5a66d1cf094c
|
7
|
+
data.tar.gz: de6edbb743e8b01634aaa12c656bc7cfa618de8086aa4e4e6add08683e8383b611856b4b9fa452c2e2e2bbd3efa2a74edefcc17af8188d2605babfc5067ecaf2
|
data/.rubocop.yml
CHANGED
data/CLAUDE.md
CHANGED
@@ -2,187 +2,196 @@
|
|
2
2
|
|
3
3
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
4
4
|
|
5
|
-
##
|
5
|
+
## Project Purpose
|
6
6
|
|
7
|
-
This is a Ruby
|
7
|
+
This project is a Ruby SDK for building multi-agent AI workflows. It allows developers to create specialized AI agents that can collaborate to solve complex tasks. The key features include:
|
8
8
|
|
9
|
-
**
|
10
|
-
-
|
11
|
-
-
|
12
|
-
-
|
9
|
+
- **Multi-Agent Orchestration**: Defining and managing multiple AI agents with distinct roles.
|
10
|
+
- **Seamless Handoffs**: Transferring conversations between agents without the user's knowledge.
|
11
|
+
- **Tool Integration**: Allowing agents to use custom tools to interact with external systems.
|
12
|
+
- **Shared Context**: Maintaining state and conversation history across agent interactions with full persistence support.
|
13
|
+
- **Thread-Safe Architecture**: Reusable agent runners that work safely across multiple threads.
|
14
|
+
- **Provider Agnostic**: Supporting various LLM providers like OpenAI, Anthropic, and Gemini.
|
13
15
|
|
14
|
-
##
|
16
|
+
## Key Technologies
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
- **Ruby**: The primary programming language.
|
19
|
+
- **RubyLLM**: The underlying library for interacting with Large Language Models.
|
20
|
+
- **RSpec**: The testing framework.
|
21
|
+
- **RuboCop**: The code style linter.
|
22
|
+
- **GitHub Actions**: For continuous integration (testing and linting).
|
20
23
|
|
21
|
-
|
22
|
-
rake spec
|
23
|
-
# OR
|
24
|
-
bundle exec rspec
|
24
|
+
## Project Structure
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
- `lib/`: The core source code of the `ai-agents` gem.
|
27
|
+
- `lib/agents.rb`: The main entry point, handling configuration and loading other components.
|
28
|
+
- `lib/agents/agent.rb`: Defines the `Agent` class, which represents an individual AI agent.
|
29
|
+
- `lib/agents/tool.rb`: Defines the `Tool` class, the base for creating custom tools for agents.
|
30
|
+
- `lib/agents/agent_runner.rb`: Thread-safe agent execution manager for multi-agent conversations.
|
31
|
+
- `lib/agents/runner.rb`: Internal orchestrator that handles individual conversation turns.
|
32
|
+
- `spec/`: Contains the RSpec tests for the project.
|
33
|
+
- `examples/`: Includes example implementations of multi-agent systems, such as an ISP customer support demo.
|
34
|
+
- `Gemfile`: Manages the project's Ruby dependencies.
|
35
|
+
- `.rubocop.yml`: Configures the code style rules for RuboCop.
|
36
|
+
- `.github/workflows/main.yml`: Defines the CI pipeline for running tests and linting on push and pull requests.
|
28
37
|
|
29
|
-
|
30
|
-
bundle exec rspec # SimpleCov will generate coverage/index.html
|
38
|
+
## Development Workflow
|
31
39
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
40
|
+
1. **Dependencies**: Managed by Bundler (`bundle install`).
|
41
|
+
2. **Testing**: Run tests with `bundle exec rspec`.
|
42
|
+
3. **Linting**: Check code style with `bundle exec rubocop`.
|
43
|
+
4. **CI/CD**: GitHub Actions automatically runs tests and linting for all pushes and pull requests to the `main` branch.
|
36
44
|
|
37
|
-
|
38
|
-
bundle exec rubocop -a
|
45
|
+
## How to Run the Example
|
39
46
|
|
40
|
-
|
41
|
-
rake
|
42
|
-
```
|
47
|
+
The project includes an interactive example of an ISP customer support system. To run it:
|
43
48
|
|
44
|
-
### Interactive Development
|
45
49
|
```bash
|
46
|
-
|
47
|
-
bin/console
|
48
|
-
|
49
|
-
# Run the airline booking demo
|
50
|
-
ruby examples/booking/interactive.rb
|
51
|
-
|
52
|
-
# Run automatic booking demo
|
53
|
-
ruby examples/booking/automatic.rb
|
50
|
+
ruby examples/isp-support/interactive.rb
|
54
51
|
```
|
55
52
|
|
56
|
-
|
53
|
+
This will start a command-line interface where you can interact with the multi-agent system. The example demonstrates:
|
54
|
+
- Thread-safe agent runner creation
|
55
|
+
- Automatic agent selection based on conversation history
|
56
|
+
- Context persistence that works across process boundaries
|
57
|
+
- Seamless handoffs between triage, sales, and support agents
|
57
58
|
|
58
|
-
|
59
|
+
## Key Concepts
|
59
60
|
|
60
|
-
**
|
61
|
+
- **Agent**: An AI assistant with a specific role, instructions, and tools.
|
62
|
+
- **Tool**: A custom function that an agent can use to perform actions (e.g., look up customer data, send an email).
|
63
|
+
- **Handoff**: The process of transferring a conversation from one agent to another. This is a core feature of the SDK.
|
64
|
+
- **AgentRunner**: The thread-safe execution manager that coordinates multi-agent conversations and provides the main API.
|
65
|
+
- **Runner**: Internal component that manages individual conversation turns (used by AgentRunner).
|
66
|
+
- **Context**: A shared state object that stores conversation history and agent information, fully serializable for persistence.
|
61
67
|
|
62
|
-
|
63
|
-
- Class-level configuration: `name`, `instructions`, `provider`, `model`, `uses`, `handoffs`
|
64
|
-
- Instance execution via `call` method with conversation history management
|
65
|
-
- Tool and handoff tool registration at runtime
|
66
|
-
- Context-aware execution with proper conversation history restoration using `chat.add_message`
|
67
|
-
- **No domain-specific logic** - remains completely generic
|
68
|
+
## Development Commands
|
68
69
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
- **Domain-agnostic** - specific tool implementations belong in user code
|
70
|
+
### Testing
|
71
|
+
```bash
|
72
|
+
# Run all tests with RSpec
|
73
|
+
bundle exec rspec
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
- `AgentResponse` - Wraps agent responses with optional handoff results
|
78
|
-
- `HandoffTool` - Generic tool for transferring between agents using context-based signaling
|
79
|
-
- **Generic handoff mechanism** - no assumptions about specific agent types
|
75
|
+
# Run tests with coverage report (uses SimpleCov)
|
76
|
+
bundle exec rake spec
|
80
77
|
|
81
|
-
|
78
|
+
# Run specific test file
|
79
|
+
bundle exec rspec spec/agents/agent_spec.rb
|
82
80
|
|
83
|
-
|
81
|
+
# Run specific test with line number
|
82
|
+
bundle exec rspec spec/agents/agent_spec.rb:25
|
83
|
+
```
|
84
84
|
|
85
|
-
###
|
85
|
+
### Code Quality
|
86
|
+
```bash
|
87
|
+
# Run RuboCop linter
|
88
|
+
bundle exec rubocop
|
86
89
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
provider :openai # Optional, defaults to configured provider
|
93
|
-
model "gpt-4o" # Optional, defaults to configured model
|
94
|
-
|
95
|
-
uses SomeTool # Register tools by class
|
96
|
-
handoffs OtherAgent, AnotherAgent # Define possible handoff targets
|
97
|
-
end
|
90
|
+
# Run RuboCop with auto-correction
|
91
|
+
bundle exec rubocop -a
|
92
|
+
|
93
|
+
# Run both tests and linting (default rake task)
|
94
|
+
bundle exec rake
|
98
95
|
```
|
99
96
|
|
100
|
-
|
101
|
-
```
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
# Tool logic should be domain-specific in user implementations
|
111
|
-
"Tool result"
|
112
|
-
end
|
113
|
-
end
|
97
|
+
### Development
|
98
|
+
```bash
|
99
|
+
# Install dependencies
|
100
|
+
bundle install
|
101
|
+
|
102
|
+
# Interactive Ruby console with gem loaded
|
103
|
+
bundle exec irb -r ./lib/agents
|
104
|
+
|
105
|
+
# Run ISP support example interactively
|
106
|
+
ruby examples/isp-support/interactive.rb
|
114
107
|
```
|
115
108
|
|
116
|
-
|
117
|
-
The handoff system uses context signaling rather than text parsing:
|
118
|
-
1. `HandoffTool` instances are created automatically from `handoffs` declarations
|
119
|
-
2. When called, `HandoffTool.perform` sets `context[:pending_handoff]`
|
120
|
-
3. `Agent.detect_handoff_from_context` checks for pending handoffs after LLM responses
|
121
|
-
4. Interactive systems handle handoffs by switching to the target agent class
|
109
|
+
## Architecture
|
122
110
|
|
123
|
-
|
124
|
-
Critical for multi-turn conversations:
|
125
|
-
- Agents maintain `@conversation_history` as array of `{user:, assistant:, timestamp:}` hashes
|
126
|
-
- `restore_conversation_history(chat)` uses `chat.add_message(role:, content:)` to restore RubyLLM chat state
|
127
|
-
- This prevents agents from "forgetting" previous conversation turns
|
111
|
+
### Core Components
|
128
112
|
|
129
|
-
|
113
|
+
- **Agents::Agent**: Individual AI agents with specific roles, instructions, and tools
|
114
|
+
- **Agents::Runner**: Orchestrates multi-agent conversations with automatic handoffs
|
115
|
+
- **Agents::Tool**: Base class for custom tools that agents can execute
|
116
|
+
- **Agents::Context**: Shared state management across agent interactions
|
117
|
+
- **Agents::Handoff**: Manages seamless transfers between agents
|
130
118
|
|
131
|
-
|
132
|
-
- Use flat naming like `class Agents::Tool` instead of nested declarations
|
133
|
-
- Follow Ruby naming conventions for agent and tool classes
|
119
|
+
### Key Design Principles
|
134
120
|
|
135
|
-
|
136
|
-
- Always write doc strings when writing functions
|
137
|
-
- Use YARD format for documentation
|
138
|
-
- Always write RDoc for new methods
|
139
|
-
- When creating a new file, start the file with a description comment on what the file has and where does it fit in the project
|
121
|
+
1. **Thread Safety**: All components are designed to be thread-safe. Tools receive context as parameters, not instance variables.
|
140
122
|
|
141
|
-
|
142
|
-
- Default model for OpenAI provider is `gpt-4.1-mini` (configured in lib/agents.rb)
|
143
|
-
- Can be overridden in agent classes or runtime configuration
|
123
|
+
2. **Immutable Agents**: Agents are configured once and can be cloned with modifications. No execution state is stored in agent instances.
|
144
124
|
|
145
|
-
|
125
|
+
3. **Provider Agnostic**: Built on RubyLLM, supports OpenAI, Anthropic, and Gemini through configuration.
|
146
126
|
|
147
|
-
**examples/booking/** - Complete airline booking demo showcasing multi-agent workflows. This is just one example of how the SDK can be used. The example demonstrates:
|
148
|
-
- Multi-agent workflow patterns
|
149
|
-
- Context sharing between agents
|
150
|
-
- Tool usage patterns
|
151
|
-
- Interactive CLI and automatic execution modes
|
152
|
-
- Proper handoff handling
|
153
127
|
|
154
|
-
|
128
|
+
### File Structure
|
155
129
|
|
156
|
-
|
130
|
+
```
|
131
|
+
lib/agents/
|
132
|
+
├── agent.rb # Core agent definition and configuration
|
133
|
+
├── agent_runner.rb # Thread-safe execution manager (main API)
|
134
|
+
├── runner.rb # Internal execution engine for conversation turns
|
135
|
+
├── tool.rb # Base class for custom tools
|
136
|
+
├── handoff.rb # Agent handoff management
|
137
|
+
├── chat.rb # Chat message handling
|
138
|
+
├── result.rb # Result object for agent responses
|
139
|
+
├── run_context.rb # Execution context management
|
140
|
+
├── tool_context.rb # Tool execution context
|
141
|
+
├── tool_wrapper.rb # Thread-safe tool wrapping
|
142
|
+
└── version.rb # Gem version
|
143
|
+
```
|
157
144
|
|
158
|
-
|
159
|
-
- Agents SDK configures RubyLLM automatically via `Agents.configure`
|
160
|
-
- Tools inherit from `RubyLLM::Tool` but use enhanced `perform` method
|
161
|
-
- Conversation history restored using `chat.add_message`
|
162
|
-
- Debug mode available via `ENV["RUBYLLM_DEBUG"] = "true"`
|
145
|
+
### Configuration
|
163
146
|
|
164
|
-
|
147
|
+
The SDK requires at least one LLM provider API key:
|
165
148
|
|
166
|
-
|
149
|
+
```ruby
|
150
|
+
Agents.configure do |config|
|
151
|
+
config.openai_api_key = ENV['OPENAI_API_KEY']
|
152
|
+
config.anthropic_api_key = ENV['ANTHROPIC_API_KEY']
|
153
|
+
config.gemini_api_key = ENV['GEMINI_API_KEY']
|
154
|
+
config.default_model = 'gpt-4o-mini'
|
155
|
+
config.debug = true
|
156
|
+
end
|
157
|
+
```
|
167
158
|
|
168
|
-
|
159
|
+
### Basic Usage Pattern
|
169
160
|
|
170
|
-
|
161
|
+
```ruby
|
162
|
+
# Create agents with handoff relationships
|
163
|
+
triage = Agent.new(name: "Triage", instructions: "Route users...")
|
164
|
+
billing = Agent.new(name: "Billing", instructions: "Handle billing...")
|
165
|
+
support = Agent.new(name: "Support", instructions: "Technical support...")
|
166
|
+
|
167
|
+
triage.register_handoffs(billing, support)
|
168
|
+
|
169
|
+
# Create thread-safe runner (first agent is default entry point)
|
170
|
+
runner = Agents::Runner.with_agents(triage, billing, support)
|
171
|
+
|
172
|
+
# Use for conversations - automatically handles agent selection and persistence
|
173
|
+
result = runner.run("I have a billing question")
|
174
|
+
result = runner.run("What about technical support?", context: result.context)
|
175
|
+
```
|
171
176
|
|
172
|
-
|
177
|
+
### Tool Development
|
173
178
|
|
174
|
-
|
179
|
+
When creating custom tools:
|
180
|
+
- Extend `Agents::Tool`
|
181
|
+
- Use `tool_context` parameter for all state
|
182
|
+
- Never store execution state in instance variables
|
183
|
+
- Follow the thread-safe design pattern shown in examples
|
175
184
|
|
176
|
-
|
185
|
+
### Testing Strategy
|
177
186
|
|
178
|
-
|
187
|
+
- SimpleCov tracks coverage with 50% minimum overall, 40% per file
|
188
|
+
- WebMock is used for HTTP mocking in tests
|
189
|
+
- RSpec is the testing framework with standard configuration
|
190
|
+
- Tests are organized by component in `spec/agents/`
|
179
191
|
|
180
|
-
###
|
192
|
+
### Examples
|
181
193
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
4. Never use `receive_message_chain`
|
187
|
-
5. When writing tests, always use verifying doubles and never normal doubles
|
188
|
-
```
|
194
|
+
The `examples/` directory contains complete working examples:
|
195
|
+
- `isp-support/`: Multi-agent ISP customer support system
|
196
|
+
- Shows hub-and-spoke architecture patterns
|
197
|
+
- Demonstrates tool integration and handoff workflows
|
data/README.md
CHANGED
@@ -40,15 +40,18 @@ Agents.configure do |config|
|
|
40
40
|
config.openai_api_key = ENV['OPENAI_API_KEY']
|
41
41
|
end
|
42
42
|
|
43
|
-
# Create
|
44
|
-
|
43
|
+
# Create agents
|
44
|
+
weather_agent = Agents::Agent.new(
|
45
45
|
name: "Weather Assistant",
|
46
46
|
instructions: "Help users get weather information",
|
47
47
|
tools: [WeatherTool.new]
|
48
48
|
)
|
49
49
|
|
50
|
-
#
|
51
|
-
|
50
|
+
# Create a thread-safe runner (reusable across conversations)
|
51
|
+
runner = Agents::Runner.with_agents(weather_agent)
|
52
|
+
|
53
|
+
# Use the runner for conversations
|
54
|
+
result = runner.run("What's the weather like today?")
|
52
55
|
puts result.output
|
53
56
|
```
|
54
57
|
|
@@ -64,14 +67,14 @@ triage = Agents::Agent.new(
|
|
64
67
|
)
|
65
68
|
|
66
69
|
faq = Agents::Agent.new(
|
67
|
-
name: "FAQ Agent",
|
70
|
+
name: "FAQ Agent",
|
68
71
|
instructions: "Answer frequently asked questions",
|
69
72
|
tools: [FaqLookupTool.new]
|
70
73
|
)
|
71
74
|
|
72
75
|
support = Agents::Agent.new(
|
73
76
|
name: "Support Agent",
|
74
|
-
instructions: "Handle technical issues",
|
77
|
+
instructions: "Handle technical issues",
|
75
78
|
tools: [TicketTool.new]
|
76
79
|
)
|
77
80
|
|
@@ -80,9 +83,16 @@ triage.register_handoffs(faq, support)
|
|
80
83
|
faq.register_handoffs(triage) # Can route back to triage
|
81
84
|
support.register_handoffs(triage) # Hub-and-spoke pattern
|
82
85
|
|
83
|
-
#
|
84
|
-
|
86
|
+
# Create runner with all agents (triage is default entry point)
|
87
|
+
runner = Agents::Runner.with_agents(triage, faq, support)
|
88
|
+
|
89
|
+
# Run conversations with automatic handoffs and persistence
|
90
|
+
result = runner.run("How many seats are on the plane?")
|
85
91
|
# User gets direct answer from FAQ agent without knowing about the handoff!
|
92
|
+
|
93
|
+
# Continue the conversation seamlessly
|
94
|
+
result = runner.run("What about technical support?", context: result.context)
|
95
|
+
# Context automatically tracks conversation history and current agent
|
86
96
|
```
|
87
97
|
|
88
98
|
## 🏗️ Architecture
|
@@ -90,8 +100,9 @@ result = Agents::Runner.run(triage, "How many seats are on the plane?")
|
|
90
100
|
### Core Components
|
91
101
|
|
92
102
|
- **Agent**: Individual AI agents with specific roles and capabilities
|
93
|
-
- **
|
94
|
-
- **
|
103
|
+
- **AgentRunner**: Thread-safe execution manager for multi-agent conversations
|
104
|
+
- **Runner**: Internal orchestrator that handles conversation turns (used by AgentRunner)
|
105
|
+
- **Context**: Shared state management with automatic persistence across agents
|
95
106
|
- **Tools**: Custom functions that agents can use
|
96
107
|
- **Handoffs**: Seamless transfers between specialized agents
|
97
108
|
|
@@ -134,11 +145,11 @@ end
|
|
134
145
|
```ruby
|
135
146
|
class EmailTool < Agents::Tool
|
136
147
|
description "Send emails to customers"
|
137
|
-
param :to,
|
138
|
-
param :subject,
|
139
|
-
param :body,
|
148
|
+
param :to, type: "string", desc: "Email address"
|
149
|
+
param :subject, type: "string", desc: "Email subject"
|
150
|
+
param :body, type: "string", desc: "Email body"
|
140
151
|
|
141
|
-
def perform(to:, subject:, body
|
152
|
+
def perform(tool_context, to:, subject:, body:)
|
142
153
|
# Send email logic here
|
143
154
|
"Email sent to #{to}"
|
144
155
|
end
|
@@ -175,16 +186,27 @@ sales.register_handoffs(customer_info)
|
|
175
186
|
customer_info.register_handoffs(sales)
|
176
187
|
```
|
177
188
|
|
178
|
-
### Context Management
|
189
|
+
### Context Management & Persistence
|
179
190
|
|
180
191
|
```ruby
|
181
|
-
# Context is automatically managed
|
182
|
-
|
183
|
-
result = Agents::Runner.run(agent, "Hello", context: context)
|
192
|
+
# Context is automatically managed and serializable
|
193
|
+
runner = Agents::Runner.with_agents(triage, billing, support)
|
184
194
|
|
185
|
-
#
|
195
|
+
# Start a conversation
|
196
|
+
result = runner.run("I need billing help")
|
197
|
+
|
198
|
+
# Context is automatically updated with conversation history and current agent
|
199
|
+
context = result.context
|
186
200
|
puts context[:conversation_history]
|
187
|
-
puts context[:current_agent]
|
201
|
+
puts context[:current_agent] # Agent name (string), not object!
|
202
|
+
|
203
|
+
# Serialize context for persistence (Rails, databases, etc.)
|
204
|
+
json_context = JSON.dump(context) # ✅ Works! No object references
|
205
|
+
|
206
|
+
# Later: restore and continue conversation
|
207
|
+
restored_context = JSON.parse(json_context, symbolize_names: true)
|
208
|
+
result = runner.run("Actually, I need technical support too", context: restored_context)
|
209
|
+
# System automatically determines correct agent from conversation history
|
188
210
|
```
|
189
211
|
|
190
212
|
## 📋 Examples
|
@@ -48,11 +48,10 @@ module ISPSupport
|
|
48
48
|
)
|
49
49
|
end
|
50
50
|
|
51
|
-
|
52
51
|
def create_sales_agent
|
53
52
|
Agents::Agent.new(
|
54
53
|
name: "Sales Agent",
|
55
|
-
instructions:
|
54
|
+
instructions: sales_instructions_with_state,
|
56
55
|
model: "gpt-4.1-mini",
|
57
56
|
tools: [ISPSupport::CreateLeadTool.new, ISPSupport::CreateCheckoutTool.new]
|
58
57
|
)
|
@@ -65,7 +64,7 @@ module ISPSupport
|
|
65
64
|
model: "gpt-4.1-mini",
|
66
65
|
tools: [
|
67
66
|
ISPSupport::CrmLookupTool.new,
|
68
|
-
ISPSupport::SearchDocsTool.new,
|
67
|
+
ISPSupport::SearchDocsTool.new,
|
69
68
|
ISPSupport::EscalateToHumanTool.new
|
70
69
|
]
|
71
70
|
)
|
@@ -89,7 +88,6 @@ module ISPSupport
|
|
89
88
|
INSTRUCTIONS
|
90
89
|
end
|
91
90
|
|
92
|
-
|
93
91
|
def sales_instructions
|
94
92
|
<<~INSTRUCTIONS
|
95
93
|
You are the Sales Agent for an ISP. You handle new customer acquisition, service upgrades,
|
@@ -101,19 +99,76 @@ module ISPSupport
|
|
101
99
|
- Handoff tools: Route back to triage when needed
|
102
100
|
|
103
101
|
**When to hand off:**
|
104
|
-
-
|
105
|
-
-
|
106
|
-
- Non-sales requests → Triage Agent
|
102
|
+
- Pure technical support questions → Triage Agent for re-routing
|
103
|
+
- Customer needs to speak with human agent → Triage Agent for re-routing
|
107
104
|
|
108
105
|
**Instructions:**
|
109
106
|
- Be enthusiastic but not pushy
|
110
107
|
- Gather required info: name, email, desired plan for leads
|
111
|
-
- For
|
108
|
+
- For account verification, ask customer for their account details directly
|
109
|
+
- For existing customers wanting upgrades, collect account info and proceed
|
112
110
|
- Create checkout links for confirmed purchases
|
113
111
|
- Always explain next steps after creating leads or checkout links
|
112
|
+
- Handle billing questions yourself - don't hand off for account verification
|
114
113
|
INSTRUCTIONS
|
115
114
|
end
|
116
115
|
|
116
|
+
def sales_instructions_with_state
|
117
|
+
lambda { |context|
|
118
|
+
state = context.context[:state] || {}
|
119
|
+
|
120
|
+
base_instructions = <<~INSTRUCTIONS
|
121
|
+
You are the Sales Agent for an ISP. You handle new customer acquisition, service upgrades,
|
122
|
+
and plan changes.
|
123
|
+
|
124
|
+
**Your tools:**
|
125
|
+
- `create_lead`: Create sales leads with customer information
|
126
|
+
- `create_checkout`: Generate secure checkout links for purchases
|
127
|
+
- Handoff tools: Route back to triage when needed
|
128
|
+
|
129
|
+
**When to hand off:**
|
130
|
+
- Pure technical support questions → Triage Agent for re-routing
|
131
|
+
- Customer needs to speak with human agent → Triage Agent for re-routing
|
132
|
+
INSTRUCTIONS
|
133
|
+
|
134
|
+
# Add customer context if available from previous agent interactions
|
135
|
+
if state[:customer_name] && state[:customer_id]
|
136
|
+
base_instructions += <<~CONTEXT
|
137
|
+
|
138
|
+
**Customer Context Available:**
|
139
|
+
- Customer Name: #{state[:customer_name]}
|
140
|
+
- Customer ID: #{state[:customer_id]}
|
141
|
+
- Email: #{state[:customer_email]}
|
142
|
+
- Phone: #{state[:customer_phone]}
|
143
|
+
- Address: #{state[:customer_address]}
|
144
|
+
#{state[:current_plan] ? "- Current Plan: #{state[:current_plan]}" : ""}
|
145
|
+
#{state[:account_status] ? "- Account Status: #{state[:account_status]}" : ""}
|
146
|
+
#{state[:monthly_usage] ? "- Monthly Usage: #{state[:monthly_usage]}GB" : ""}
|
147
|
+
|
148
|
+
**IMPORTANT:**#{" "}
|
149
|
+
- Use this existing customer information when creating leads or providing service
|
150
|
+
- Do NOT ask for name, email, phone, or address - you already have these details
|
151
|
+
- For new connections, use the existing customer details and only ask for the desired plan
|
152
|
+
- Provide personalized recommendations based on their current information
|
153
|
+
CONTEXT
|
154
|
+
end
|
155
|
+
|
156
|
+
base_instructions += <<~FINAL_INSTRUCTIONS
|
157
|
+
|
158
|
+
**Instructions:**
|
159
|
+
- Be enthusiastic but not pushy
|
160
|
+
- Gather required info: name, email, desired plan for leads
|
161
|
+
- For account verification, ask customer for their account details directly
|
162
|
+
- For existing customers wanting upgrades, collect account info and proceed
|
163
|
+
- Create checkout links for confirmed purchases
|
164
|
+
- Always explain next steps after creating leads or checkout links
|
165
|
+
- Handle billing questions yourself - don't hand off for account verification
|
166
|
+
FINAL_INSTRUCTIONS
|
167
|
+
|
168
|
+
base_instructions
|
169
|
+
}
|
170
|
+
end
|
171
|
+
|
117
172
|
def support_instructions
|
118
173
|
<<~INSTRUCTIONS
|
119
174
|
You are the Support Agent for an ISP. You handle technical support, troubleshooting,
|
@@ -126,8 +181,8 @@ module ISPSupport
|
|
126
181
|
- Handoff tools: Route back to triage when needed
|
127
182
|
|
128
183
|
**When to hand off:**
|
129
|
-
- Customer wants to buy
|
130
|
-
-
|
184
|
+
- Customer wants to buy new service or upgrade plans → Triage Agent to route to Sales
|
185
|
+
- Complex issues requiring human intervention → Use escalate_to_human tool instead
|
131
186
|
|
132
187
|
**Instructions:**
|
133
188
|
- For account questions: Always ask for account ID and use crm_lookup
|
@@ -136,6 +191,7 @@ module ISPSupport
|
|
136
191
|
- Be patient and provide step-by-step guidance
|
137
192
|
- If customer gets frustrated or issue persists, escalate to human
|
138
193
|
- Present account information clearly and protect sensitive data
|
194
|
+
- Handle account verification requests directly - don't hand off back to triage
|
139
195
|
INSTRUCTIONS
|
140
196
|
end
|
141
197
|
end
|