robot_lab 0.0.1

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.
Files changed (153) hide show
  1. checksums.yaml +7 -0
  2. data/.envrc +1 -0
  3. data/.github/workflows/deploy-github-pages.yml +52 -0
  4. data/.github/workflows/deploy-yard-docs.yml +52 -0
  5. data/CHANGELOG.md +55 -0
  6. data/COMMITS.md +196 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +332 -0
  9. data/Rakefile +67 -0
  10. data/docs/api/adapters/anthropic.md +121 -0
  11. data/docs/api/adapters/gemini.md +133 -0
  12. data/docs/api/adapters/index.md +104 -0
  13. data/docs/api/adapters/openai.md +134 -0
  14. data/docs/api/core/index.md +113 -0
  15. data/docs/api/core/memory.md +314 -0
  16. data/docs/api/core/network.md +291 -0
  17. data/docs/api/core/robot.md +273 -0
  18. data/docs/api/core/state.md +273 -0
  19. data/docs/api/core/tool.md +353 -0
  20. data/docs/api/history/active-record-adapter.md +195 -0
  21. data/docs/api/history/config.md +191 -0
  22. data/docs/api/history/index.md +132 -0
  23. data/docs/api/history/thread-manager.md +144 -0
  24. data/docs/api/index.md +82 -0
  25. data/docs/api/mcp/client.md +221 -0
  26. data/docs/api/mcp/index.md +111 -0
  27. data/docs/api/mcp/server.md +225 -0
  28. data/docs/api/mcp/transports.md +264 -0
  29. data/docs/api/messages/index.md +67 -0
  30. data/docs/api/messages/text-message.md +102 -0
  31. data/docs/api/messages/tool-call-message.md +144 -0
  32. data/docs/api/messages/tool-result-message.md +154 -0
  33. data/docs/api/messages/user-message.md +171 -0
  34. data/docs/api/streaming/context.md +174 -0
  35. data/docs/api/streaming/events.md +237 -0
  36. data/docs/api/streaming/index.md +108 -0
  37. data/docs/architecture/core-concepts.md +243 -0
  38. data/docs/architecture/index.md +138 -0
  39. data/docs/architecture/message-flow.md +320 -0
  40. data/docs/architecture/network-orchestration.md +216 -0
  41. data/docs/architecture/robot-execution.md +243 -0
  42. data/docs/architecture/state-management.md +323 -0
  43. data/docs/assets/css/custom.css +56 -0
  44. data/docs/assets/images/robot_lab.jpg +0 -0
  45. data/docs/concepts.md +216 -0
  46. data/docs/examples/basic-chat.md +193 -0
  47. data/docs/examples/index.md +129 -0
  48. data/docs/examples/mcp-server.md +290 -0
  49. data/docs/examples/multi-robot-network.md +312 -0
  50. data/docs/examples/rails-application.md +420 -0
  51. data/docs/examples/tool-usage.md +310 -0
  52. data/docs/getting-started/configuration.md +230 -0
  53. data/docs/getting-started/index.md +56 -0
  54. data/docs/getting-started/installation.md +179 -0
  55. data/docs/getting-started/quick-start.md +203 -0
  56. data/docs/guides/building-robots.md +376 -0
  57. data/docs/guides/creating-networks.md +366 -0
  58. data/docs/guides/history.md +359 -0
  59. data/docs/guides/index.md +68 -0
  60. data/docs/guides/mcp-integration.md +356 -0
  61. data/docs/guides/memory.md +309 -0
  62. data/docs/guides/rails-integration.md +432 -0
  63. data/docs/guides/streaming.md +314 -0
  64. data/docs/guides/using-tools.md +394 -0
  65. data/docs/index.md +160 -0
  66. data/examples/01_simple_robot.rb +38 -0
  67. data/examples/02_tools.rb +106 -0
  68. data/examples/03_network.rb +103 -0
  69. data/examples/04_mcp.rb +219 -0
  70. data/examples/05_streaming.rb +124 -0
  71. data/examples/06_prompt_templates.rb +324 -0
  72. data/examples/07_network_memory.rb +329 -0
  73. data/examples/prompts/assistant/system.txt.erb +2 -0
  74. data/examples/prompts/assistant/user.txt.erb +1 -0
  75. data/examples/prompts/billing/system.txt.erb +7 -0
  76. data/examples/prompts/billing/user.txt.erb +1 -0
  77. data/examples/prompts/classifier/system.txt.erb +4 -0
  78. data/examples/prompts/classifier/user.txt.erb +1 -0
  79. data/examples/prompts/entity_extractor/system.txt.erb +11 -0
  80. data/examples/prompts/entity_extractor/user.txt.erb +3 -0
  81. data/examples/prompts/escalation/system.txt.erb +35 -0
  82. data/examples/prompts/escalation/user.txt.erb +34 -0
  83. data/examples/prompts/general/system.txt.erb +4 -0
  84. data/examples/prompts/general/user.txt.erb +1 -0
  85. data/examples/prompts/github_assistant/system.txt.erb +6 -0
  86. data/examples/prompts/github_assistant/user.txt.erb +1 -0
  87. data/examples/prompts/helper/system.txt.erb +1 -0
  88. data/examples/prompts/helper/user.txt.erb +1 -0
  89. data/examples/prompts/keyword_extractor/system.txt.erb +8 -0
  90. data/examples/prompts/keyword_extractor/user.txt.erb +3 -0
  91. data/examples/prompts/order_support/system.txt.erb +27 -0
  92. data/examples/prompts/order_support/user.txt.erb +22 -0
  93. data/examples/prompts/product_support/system.txt.erb +30 -0
  94. data/examples/prompts/product_support/user.txt.erb +32 -0
  95. data/examples/prompts/sentiment_analyzer/system.txt.erb +9 -0
  96. data/examples/prompts/sentiment_analyzer/user.txt.erb +3 -0
  97. data/examples/prompts/synthesizer/system.txt.erb +14 -0
  98. data/examples/prompts/synthesizer/user.txt.erb +15 -0
  99. data/examples/prompts/technical/system.txt.erb +7 -0
  100. data/examples/prompts/technical/user.txt.erb +1 -0
  101. data/examples/prompts/triage/system.txt.erb +16 -0
  102. data/examples/prompts/triage/user.txt.erb +17 -0
  103. data/lib/generators/robot_lab/install_generator.rb +78 -0
  104. data/lib/generators/robot_lab/robot_generator.rb +55 -0
  105. data/lib/generators/robot_lab/templates/initializer.rb.tt +41 -0
  106. data/lib/generators/robot_lab/templates/migration.rb.tt +32 -0
  107. data/lib/generators/robot_lab/templates/result_model.rb.tt +52 -0
  108. data/lib/generators/robot_lab/templates/robot.rb.tt +46 -0
  109. data/lib/generators/robot_lab/templates/robot_test.rb.tt +32 -0
  110. data/lib/generators/robot_lab/templates/routing_robot.rb.tt +53 -0
  111. data/lib/generators/robot_lab/templates/thread_model.rb.tt +40 -0
  112. data/lib/robot_lab/adapters/anthropic.rb +163 -0
  113. data/lib/robot_lab/adapters/base.rb +85 -0
  114. data/lib/robot_lab/adapters/gemini.rb +193 -0
  115. data/lib/robot_lab/adapters/openai.rb +159 -0
  116. data/lib/robot_lab/adapters/registry.rb +81 -0
  117. data/lib/robot_lab/configuration.rb +143 -0
  118. data/lib/robot_lab/error.rb +32 -0
  119. data/lib/robot_lab/errors.rb +70 -0
  120. data/lib/robot_lab/history/active_record_adapter.rb +146 -0
  121. data/lib/robot_lab/history/config.rb +115 -0
  122. data/lib/robot_lab/history/thread_manager.rb +93 -0
  123. data/lib/robot_lab/mcp/client.rb +210 -0
  124. data/lib/robot_lab/mcp/server.rb +84 -0
  125. data/lib/robot_lab/mcp/transports/base.rb +56 -0
  126. data/lib/robot_lab/mcp/transports/sse.rb +117 -0
  127. data/lib/robot_lab/mcp/transports/stdio.rb +133 -0
  128. data/lib/robot_lab/mcp/transports/streamable_http.rb +139 -0
  129. data/lib/robot_lab/mcp/transports/websocket.rb +108 -0
  130. data/lib/robot_lab/memory.rb +882 -0
  131. data/lib/robot_lab/memory_change.rb +123 -0
  132. data/lib/robot_lab/message.rb +357 -0
  133. data/lib/robot_lab/network.rb +350 -0
  134. data/lib/robot_lab/rails/engine.rb +29 -0
  135. data/lib/robot_lab/rails/railtie.rb +42 -0
  136. data/lib/robot_lab/robot.rb +560 -0
  137. data/lib/robot_lab/robot_result.rb +205 -0
  138. data/lib/robot_lab/robotic_model.rb +324 -0
  139. data/lib/robot_lab/state_proxy.rb +188 -0
  140. data/lib/robot_lab/streaming/context.rb +144 -0
  141. data/lib/robot_lab/streaming/events.rb +95 -0
  142. data/lib/robot_lab/streaming/sequence_counter.rb +48 -0
  143. data/lib/robot_lab/task.rb +117 -0
  144. data/lib/robot_lab/tool.rb +223 -0
  145. data/lib/robot_lab/tool_config.rb +112 -0
  146. data/lib/robot_lab/tool_manifest.rb +234 -0
  147. data/lib/robot_lab/user_message.rb +118 -0
  148. data/lib/robot_lab/version.rb +5 -0
  149. data/lib/robot_lab/waiter.rb +73 -0
  150. data/lib/robot_lab.rb +195 -0
  151. data/mkdocs.yml +214 -0
  152. data/sig/robot_lab.rbs +4 -0
  153. metadata +442 -0
@@ -0,0 +1,329 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example 7: Network Memory with Concurrent Robots
5
+ #
6
+ # Demonstrates the reactive shared memory system where:
7
+ # - Multiple robots run concurrently and write to shared memory
8
+ # - Robots can wait for values written by other robots
9
+ # - Subscriptions provide real-time notifications of memory changes
10
+ # - Network broadcast sends messages to all robots
11
+ #
12
+ # Architecture:
13
+ # ┌─────────────────────────────────────────────────────────────┐
14
+ # │ PARALLEL ANALYSIS │
15
+ # │ │
16
+ # │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
17
+ # │ │ Sentiment │ │ Entities │ │ Keywords │ │
18
+ # │ │ Analyzer │ │ Extractor │ │ Extractor │ │
19
+ # │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
20
+ # │ │ │ │ │
21
+ # │ ▼ ▼ ▼ │
22
+ # │ memory.set( memory.set( memory.set( │
23
+ # │ :sentiment) :entities) :keywords) │
24
+ # │ │ │ │ │
25
+ # │ └────────────────┼────────────────┘ │
26
+ # │ ▼ │
27
+ # │ ┌──────────────────────────────────────────────────────┐ │
28
+ # │ │ SHARED MEMORY │ │
29
+ # │ │ { sentiment: {...}, entities: {...}, keywords: {...} │ │
30
+ # │ └──────────────────────────────────────────────────────┘ │
31
+ # │ │ │
32
+ # │ ▼ │
33
+ # │ ┌──────────────────────────────────────────────────────┐ │
34
+ # │ │ Synthesizer │ │
35
+ # │ │ memory.get(:sentiment, :entities, :keywords, │ │
36
+ # │ │ wait: true) │ │
37
+ # │ └──────────────────────────────────────────────────────┘ │
38
+ # │ │
39
+ # └─────────────────────────────────────────────────────────────┘
40
+ #
41
+ # Usage:
42
+ # ANTHROPIC_API_KEY=your_key ruby examples/07_network_memory.rb
43
+
44
+ require_relative "../lib/robot_lab"
45
+ require "json"
46
+
47
+ # Configure RobotLab
48
+ RobotLab.configure do |config|
49
+ config.anthropic_api_key = ENV.fetch("ANTHROPIC_API_KEY", nil)
50
+ config.template_path = File.join(__dir__, "prompts")
51
+ end
52
+
53
+ puts "=" * 60
54
+ puts "Example 7: Network Memory with Concurrent Robots"
55
+ puts "=" * 60
56
+ puts
57
+
58
+ # -----------------------------------------------------------------------------
59
+ # Custom Robot Classes that Write to Shared Memory
60
+ # -----------------------------------------------------------------------------
61
+
62
+ # Base class for analysis robots that write results to memory
63
+ class AnalysisRobot < RobotLab::Robot
64
+ def initialize(memory_key:, **opts)
65
+ super(**opts)
66
+ @memory_key = memory_key
67
+ end
68
+
69
+ def call(result)
70
+ run_context = extract_run_context(result)
71
+ network_memory = run_context.delete(:network_memory)
72
+
73
+ robot_result = run(network_memory: network_memory, **run_context)
74
+
75
+ # Parse the JSON response and write to shared memory
76
+ if network_memory
77
+ content = robot_result.last_text_content.to_s
78
+
79
+ # Set writer before writing to memory
80
+ network_memory.current_writer = @name
81
+
82
+ begin
83
+ parsed = JSON.parse(content)
84
+ network_memory.set(@memory_key, parsed)
85
+ puts " [#{@name}] Wrote JSON to memory[:#{@memory_key}]"
86
+ rescue JSON::ParserError
87
+ # If not valid JSON, store the raw text
88
+ network_memory.set(@memory_key, content)
89
+ puts " [#{@name}] Wrote text to memory[:#{@memory_key}]"
90
+ end
91
+ end
92
+
93
+ result
94
+ .with_context(@name.to_sym, robot_result)
95
+ .continue(robot_result)
96
+ end
97
+ end
98
+
99
+ # Synthesizer robot that reads from shared memory and synthesizes results
100
+ class SynthesizerRobot < RobotLab::Robot
101
+ def call(result)
102
+ run_context = extract_run_context(result)
103
+ network_memory = run_context.delete(:network_memory)
104
+
105
+ puts " [#{@name}] Reading analysis results from memory..."
106
+
107
+ if network_memory
108
+ # Read results from memory - they should already be there since
109
+ # SimpleFlow ensures our dependencies completed first
110
+ sentiment = network_memory.get(:sentiment)
111
+ entities = network_memory.get(:entities)
112
+ keywords = network_memory.get(:keywords)
113
+
114
+ puts " [#{@name}] Got sentiment: #{sentiment.nil? ? 'nil' : 'present'}"
115
+ puts " [#{@name}] Got entities: #{entities.nil? ? 'nil' : 'present'}"
116
+ puts " [#{@name}] Got keywords: #{keywords.nil? ? 'nil' : 'present'}"
117
+
118
+ # Format for the template
119
+ run_context[:sentiment] = format_for_template(sentiment)
120
+ run_context[:entities] = format_for_template(entities)
121
+ run_context[:keywords] = format_for_template(keywords)
122
+ else
123
+ run_context[:sentiment] = "Not available"
124
+ run_context[:entities] = "Not available"
125
+ run_context[:keywords] = "Not available"
126
+ end
127
+
128
+ robot_result = run(network_memory: network_memory, **run_context)
129
+
130
+ result
131
+ .with_context(@name.to_sym, robot_result)
132
+ .continue(robot_result)
133
+ end
134
+
135
+ private
136
+
137
+ def format_for_template(value)
138
+ case value
139
+ when Hash, Array
140
+ JSON.pretty_generate(value)
141
+ when nil
142
+ "Not available"
143
+ else
144
+ value.to_s
145
+ end
146
+ end
147
+ end
148
+
149
+ # -----------------------------------------------------------------------------
150
+ # Create the Robots
151
+ # -----------------------------------------------------------------------------
152
+
153
+ sentiment_robot = AnalysisRobot.new(
154
+ name: "sentiment_analyzer",
155
+ template: :sentiment_analyzer,
156
+ memory_key: :sentiment,
157
+ model: "claude-sonnet-4"
158
+ )
159
+
160
+ entity_robot = AnalysisRobot.new(
161
+ name: "entity_extractor",
162
+ template: :entity_extractor,
163
+ memory_key: :entities,
164
+ model: "claude-sonnet-4"
165
+ )
166
+
167
+ keyword_robot = AnalysisRobot.new(
168
+ name: "keyword_extractor",
169
+ template: :keyword_extractor,
170
+ memory_key: :keywords,
171
+ model: "claude-sonnet-4"
172
+ )
173
+
174
+ synthesizer = SynthesizerRobot.new(
175
+ name: "synthesizer",
176
+ template: :synthesizer,
177
+ model: "claude-sonnet-4"
178
+ )
179
+
180
+ # -----------------------------------------------------------------------------
181
+ # Create the Network with Shared Memory
182
+ # -----------------------------------------------------------------------------
183
+
184
+ network = RobotLab.create_network(name: "parallel_analysis") do
185
+ # Three analysis robots run in parallel (all depend on nothing)
186
+ task :sentiment, sentiment_robot, depends_on: :none
187
+ task :entities, entity_robot, depends_on: :none
188
+ task :keywords, keyword_robot, depends_on: :none
189
+
190
+ # Synthesizer waits for all three to complete
191
+ task :synthesize, synthesizer, depends_on: [:sentiment, :entities, :keywords]
192
+ end
193
+
194
+ # -----------------------------------------------------------------------------
195
+ # Set Up Memory Subscriptions (for monitoring)
196
+ # -----------------------------------------------------------------------------
197
+
198
+ puts "Setting up memory subscriptions for monitoring..."
199
+ puts
200
+
201
+ # Note: In concurrent execution, change.writer may be unreliable due to race
202
+ # conditions. For production use, consider including writer info in the value.
203
+ network.memory.subscribe(:sentiment, :entities, :keywords) do |change|
204
+ value_preview = case change.value
205
+ when Hash then change.value.keys.join(", ")
206
+ when String then change.value[0..50]
207
+ else change.value.class.name
208
+ end
209
+ puts " [MONITOR] Memory[:#{change.key}] updated with keys: #{value_preview}"
210
+ end
211
+
212
+ # -----------------------------------------------------------------------------
213
+ # Set Up Broadcast Handler
214
+ # -----------------------------------------------------------------------------
215
+
216
+ network.on_broadcast do |message|
217
+ puts " [BROADCAST] #{message[:payload][:event]}: #{message[:payload][:details]}"
218
+ end
219
+
220
+ # -----------------------------------------------------------------------------
221
+ # Run the Network
222
+ # -----------------------------------------------------------------------------
223
+
224
+ sample_text = <<~TEXT
225
+ Apple Inc. announced today that CEO Tim Cook will be presenting the new iPhone 15
226
+ at their headquarters in Cupertino, California on September 12th, 2024.
227
+ Industry analysts are extremely excited about the new features, though some
228
+ consumer advocates have expressed concerns about the expected price increase.
229
+ Samsung and Google are reportedly preparing competitive responses for later this year.
230
+ TEXT
231
+
232
+ puts "Network structure:"
233
+ puts network.visualize
234
+ puts
235
+ puts "-" * 60
236
+ puts "Input text:"
237
+ puts sample_text.strip
238
+ puts "-" * 60
239
+ puts
240
+
241
+ # Send a broadcast before starting
242
+ network.broadcast(event: "analysis_started", details: "Beginning parallel analysis")
243
+
244
+ puts "Running parallel analysis..."
245
+ puts
246
+ start_time = Time.now
247
+
248
+ result = network.run(message: sample_text)
249
+
250
+ elapsed = Time.now - start_time
251
+ puts
252
+ puts "-" * 60
253
+ puts "Analysis complete in #{elapsed.round(2)} seconds"
254
+ puts "-" * 60
255
+
256
+ # Send completion broadcast
257
+ network.broadcast(event: "analysis_complete", details: "All robots finished")
258
+
259
+ # -----------------------------------------------------------------------------
260
+ # Display Results
261
+ # -----------------------------------------------------------------------------
262
+
263
+ puts
264
+ puts "=" * 60
265
+ puts "FINAL SYNTHESIS"
266
+ puts "=" * 60
267
+ puts
268
+
269
+ if result.value.is_a?(RobotLab::RobotResult)
270
+ puts result.value.last_text_content
271
+ end
272
+
273
+ puts
274
+ puts "=" * 60
275
+ puts "MEMORY STATE"
276
+ puts "=" * 60
277
+ puts
278
+
279
+ # Show what's in shared memory
280
+ memory = network.memory
281
+ puts "Sentiment: #{memory.get(:sentiment)&.to_json}"
282
+ puts
283
+ puts "Entities: #{memory.get(:entities)&.to_json}"
284
+ puts
285
+ puts "Keywords: #{memory.get(:keywords)&.to_json}"
286
+
287
+ # -----------------------------------------------------------------------------
288
+ # Demonstrate Blocking Wait (without pipeline dependencies)
289
+ # -----------------------------------------------------------------------------
290
+
291
+ puts
292
+ puts "=" * 60
293
+ puts "DEMONSTRATING BLOCKING WAIT"
294
+ puts "=" * 60
295
+ puts
296
+
297
+ # Create a fresh memory for this demo
298
+ demo_memory = RobotLab::Memory.new(network_name: "wait_demo")
299
+
300
+ # Simulate a concurrent scenario where one thread waits for another
301
+ puts "Starting writer thread (will write after 1 second)..."
302
+ puts "Starting reader thread (will wait for value)..."
303
+
304
+ reader_result = nil
305
+ writer_done = false
306
+
307
+ reader = Thread.new do
308
+ start = Time.now
309
+ puts " [reader] Waiting for :delayed_result..."
310
+ value = demo_memory.get(:delayed_result, wait: 10)
311
+ elapsed = Time.now - start
312
+ reader_result = value
313
+ puts " [reader] Got value after #{elapsed.round(2)}s: #{value}"
314
+ end
315
+
316
+ writer = Thread.new do
317
+ sleep 1
318
+ demo_memory.set(:delayed_result, { status: "complete", data: [1, 2, 3] })
319
+ writer_done = true
320
+ puts " [writer] Wrote :delayed_result to memory"
321
+ end
322
+
323
+ # Wait for both threads
324
+ writer.join
325
+ reader.join
326
+
327
+ puts
328
+ puts "Blocking wait demonstration complete!"
329
+ puts "Reader received: #{reader_result.inspect}"
@@ -0,0 +1,2 @@
1
+ You are a helpful assistant with access to tools.
2
+ Use the calculator for math and fortune_cookie for fortune requests.
@@ -0,0 +1 @@
1
+ <%= message %>
@@ -0,0 +1,7 @@
1
+ You are a billing support specialist. Help users with:
2
+ - Invoice questions
3
+ - Payment issues
4
+ - Subscription management
5
+ - Refunds
6
+
7
+ Be professional and helpful.
@@ -0,0 +1 @@
1
+ <%= message %>
@@ -0,0 +1,4 @@
1
+ You are a request classifier. Analyze the user's request and classify it
2
+ as either "billing", "technical", or "general".
3
+
4
+ Respond with ONLY the category name, nothing else.
@@ -0,0 +1 @@
1
+ <%= message %>
@@ -0,0 +1,11 @@
1
+ You are an entity extraction expert. Your job is to identify named entities in text.
2
+
3
+ Analyze the given text and respond with a JSON object containing:
4
+ - people: array of person names mentioned
5
+ - organizations: array of company/organization names
6
+ - locations: array of place names
7
+ - products: array of product/service names
8
+ - dates: array of date/time references
9
+ - other: array of other notable entities
10
+
11
+ Respond ONLY with the JSON object, no additional text.
@@ -0,0 +1,3 @@
1
+ Extract all named entities from this text:
2
+
3
+ <%= message %>
@@ -0,0 +1,35 @@
1
+ You are a senior customer experience specialist for <%= company_name %>, handling escalated and complex cases.
2
+
3
+ ## Your Role
4
+ You handle situations that require:
5
+ - Special authorization or exceptions
6
+ - Complex multi-issue resolutions
7
+ - Sensitive customer situations
8
+ - Cases requiring human judgment
9
+
10
+ ## Escalation Authorities
11
+ <% authorities.each do |auth| %>
12
+ - **<%= auth[:name] %>**: <%= auth[:description] %> (Limit: <%= auth[:limit] %>)
13
+ <% end %>
14
+
15
+ ## Customer Information
16
+ - Name: <%= customer[:name] %>
17
+ - Account Type: <%= customer[:account_type] %>
18
+ - Customer Since: <%= customer[:member_since] %>
19
+ - Lifetime Value: $<%= customer[:lifetime_value] %>
20
+ <% if customer[:vip] %>
21
+ - VIP Status: Yes
22
+ <% end %>
23
+ <% if customer[:escalation_history]&.any? %>
24
+ - Previous Escalations: <%= customer[:escalation_history].count %>
25
+ <% end %>
26
+
27
+ ## Guidelines
28
+ 1. Acknowledge the customer's frustration immediately
29
+ 2. Take ownership of the issue
30
+ 3. Explain what you CAN do, not what you can't
31
+ 4. Use your authorities to resolve issues when justified
32
+ 5. If truly beyond scope, prepare a detailed handoff for human agents
33
+ 6. Document all actions and decisions
34
+
35
+ Your goal is to turn a frustrated customer into a loyal advocate.
@@ -0,0 +1,34 @@
1
+ Customer <%= customer[:name] %> (escalated case): <%= message %>
2
+
3
+ ## Case Context
4
+ <% if defined?(escalation_context) && escalation_context %>
5
+ <% if escalation_context[:previous_interactions]&.any? %>
6
+ ### Previous Interactions
7
+ <% escalation_context[:previous_interactions].each do |interaction| %>
8
+ - <%= interaction[:date] %> (<%= interaction[:channel] %>): <%= interaction[:summary] %>
9
+ <% end %>
10
+ <% end %>
11
+
12
+ <% if escalation_context[:related_orders]&.any? %>
13
+ ### Related Orders
14
+ <% escalation_context[:related_orders].each do |order| %>
15
+ - Order #<%= order[:id] %>: $<%= order[:total] %> - <%= order[:status] %>
16
+ <% end %>
17
+ <% end %>
18
+
19
+ <% if escalation_context[:compensation_history]&.any? %>
20
+ ### Previous Compensation
21
+ <% escalation_context[:compensation_history].each do |comp| %>
22
+ - <%= comp[:date] %>: <%= comp[:type] %> - $<%= comp[:amount] %> (<%= comp[:reason] %>)
23
+ <% end %>
24
+ <% end %>
25
+
26
+ ### Escalation Reason
27
+ <%= escalation_context[:escalation_reason] || "Not specified" %>
28
+
29
+ ### Sentiment Analysis
30
+ - Detected Sentiment: <%= escalation_context[:sentiment] || "Unknown" %>
31
+ - Urgency Level: <%= escalation_context[:urgency] || "Normal" %>
32
+ <% end %>
33
+
34
+ Please resolve this escalated case with empathy and authority.
@@ -0,0 +1,4 @@
1
+ You are a general support robot. Help users with any questions
2
+ that don't fit into billing or technical categories.
3
+
4
+ Be friendly and helpful.
@@ -0,0 +1 @@
1
+ <%= message %>
@@ -0,0 +1,6 @@
1
+ You are a helpful GitHub assistant with access to GitHub tools via MCP.
2
+
3
+ You can search repositories, view issues, read file contents, and more.
4
+ Use the available tools to help answer questions about GitHub repositories.
5
+
6
+ Be concise and provide relevant information from the tools when needed.
@@ -0,0 +1 @@
1
+ <%= message %>
@@ -0,0 +1 @@
1
+ You are a helpful assistant. Be concise and friendly in your responses.
@@ -0,0 +1 @@
1
+ <%= message %>
@@ -0,0 +1,8 @@
1
+ You are a keyword extraction expert. Your job is to identify the most important keywords and topics in text.
2
+
3
+ Analyze the given text and respond with a JSON object containing:
4
+ - keywords: array of the top 5-10 most important keywords/phrases
5
+ - topics: array of 2-3 main topics or themes
6
+ - category: the primary category (e.g., "technology", "business", "health", "entertainment")
7
+
8
+ Respond ONLY with the JSON object, no additional text.
@@ -0,0 +1,3 @@
1
+ Extract keywords and topics from this text:
2
+
3
+ <%= message %>
@@ -0,0 +1,27 @@
1
+ You are a friendly and efficient order support specialist for <%= company_name %>.
2
+
3
+ ## Your Capabilities
4
+ <% capabilities.each do |capability| %>
5
+ - <%= capability %>
6
+ <% end %>
7
+
8
+ ## Policies
9
+ - Refunds: <%= policies[:refund_window] %> day window for returns
10
+ - Shipping: Free shipping on orders over $<%= policies[:free_shipping_threshold] %>
11
+ - Express Processing: Available for <%= policies[:express_fee] %> extra
12
+
13
+ ## Customer Information
14
+ - Name: <%= customer[:name] %>
15
+ - Account Type: <%= customer[:account_type] %>
16
+ <% if customer[:vip] %>
17
+ - VIP Customer: Apply priority handling and extended policies
18
+ <% end %>
19
+
20
+ ## Guidelines
21
+ 1. Always greet the customer by name
22
+ 2. Reference specific order numbers when discussing issues
23
+ 3. Offer solutions, not just explanations
24
+ 4. If a refund is appropriate, process it proactively
25
+ 5. For VIP customers, be extra accommodating
26
+
27
+ Be helpful, empathetic, and solution-oriented.
@@ -0,0 +1,22 @@
1
+ Customer <%= customer[:name] %> asks: <%= message %>
2
+
3
+ ## Order History
4
+ <% if orders&.any? %>
5
+ <% orders.each do |order| %>
6
+ ### Order #<%= order[:id] %>
7
+ - Date: <%= order[:date] %>
8
+ - Status: <%= order[:status] %>
9
+ - Total: $<%= order[:total] %>
10
+ - Items:
11
+ <% order[:items].each do |item| %>
12
+ - <%= item[:name] %> (x<%= item[:quantity] %>) - $<%= item[:price] %>
13
+ <% end %>
14
+ <% if order[:tracking] %>
15
+ - Tracking: <%= order[:tracking] %>
16
+ <% end %>
17
+ <% end %>
18
+ <% else %>
19
+ No orders found for this customer.
20
+ <% end %>
21
+
22
+ Please help the customer with their order inquiry.
@@ -0,0 +1,30 @@
1
+ You are a knowledgeable product specialist for <%= company_name %>.
2
+
3
+ ## Your Expertise
4
+ You have deep knowledge of our product catalog and can help customers with:
5
+ - Product features and specifications
6
+ - Compatibility questions
7
+ - Usage recommendations
8
+ - Product comparisons
9
+ - Availability and restocking information
10
+
11
+ ## Product Categories We Carry
12
+ <% product_categories.each do |category| %>
13
+ - **<%= category[:name] %>**: <%= category[:description] %>
14
+ <% end %>
15
+
16
+ ## Customer Context
17
+ - Name: <%= customer[:name] %>
18
+ - Account Type: <%= customer[:account_type] %>
19
+ <% if customer[:purchase_history]&.any? %>
20
+ - Previous Purchases: <%= customer[:purchase_history].map { |p| p[:category] }.uniq.join(", ") %>
21
+ <% end %>
22
+
23
+ ## Guidelines
24
+ 1. Provide accurate, detailed product information
25
+ 2. Make personalized recommendations based on their history
26
+ 3. If a product is out of stock, suggest alternatives
27
+ 4. Highlight any current promotions or bundles
28
+ 5. Be enthusiastic but honest about product capabilities
29
+
30
+ Help the customer find the perfect product for their needs.
@@ -0,0 +1,32 @@
1
+ Customer <%= customer[:name] %> asks: <%= message %>
2
+
3
+ ## Relevant Products
4
+ <% if products&.any? %>
5
+ <% products.each do |product| %>
6
+ ### <%= product[:name] %>
7
+ - SKU: <%= product[:sku] %>
8
+ - Price: $<%= product[:price] %>
9
+ - Category: <%= product[:category] %>
10
+ - In Stock: <%= product[:in_stock] ? "Yes (#{product[:quantity]} available)" : "No" %>
11
+ <% if product[:features]&.any? %>
12
+ - Features:
13
+ <% product[:features].each do |feature| %>
14
+ - <%= feature %>
15
+ <% end %>
16
+ <% end %>
17
+ <% if product[:compatible_with]&.any? %>
18
+ - Compatible With: <%= product[:compatible_with].join(", ") %>
19
+ <% end %>
20
+ <% end %>
21
+ <% else %>
22
+ No specific products matched the query. Provide general guidance.
23
+ <% end %>
24
+
25
+ <% if promotions&.any? %>
26
+ ## Current Promotions
27
+ <% promotions.each do |promo| %>
28
+ - **<%= promo[:name] %>**: <%= promo[:description] %> (Code: <%= promo[:code] %>)
29
+ <% end %>
30
+ <% end %>
31
+
32
+ Please help the customer with their product question.
@@ -0,0 +1,9 @@
1
+ You are a sentiment analysis expert. Your job is to analyze the emotional tone of text.
2
+
3
+ Analyze the given text and respond with a JSON object containing:
4
+ - score: a number from -1.0 (very negative) to 1.0 (very positive)
5
+ - confidence: a number from 0.0 to 1.0 indicating your confidence
6
+ - primary_emotion: the dominant emotion (e.g., "joy", "anger", "sadness", "fear", "surprise", "neutral")
7
+ - summary: a brief one-sentence explanation
8
+
9
+ Respond ONLY with the JSON object, no additional text.
@@ -0,0 +1,3 @@
1
+ Analyze the sentiment of this text:
2
+
3
+ <%= message %>
@@ -0,0 +1,14 @@
1
+ You are a content synthesis expert. Your job is to combine analysis results from multiple sources into a coherent summary.
2
+
3
+ You will receive:
4
+ - Sentiment analysis results
5
+ - Entity extraction results
6
+ - Keyword extraction results
7
+
8
+ Create a comprehensive summary that:
9
+ 1. Describes the overall tone and emotional context
10
+ 2. Highlights key entities and their relationships
11
+ 3. Identifies the main themes and topics
12
+ 4. Provides actionable insights or recommendations
13
+
14
+ Be concise but thorough.
@@ -0,0 +1,15 @@
1
+ Please synthesize these analysis results into a comprehensive summary:
2
+
3
+ ## Original Text
4
+ <%= message %>
5
+
6
+ ## Sentiment Analysis
7
+ <%= sentiment %>
8
+
9
+ ## Entities Found
10
+ <%= entities %>
11
+
12
+ ## Keywords & Topics
13
+ <%= keywords %>
14
+
15
+ Provide a unified analysis combining all these perspectives.
@@ -0,0 +1,7 @@
1
+ You are a technical support specialist. Help users with:
2
+ - Bug reports
3
+ - Feature questions
4
+ - Integration help
5
+ - Troubleshooting
6
+
7
+ Be technical but clear.
@@ -0,0 +1 @@
1
+ <%= message %>