coolhand 0.1.4 → 0.2.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 +4 -4
- data/.rubocop.yml +2 -1
- data/CHANGELOG.md +53 -0
- data/README.md +32 -33
- data/docs/anthropic.md +518 -0
- data/lib/coolhand/ruby/anthropic_interceptor.rb +300 -0
- data/lib/coolhand/ruby/api_service.rb +18 -3
- data/lib/coolhand/ruby/base_interceptor.rb +148 -0
- data/lib/coolhand/ruby/faraday_interceptor.rb +129 -0
- data/lib/coolhand/ruby/version.rb +1 -1
- data/lib/coolhand/ruby.rb +38 -7
- metadata +12 -7
- data/coolhand-ruby.gemspec +0 -42
- data/lib/coolhand/ruby/interceptor.rb +0 -118
data/docs/anthropic.md
ADDED
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
# Anthropic Integration Guide
|
|
2
|
+
|
|
3
|
+
Coolhand provides comprehensive monitoring for Anthropic's Claude API through support for both the official and community Ruby gems. This guide covers setup, usage, streaming, and troubleshooting.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Coolhand automatically detects which Anthropic gem you're using and applies the appropriate monitoring strategy:
|
|
8
|
+
|
|
9
|
+
- **Official Anthropic Gem** (`anthropic`): Uses Net::HTTP transport, monitored via AnthropicInterceptor
|
|
10
|
+
- **Community Ruby-Anthropic Gem** (`ruby-anthropic`): Uses Faraday transport, monitored via FaradayInterceptor
|
|
11
|
+
- **Dual Installation**: Automatically handles conflicts and prevents duplicate logging
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### Basic Configuration
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
require 'coolhand/ruby'
|
|
19
|
+
|
|
20
|
+
Coolhand.configure do |config|
|
|
21
|
+
config.api_key = 'your_coolhand_api_key_here'
|
|
22
|
+
config.silent = true # Set to false for debug output
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
That's it! All Anthropic API calls are now automatically monitored.
|
|
27
|
+
|
|
28
|
+
## Official Anthropic Gem
|
|
29
|
+
|
|
30
|
+
### Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
gem install anthropic
|
|
34
|
+
# or add to Gemfile
|
|
35
|
+
gem 'anthropic'
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Basic Usage
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
require 'anthropic'
|
|
42
|
+
require 'coolhand/ruby'
|
|
43
|
+
|
|
44
|
+
# Configure Coolhand
|
|
45
|
+
Coolhand.configure do |config|
|
|
46
|
+
config.api_key = 'your_coolhand_api_key'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Use official Anthropic gem normally
|
|
50
|
+
client = Anthropic::Client.new
|
|
51
|
+
|
|
52
|
+
response = client.messages(
|
|
53
|
+
parameters: {
|
|
54
|
+
model: "claude-3-sonnet-20240229",
|
|
55
|
+
max_tokens: 1024,
|
|
56
|
+
messages: [{ role: "user", content: "Hello, Claude!" }]
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
puts response.content.first.text
|
|
61
|
+
# ✅ Request and response automatically logged to Coolhand
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Streaming with Official Gem
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
# Streaming is automatically detected and properly logged
|
|
68
|
+
response = client.messages(
|
|
69
|
+
parameters: {
|
|
70
|
+
model: "claude-3-sonnet-20240229",
|
|
71
|
+
max_tokens: 1024,
|
|
72
|
+
messages: [{ role: "user", content: "Write a haiku about Ruby" }],
|
|
73
|
+
stream: true # ✅ Streaming automatically detected
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Process streaming response
|
|
78
|
+
accumulated_text = ""
|
|
79
|
+
response.each do |chunk|
|
|
80
|
+
if chunk.delta&.text
|
|
81
|
+
print chunk.delta.text
|
|
82
|
+
accumulated_text += chunk.delta.text
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# ✅ Complete accumulated response logged to Coolhand (not individual chunks)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Advanced Configuration
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
client = Anthropic::Client.new
|
|
93
|
+
|
|
94
|
+
# All parameters are automatically captured and logged
|
|
95
|
+
response = client.messages(
|
|
96
|
+
parameters: {
|
|
97
|
+
model: "claude-3-opus-20240229",
|
|
98
|
+
max_tokens: 2000,
|
|
99
|
+
temperature: 0.7,
|
|
100
|
+
top_p: 0.9,
|
|
101
|
+
system: "You are a helpful assistant specializing in Ruby programming.",
|
|
102
|
+
messages: [
|
|
103
|
+
{ role: "user", content: "Explain Ruby metaprogramming" }
|
|
104
|
+
],
|
|
105
|
+
# Streaming works automatically
|
|
106
|
+
stream: true
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# ✅ All parameters (model, temperature, top_p, system, etc.) logged
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Community Ruby-Anthropic Gem
|
|
114
|
+
|
|
115
|
+
### Installation
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
gem install ruby-anthropic
|
|
119
|
+
# or add to Gemfile
|
|
120
|
+
gem 'ruby-anthropic'
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Basic Usage
|
|
124
|
+
|
|
125
|
+
```ruby
|
|
126
|
+
require 'ruby-anthropic'
|
|
127
|
+
require 'coolhand/ruby'
|
|
128
|
+
|
|
129
|
+
# Configure Coolhand
|
|
130
|
+
Coolhand.configure do |config|
|
|
131
|
+
config.api_key = 'your_coolhand_api_key'
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Use ruby-anthropic gem normally - monitored via Faraday
|
|
135
|
+
client = Anthropic::Client.new(access_token: ENV['ANTHROPIC_API_KEY'])
|
|
136
|
+
|
|
137
|
+
response = client.messages(
|
|
138
|
+
model: "claude-3-sonnet-20240229",
|
|
139
|
+
max_tokens: 1024,
|
|
140
|
+
messages: [{ role: "user", content: "Hello, Claude!" }]
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
puts response.dig("content", 0, "text")
|
|
144
|
+
# ✅ Automatically logged via FaradayInterceptor
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Streaming with Ruby-Anthropic
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
# Streaming works seamlessly via Faraday monitoring
|
|
151
|
+
response = client.messages(
|
|
152
|
+
model: "claude-3-sonnet-20240229",
|
|
153
|
+
max_tokens: 1024,
|
|
154
|
+
messages: [{ role: "user", content: "Count to 10 slowly" }],
|
|
155
|
+
stream: true
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Process Server-Sent Events
|
|
159
|
+
response.each do |event|
|
|
160
|
+
puts event if event.start_with?("data:")
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# ✅ Complete conversation logged to Coolhand
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Dual Gem Installation
|
|
167
|
+
|
|
168
|
+
### Automatic Conflict Resolution
|
|
169
|
+
|
|
170
|
+
When both gems are installed, Coolhand automatically handles the conflict:
|
|
171
|
+
|
|
172
|
+
```ruby
|
|
173
|
+
require 'anthropic' # Official gem
|
|
174
|
+
require 'ruby-anthropic' # Community gem
|
|
175
|
+
require 'coolhand/ruby'
|
|
176
|
+
|
|
177
|
+
Coolhand.configure do |config|
|
|
178
|
+
config.api_key = 'your_coolhand_api_key'
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# ⚠️ Warning displayed:
|
|
182
|
+
# "Both 'anthropic' and 'ruby-anthropic' gems are installed.
|
|
183
|
+
# Coolhand will only monitor ruby-anthropic (Faraday-based) requests.
|
|
184
|
+
# Official anthropic gem monitoring has been disabled."
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Recommendation**: Use only one gem to avoid confusion. Choose based on your needs:
|
|
188
|
+
- **Official gem**: Latest features, official support, Net::HTTP transport
|
|
189
|
+
- **Community gem**: Faraday-based, may have community contributions
|
|
190
|
+
|
|
191
|
+
### Manual Conflict Resolution
|
|
192
|
+
|
|
193
|
+
To explicitly use the official gem when both are installed:
|
|
194
|
+
|
|
195
|
+
```ruby
|
|
196
|
+
# Temporarily hide the community gem
|
|
197
|
+
begin
|
|
198
|
+
# Remove ruby-anthropic from the load path
|
|
199
|
+
$LOAD_PATH.reject! { |path| path.include?('ruby-anthropic') }
|
|
200
|
+
|
|
201
|
+
require 'anthropic'
|
|
202
|
+
require 'coolhand/ruby'
|
|
203
|
+
|
|
204
|
+
Coolhand.configure do |config|
|
|
205
|
+
config.api_key = 'your_coolhand_api_key'
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Now only the official gem will be monitored
|
|
209
|
+
client = Anthropic::Client.new
|
|
210
|
+
# ... use official gem
|
|
211
|
+
end
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Rails Integration
|
|
215
|
+
|
|
216
|
+
### Initializer Setup
|
|
217
|
+
|
|
218
|
+
```ruby
|
|
219
|
+
# config/initializers/coolhand.rb
|
|
220
|
+
Coolhand.configure do |config|
|
|
221
|
+
# Use Rails credentials for API key
|
|
222
|
+
config.api_key = Rails.application.credentials.coolhand_api_key
|
|
223
|
+
|
|
224
|
+
# Suppress console output in production
|
|
225
|
+
config.silent = Rails.env.production?
|
|
226
|
+
|
|
227
|
+
# Ensure Anthropic endpoints are monitored (default behavior)
|
|
228
|
+
# config.intercept_addresses = ["api.openai.com", "api.anthropic.com"]
|
|
229
|
+
end
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Service Object Pattern
|
|
233
|
+
|
|
234
|
+
```ruby
|
|
235
|
+
# app/services/claude_chat_service.rb
|
|
236
|
+
class ClaudeChatService
|
|
237
|
+
def initialize
|
|
238
|
+
@client = Anthropic::Client.new
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def generate_response(user_message, context: nil)
|
|
242
|
+
messages = []
|
|
243
|
+
messages << { role: "system", content: context } if context
|
|
244
|
+
messages << { role: "user", content: user_message }
|
|
245
|
+
|
|
246
|
+
response = @client.messages(
|
|
247
|
+
parameters: {
|
|
248
|
+
model: "claude-3-sonnet-20240229",
|
|
249
|
+
max_tokens: 1500,
|
|
250
|
+
messages: messages
|
|
251
|
+
}
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
response.content.first.text
|
|
255
|
+
# ✅ Automatically logged to Coolhand with all context
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def stream_response(user_message)
|
|
259
|
+
response = @client.messages(
|
|
260
|
+
parameters: {
|
|
261
|
+
model: "claude-3-sonnet-20240229",
|
|
262
|
+
max_tokens: 1500,
|
|
263
|
+
messages: [{ role: "user", content: user_message }],
|
|
264
|
+
stream: true
|
|
265
|
+
}
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
Enumerator.new do |yielder|
|
|
269
|
+
response.each do |chunk|
|
|
270
|
+
if chunk.delta&.text
|
|
271
|
+
yielder << chunk.delta.text
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
# ✅ Complete streaming conversation logged
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Background Job Example
|
|
281
|
+
|
|
282
|
+
```ruby
|
|
283
|
+
# app/jobs/claude_analysis_job.rb
|
|
284
|
+
class ClaudeAnalysisJob < ApplicationJob
|
|
285
|
+
def perform(document_id, analysis_type)
|
|
286
|
+
document = Document.find(document_id)
|
|
287
|
+
|
|
288
|
+
client = Anthropic::Client.new
|
|
289
|
+
|
|
290
|
+
response = client.messages(
|
|
291
|
+
parameters: {
|
|
292
|
+
model: "claude-3-opus-20240229",
|
|
293
|
+
max_tokens: 2000,
|
|
294
|
+
system: "You are an expert document analyzer.",
|
|
295
|
+
messages: [
|
|
296
|
+
{
|
|
297
|
+
role: "user",
|
|
298
|
+
content: "Analyze this document: #{document.content}"
|
|
299
|
+
}
|
|
300
|
+
]
|
|
301
|
+
}
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
document.update!(
|
|
305
|
+
analysis: response.content.first.text,
|
|
306
|
+
analysis_type: analysis_type
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
# ✅ Analysis request logged with document context
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## Advanced Features
|
|
315
|
+
|
|
316
|
+
### Thread-Safe Concurrent Requests
|
|
317
|
+
|
|
318
|
+
```ruby
|
|
319
|
+
# Coolhand handles concurrent requests safely
|
|
320
|
+
threads = []
|
|
321
|
+
|
|
322
|
+
10.times do |i|
|
|
323
|
+
threads << Thread.new do
|
|
324
|
+
client = Anthropic::Client.new
|
|
325
|
+
|
|
326
|
+
response = client.messages(
|
|
327
|
+
parameters: {
|
|
328
|
+
model: "claude-3-sonnet-20240229",
|
|
329
|
+
max_tokens: 500,
|
|
330
|
+
messages: [{ role: "user", content: "Request #{i}" }]
|
|
331
|
+
}
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
puts "Response #{i}: #{response.content.first.text}"
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
threads.each(&:join)
|
|
339
|
+
# ✅ All 10 requests logged correctly without conflicts
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Request Correlation
|
|
343
|
+
|
|
344
|
+
Access the current request ID for correlation:
|
|
345
|
+
|
|
346
|
+
```ruby
|
|
347
|
+
client = Anthropic::Client.new
|
|
348
|
+
|
|
349
|
+
response = client.messages(
|
|
350
|
+
parameters: {
|
|
351
|
+
model: "claude-3-sonnet-20240229",
|
|
352
|
+
max_tokens: 1000,
|
|
353
|
+
messages: [{ role: "user", content: "Hello" }]
|
|
354
|
+
}
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
# Get the request ID that was logged to Coolhand
|
|
358
|
+
request_id = Thread.current[:coolhand_current_request_id]
|
|
359
|
+
puts "Logged to Coolhand with ID: #{request_id}"
|
|
360
|
+
|
|
361
|
+
# Use this ID for feedback or debugging
|
|
362
|
+
feedback_service = Coolhand::Ruby::FeedbackService.new(Coolhand.configuration)
|
|
363
|
+
feedback_service.create_feedback(
|
|
364
|
+
llm_request_log_id: request_id,
|
|
365
|
+
like: true,
|
|
366
|
+
explanation: "Great response quality"
|
|
367
|
+
)
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
## Troubleshooting
|
|
371
|
+
|
|
372
|
+
### Debug Mode
|
|
373
|
+
|
|
374
|
+
Enable verbose logging to see what's being intercepted:
|
|
375
|
+
|
|
376
|
+
```ruby
|
|
377
|
+
Coolhand.configure do |config|
|
|
378
|
+
config.api_key = 'your_api_key'
|
|
379
|
+
config.silent = false # Enable debug output
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# Now you'll see console output like:
|
|
383
|
+
# "✅ Coolhand ready - will log OpenAI and Anthropic (official gem) calls"
|
|
384
|
+
# "COOLHAND: ⚠️ Warning: Both 'anthropic' and 'ruby-anthropic' gems are installed..."
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Common Issues
|
|
388
|
+
|
|
389
|
+
#### 1. Gem Not Detected
|
|
390
|
+
|
|
391
|
+
**Problem**: Coolhand says "Anthropic gem not loaded"
|
|
392
|
+
|
|
393
|
+
**Solution**: Ensure you require the gem before configuring Coolhand:
|
|
394
|
+
|
|
395
|
+
```ruby
|
|
396
|
+
require 'anthropic' # Must come before coolhand/ruby
|
|
397
|
+
require 'coolhand/ruby'
|
|
398
|
+
|
|
399
|
+
Coolhand.configure do |config|
|
|
400
|
+
config.api_key = 'your_api_key'
|
|
401
|
+
end
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
#### 2. Duplicate Requests
|
|
405
|
+
|
|
406
|
+
**Problem**: Seeing requests logged twice in dashboard
|
|
407
|
+
|
|
408
|
+
**Cause**: Usually indicates both gems are installed and conflicting
|
|
409
|
+
|
|
410
|
+
**Solution**: Choose one gem and uninstall the other:
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
# Keep official gem
|
|
414
|
+
gem uninstall ruby-anthropic
|
|
415
|
+
|
|
416
|
+
# OR keep community gem
|
|
417
|
+
gem uninstall anthropic
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
#### 3. Missing Streaming Data
|
|
421
|
+
|
|
422
|
+
**Problem**: Only seeing individual chunks, not complete response
|
|
423
|
+
|
|
424
|
+
**Cause**: Custom streaming handling interfering with automatic detection
|
|
425
|
+
|
|
426
|
+
**Solution**: Let Coolhand handle streaming automatically:
|
|
427
|
+
|
|
428
|
+
```ruby
|
|
429
|
+
# ❌ Don't manually collect chunks for logging
|
|
430
|
+
response = client.messages(parameters: { stream: true })
|
|
431
|
+
manual_collection = ""
|
|
432
|
+
response.each { |chunk| manual_collection += chunk.delta.text }
|
|
433
|
+
|
|
434
|
+
# ✅ Just process chunks normally - Coolhand handles logging
|
|
435
|
+
response = client.messages(parameters: { stream: true })
|
|
436
|
+
response.each { |chunk| print chunk.delta.text }
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
#### 4. Performance Concerns
|
|
440
|
+
|
|
441
|
+
**Problem**: Worried about monitoring overhead
|
|
442
|
+
|
|
443
|
+
**Solution**: Monitoring is asynchronous and negligible:
|
|
444
|
+
|
|
445
|
+
```ruby
|
|
446
|
+
# Monitoring happens in background threads
|
|
447
|
+
# Your application performance is unaffected
|
|
448
|
+
require 'benchmark'
|
|
449
|
+
|
|
450
|
+
time = Benchmark.measure do
|
|
451
|
+
1000.times do
|
|
452
|
+
client.messages(
|
|
453
|
+
parameters: {
|
|
454
|
+
model: "claude-3-haiku-20240307", # Fast model for testing
|
|
455
|
+
max_tokens: 100,
|
|
456
|
+
messages: [{ role: "user", content: "Hi" }]
|
|
457
|
+
}
|
|
458
|
+
)
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
puts "Time with monitoring: #{time.real}s"
|
|
463
|
+
# Overhead is typically < 1ms per request
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### Testing
|
|
467
|
+
|
|
468
|
+
#### Test Environment Setup
|
|
469
|
+
|
|
470
|
+
```ruby
|
|
471
|
+
# spec/spec_helper.rb or test/test_helper.rb
|
|
472
|
+
if Rails.env.test?
|
|
473
|
+
Coolhand.configure do |config|
|
|
474
|
+
config.api_key = 'test_key_do_not_send_requests'
|
|
475
|
+
config.silent = true
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
#### Mocking for Tests
|
|
481
|
+
|
|
482
|
+
```ruby
|
|
483
|
+
# spec/support/anthropic_mock.rb
|
|
484
|
+
RSpec.configure do |config|
|
|
485
|
+
config.before(:each) do
|
|
486
|
+
# Mock Anthropic responses to avoid real API calls
|
|
487
|
+
allow_any_instance_of(Anthropic::Client).to receive(:messages).and_return(
|
|
488
|
+
double(
|
|
489
|
+
content: [double(text: "Mocked response")],
|
|
490
|
+
model: "claude-3-sonnet-20240229"
|
|
491
|
+
)
|
|
492
|
+
)
|
|
493
|
+
end
|
|
494
|
+
end
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
## Best Practices
|
|
498
|
+
|
|
499
|
+
1. **Choose One Gem**: Avoid installing both `anthropic` and `ruby-anthropic` gems
|
|
500
|
+
2. **Secure API Keys**: Use environment variables or Rails credentials, never commit keys
|
|
501
|
+
3. **Silent in Production**: Set `config.silent = true` in production environments
|
|
502
|
+
4. **Monitor Performance**: Use fast models (haiku) for high-frequency requests
|
|
503
|
+
5. **Request Correlation**: Use thread-local request IDs for debugging and feedback
|
|
504
|
+
6. **Streaming Efficiency**: Let Coolhand handle streaming accumulation automatically
|
|
505
|
+
7. **Test Safely**: Mock API responses in test environments to avoid real charges
|
|
506
|
+
|
|
507
|
+
## API Reference
|
|
508
|
+
|
|
509
|
+
For complete API documentation, see:
|
|
510
|
+
- [Official Anthropic Gem](https://github.com/anthropics/anthropic-sdk-ruby)
|
|
511
|
+
- [Community Ruby-Anthropic Gem](https://github.com/alexrudall/ruby-anthropic)
|
|
512
|
+
- [Coolhand Feedback API](../README.md#feedback-api)
|
|
513
|
+
|
|
514
|
+
## Support
|
|
515
|
+
|
|
516
|
+
- **Coolhand Issues**: [GitHub Issues](https://github.com/Coolhand-Labs/coolhand-ruby/issues)
|
|
517
|
+
- **Anthropic API**: [Anthropic Documentation](https://docs.anthropic.com/)
|
|
518
|
+
- **Gem Conflicts**: Check this guide's troubleshooting section
|