language-operator 0.0.1 → 0.1.30

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 (116) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +125 -0
  3. data/CHANGELOG.md +53 -0
  4. data/Gemfile +8 -0
  5. data/Gemfile.lock +284 -0
  6. data/LICENSE +229 -21
  7. data/Makefile +77 -0
  8. data/README.md +3 -11
  9. data/Rakefile +34 -0
  10. data/bin/aictl +7 -0
  11. data/completions/_aictl +232 -0
  12. data/completions/aictl.bash +121 -0
  13. data/completions/aictl.fish +114 -0
  14. data/docs/architecture/agent-runtime.md +585 -0
  15. data/docs/dsl/agent-reference.md +591 -0
  16. data/docs/dsl/best-practices.md +1078 -0
  17. data/docs/dsl/chat-endpoints.md +895 -0
  18. data/docs/dsl/constraints.md +671 -0
  19. data/docs/dsl/mcp-integration.md +1177 -0
  20. data/docs/dsl/webhooks.md +932 -0
  21. data/docs/dsl/workflows.md +744 -0
  22. data/examples/README.md +569 -0
  23. data/examples/agent_example.rb +86 -0
  24. data/examples/chat_endpoint_agent.rb +118 -0
  25. data/examples/github_webhook_agent.rb +171 -0
  26. data/examples/mcp_agent.rb +158 -0
  27. data/examples/oauth_callback_agent.rb +296 -0
  28. data/examples/stripe_webhook_agent.rb +219 -0
  29. data/examples/webhook_agent.rb +80 -0
  30. data/lib/language_operator/agent/base.rb +110 -0
  31. data/lib/language_operator/agent/executor.rb +440 -0
  32. data/lib/language_operator/agent/instrumentation.rb +54 -0
  33. data/lib/language_operator/agent/metrics_tracker.rb +183 -0
  34. data/lib/language_operator/agent/safety/ast_validator.rb +272 -0
  35. data/lib/language_operator/agent/safety/audit_logger.rb +104 -0
  36. data/lib/language_operator/agent/safety/budget_tracker.rb +175 -0
  37. data/lib/language_operator/agent/safety/content_filter.rb +93 -0
  38. data/lib/language_operator/agent/safety/manager.rb +207 -0
  39. data/lib/language_operator/agent/safety/rate_limiter.rb +150 -0
  40. data/lib/language_operator/agent/safety/safe_executor.rb +115 -0
  41. data/lib/language_operator/agent/scheduler.rb +183 -0
  42. data/lib/language_operator/agent/telemetry.rb +116 -0
  43. data/lib/language_operator/agent/web_server.rb +610 -0
  44. data/lib/language_operator/agent/webhook_authenticator.rb +226 -0
  45. data/lib/language_operator/agent.rb +149 -0
  46. data/lib/language_operator/cli/commands/agent.rb +1252 -0
  47. data/lib/language_operator/cli/commands/cluster.rb +335 -0
  48. data/lib/language_operator/cli/commands/install.rb +404 -0
  49. data/lib/language_operator/cli/commands/model.rb +266 -0
  50. data/lib/language_operator/cli/commands/persona.rb +396 -0
  51. data/lib/language_operator/cli/commands/quickstart.rb +22 -0
  52. data/lib/language_operator/cli/commands/status.rb +156 -0
  53. data/lib/language_operator/cli/commands/tool.rb +537 -0
  54. data/lib/language_operator/cli/commands/use.rb +47 -0
  55. data/lib/language_operator/cli/errors/handler.rb +180 -0
  56. data/lib/language_operator/cli/errors/suggestions.rb +176 -0
  57. data/lib/language_operator/cli/formatters/code_formatter.rb +81 -0
  58. data/lib/language_operator/cli/formatters/log_formatter.rb +290 -0
  59. data/lib/language_operator/cli/formatters/progress_formatter.rb +53 -0
  60. data/lib/language_operator/cli/formatters/table_formatter.rb +179 -0
  61. data/lib/language_operator/cli/formatters/value_formatter.rb +113 -0
  62. data/lib/language_operator/cli/helpers/cluster_context.rb +62 -0
  63. data/lib/language_operator/cli/helpers/cluster_validator.rb +101 -0
  64. data/lib/language_operator/cli/helpers/editor_helper.rb +58 -0
  65. data/lib/language_operator/cli/helpers/kubeconfig_validator.rb +167 -0
  66. data/lib/language_operator/cli/helpers/resource_dependency_checker.rb +74 -0
  67. data/lib/language_operator/cli/helpers/schedule_builder.rb +108 -0
  68. data/lib/language_operator/cli/helpers/user_prompts.rb +69 -0
  69. data/lib/language_operator/cli/main.rb +232 -0
  70. data/lib/language_operator/cli/templates/tools/generic.yaml +66 -0
  71. data/lib/language_operator/cli/wizards/agent_wizard.rb +246 -0
  72. data/lib/language_operator/cli/wizards/quickstart_wizard.rb +588 -0
  73. data/lib/language_operator/client/base.rb +214 -0
  74. data/lib/language_operator/client/config.rb +136 -0
  75. data/lib/language_operator/client/cost_calculator.rb +37 -0
  76. data/lib/language_operator/client/mcp_connector.rb +123 -0
  77. data/lib/language_operator/client.rb +19 -0
  78. data/lib/language_operator/config/cluster_config.rb +101 -0
  79. data/lib/language_operator/config/tool_patterns.yaml +57 -0
  80. data/lib/language_operator/config/tool_registry.rb +96 -0
  81. data/lib/language_operator/config.rb +138 -0
  82. data/lib/language_operator/dsl/adapter.rb +124 -0
  83. data/lib/language_operator/dsl/agent_context.rb +90 -0
  84. data/lib/language_operator/dsl/agent_definition.rb +427 -0
  85. data/lib/language_operator/dsl/chat_endpoint_definition.rb +115 -0
  86. data/lib/language_operator/dsl/config.rb +119 -0
  87. data/lib/language_operator/dsl/context.rb +50 -0
  88. data/lib/language_operator/dsl/execution_context.rb +47 -0
  89. data/lib/language_operator/dsl/helpers.rb +109 -0
  90. data/lib/language_operator/dsl/http.rb +184 -0
  91. data/lib/language_operator/dsl/mcp_server_definition.rb +73 -0
  92. data/lib/language_operator/dsl/parameter_definition.rb +124 -0
  93. data/lib/language_operator/dsl/registry.rb +36 -0
  94. data/lib/language_operator/dsl/shell.rb +125 -0
  95. data/lib/language_operator/dsl/tool_definition.rb +112 -0
  96. data/lib/language_operator/dsl/webhook_authentication.rb +114 -0
  97. data/lib/language_operator/dsl/webhook_definition.rb +106 -0
  98. data/lib/language_operator/dsl/workflow_definition.rb +259 -0
  99. data/lib/language_operator/dsl.rb +160 -0
  100. data/lib/language_operator/errors.rb +60 -0
  101. data/lib/language_operator/kubernetes/client.rb +279 -0
  102. data/lib/language_operator/kubernetes/resource_builder.rb +194 -0
  103. data/lib/language_operator/loggable.rb +47 -0
  104. data/lib/language_operator/logger.rb +141 -0
  105. data/lib/language_operator/retry.rb +123 -0
  106. data/lib/language_operator/retryable.rb +132 -0
  107. data/lib/language_operator/tool_loader.rb +242 -0
  108. data/lib/language_operator/validators.rb +170 -0
  109. data/lib/language_operator/version.rb +1 -1
  110. data/lib/language_operator.rb +65 -3
  111. data/requirements/tasks/challenge.md +9 -0
  112. data/requirements/tasks/iterate.md +36 -0
  113. data/requirements/tasks/optimize.md +21 -0
  114. data/requirements/tasks/tag.md +5 -0
  115. data/test_agent_dsl.rb +108 -0
  116. metadata +503 -20
@@ -0,0 +1,1078 @@
1
+ # Best Practices Guide
2
+
3
+ Comprehensive guide to designing, securing, and deploying Language Operator agents in production.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Agent Design Patterns](#agent-design-patterns)
8
+ - [Security Best Practices](#security-best-practices)
9
+ - [Performance Optimization](#performance-optimization)
10
+ - [Testing Strategies](#testing-strategies)
11
+ - [Debugging Tips](#debugging-tips)
12
+ - [Cost Optimization](#cost-optimization)
13
+ - [Production Deployment Checklist](#production-deployment-checklist)
14
+
15
+ ## Agent Design Patterns
16
+
17
+ ### When to Use Each Mode
18
+
19
+ #### Autonomous Mode
20
+
21
+ **Use when:**
22
+ - Continuous monitoring and alerting required
23
+ - Background data processing
24
+ - Proactive task execution
25
+ - Long-running workflows
26
+
27
+ **Don't use when:**
28
+ - Responding to external events (use reactive)
29
+ - Scheduled execution only (use scheduled)
30
+ - Cost control is critical (autonomous can be expensive)
31
+
32
+ **Example:**
33
+ ```ruby
34
+ agent "security-monitor" do
35
+ mode :autonomous
36
+
37
+ objectives [
38
+ "Monitor security logs continuously",
39
+ "Detect anomalies in access patterns",
40
+ "Alert on suspicious activity"
41
+ ]
42
+
43
+ constraints do
44
+ max_iterations 1000 # Prevent runaway
45
+ daily_budget 5000 # $50/day limit
46
+ requests_per_minute 2 # Check every 30s
47
+ end
48
+ end
49
+ ```
50
+
51
+ **Best practices:**
52
+ - Always set `max_iterations` to prevent infinite loops
53
+ - Use `requests_per_minute` to control check frequency
54
+ - Set aggressive budget limits
55
+ - Monitor costs closely
56
+
57
+ #### Scheduled Mode
58
+
59
+ **Use when:**
60
+ - Tasks run on fixed schedule (daily, weekly, etc.)
61
+ - Reports and summaries needed periodically
62
+ - Batch processing at specific times
63
+ - Predictable resource usage required
64
+
65
+ **Don't use when:**
66
+ - Need to respond to events in real-time (use reactive)
67
+ - Continuous monitoring required (use autonomous)
68
+
69
+ **Example:**
70
+ ```ruby
71
+ agent "daily-report" do
72
+ mode :scheduled
73
+ schedule "0 9 * * *" # 9 AM daily
74
+
75
+ workflow do
76
+ step :gather_data do
77
+ # Collect yesterday's data
78
+ end
79
+
80
+ step :analyze do
81
+ depends_on :gather_data
82
+ # Analyze and summarize
83
+ end
84
+
85
+ step :send_report do
86
+ depends_on :analyze
87
+ # Email report
88
+ end
89
+ end
90
+
91
+ constraints do
92
+ timeout '30m' # Must complete in 30 min
93
+ daily_budget 500 # $5/day
94
+ end
95
+ end
96
+ ```
97
+
98
+ **Best practices:**
99
+ - Always set `timeout` to prevent hanging
100
+ - Choose appropriate schedule frequency
101
+ - Consider timezone (cron runs in UTC by default)
102
+ - Set reasonable daily budget based on frequency
103
+
104
+ #### Reactive Mode
105
+
106
+ **Use when:**
107
+ - Handling webhooks from external services
108
+ - Exposing MCP tools to other agents
109
+ - Providing chat completion endpoints
110
+ - Event-driven workflows
111
+
112
+ **Don't use when:**
113
+ - Need proactive task execution (use autonomous)
114
+ - Fixed schedule sufficient (use scheduled)
115
+
116
+ **Example:**
117
+ ```ruby
118
+ agent "webhook-handler" do
119
+ mode :reactive
120
+
121
+ webhook "/events" do
122
+ method :post
123
+
124
+ authenticate do
125
+ verify_signature(
126
+ header: 'X-Signature',
127
+ secret: ENV['WEBHOOK_SECRET'],
128
+ algorithm: :sha256
129
+ )
130
+ end
131
+
132
+ validate do
133
+ content_type 'application/json'
134
+ max_body_size '5MB'
135
+ end
136
+ end
137
+
138
+ constraints do
139
+ timeout '30s' # Quick response
140
+ requests_per_minute 100 # Handle bursts
141
+ hourly_budget 500 # $5/hour
142
+ end
143
+ end
144
+ ```
145
+
146
+ **Best practices:**
147
+ - Always implement authentication
148
+ - Set quick timeouts (seconds, not minutes)
149
+ - Handle high request rates
150
+ - Validate all inputs
151
+
152
+ ### Workflow Design
153
+
154
+ #### Breaking Down Complex Tasks
155
+
156
+ **Good: Focused steps**
157
+ ```ruby
158
+ workflow do
159
+ step :fetch_data do
160
+ tool 'database_query'
161
+ end
162
+
163
+ step :validate_data do
164
+ depends_on :fetch_data
165
+ # Validate quality
166
+ end
167
+
168
+ step :transform_data do
169
+ depends_on :validate_data
170
+ # Apply transformations
171
+ end
172
+
173
+ step :load_data do
174
+ depends_on :transform_data
175
+ # Save results
176
+ end
177
+ end
178
+ ```
179
+
180
+ **Bad: Monolithic step**
181
+ ```ruby
182
+ workflow do
183
+ step :do_everything do
184
+ # Fetch, validate, transform, and load all in one step
185
+ # Hard to debug, no granular error handling
186
+ end
187
+ end
188
+ ```
189
+
190
+ **Benefits of focused steps:**
191
+ - Easier to debug (know which step failed)
192
+ - Better error handling (retry specific steps)
193
+ - Clearer dependencies
194
+ - Reusable steps
195
+
196
+ #### Error Handling in Workflows
197
+
198
+ **Always handle errors:**
199
+ ```ruby
200
+ step :risky_operation do
201
+ tool 'external_api'
202
+
203
+ on_error do |error|
204
+ # Log error
205
+ logger.error("Step failed: #{error.message}")
206
+
207
+ # Optionally retry or fail gracefully
208
+ { status: 'failed', error: error.message }
209
+ end
210
+ end
211
+ ```
212
+
213
+ **Retry with backoff:**
214
+ ```ruby
215
+ step :flaky_operation do
216
+ tool 'unreliable_api'
217
+
218
+ retry_on_failure(
219
+ max_attempts: 3,
220
+ backoff: :exponential
221
+ )
222
+ end
223
+ ```
224
+
225
+ ## Security Best Practices
226
+
227
+ ### Webhook Security
228
+
229
+ #### Always Authenticate Webhooks
230
+
231
+ **Bad: No authentication**
232
+ ```ruby
233
+ webhook "/insecure" do
234
+ method :post
235
+ # Anyone can call this!
236
+ end
237
+ ```
238
+
239
+ **Good: HMAC signature verification**
240
+ ```ruby
241
+ webhook "/secure" do
242
+ method :post
243
+
244
+ authenticate do
245
+ verify_signature(
246
+ header: 'X-Hub-Signature-256',
247
+ secret: ENV['WEBHOOK_SECRET'],
248
+ algorithm: :sha256
249
+ )
250
+ end
251
+ end
252
+ ```
253
+
254
+ **Good: API key authentication**
255
+ ```ruby
256
+ webhook "/api-secured" do
257
+ method :post
258
+
259
+ authenticate do
260
+ verify_api_key(
261
+ header: 'X-API-Key',
262
+ secret: ENV['API_KEY']
263
+ )
264
+ end
265
+ end
266
+ ```
267
+
268
+ #### Validate All Inputs
269
+
270
+ ```ruby
271
+ webhook "/validated" do
272
+ method :post
273
+
274
+ authenticate do
275
+ verify_signature(...)
276
+ end
277
+
278
+ validate do
279
+ content_type 'application/json'
280
+ max_body_size '5MB'
281
+ require_headers ['X-Event-Type', 'X-Request-ID']
282
+
283
+ custom do |request|
284
+ # Additional validation
285
+ body = JSON.parse(request.body.read)
286
+ body.key?('event') && body.key?('data')
287
+ rescue JSON::ParserError
288
+ false
289
+ end
290
+ end
291
+ end
292
+ ```
293
+
294
+ ### PII Protection
295
+
296
+ #### Filter Sensitive Data
297
+
298
+ **Use blocked_patterns:**
299
+ ```ruby
300
+ constraints do
301
+ blocked_patterns [
302
+ /\b\d{3}-\d{2}-\d{4}\b/, # SSN
303
+ /\b\d{16}\b/, # Credit card
304
+ /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/, # Phone
305
+ /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i, # Email
306
+ /password\s*[:=]/i, # Password disclosure
307
+ /api[_-]?key\s*[:=]\s*['"][^'"]+['"]/i # API keys
308
+ ]
309
+ end
310
+ ```
311
+
312
+ #### Sanitize Tool Parameters
313
+
314
+ ```ruby
315
+ tool "search_users" do
316
+ parameter :email do
317
+ type :string
318
+ required true
319
+ email_format # Validates format
320
+
321
+ # Custom sanitization
322
+ validate ->(value) {
323
+ # Ensure email is from allowed domains
324
+ allowed = ENV['ALLOWED_EMAIL_DOMAINS'].split(',')
325
+ domain = value.split('@').last
326
+ return "Email domain not allowed" unless allowed.include?(domain)
327
+ true
328
+ }
329
+ end
330
+ end
331
+ ```
332
+
333
+ #### Redact Sensitive Output
334
+
335
+ ```ruby
336
+ step :process_user_data do
337
+ execute do |context|
338
+ user_data = fetch_user(context[:user_id])
339
+
340
+ # Redact sensitive fields
341
+ user_data['ssn'] = 'REDACTED'
342
+ user_data['credit_card'] = 'REDACTED'
343
+ user_data['password'] = 'REDACTED'
344
+
345
+ user_data
346
+ end
347
+ end
348
+ ```
349
+
350
+ ### Secrets Management
351
+
352
+ #### Never Hardcode Secrets
353
+
354
+ **Bad:**
355
+ ```ruby
356
+ authenticate do
357
+ verify_api_key(
358
+ header: 'X-API-Key',
359
+ secret: 'hardcoded-secret-123' # NEVER DO THIS
360
+ )
361
+ end
362
+ ```
363
+
364
+ **Good: Use environment variables**
365
+ ```ruby
366
+ authenticate do
367
+ verify_api_key(
368
+ header: 'X-API-Key',
369
+ secret: ENV['WEBHOOK_API_KEY'] # From Kubernetes Secret
370
+ )
371
+ end
372
+ ```
373
+
374
+ #### Kubernetes Secrets
375
+
376
+ ```yaml
377
+ apiVersion: v1
378
+ kind: Secret
379
+ metadata:
380
+ name: agent-secrets
381
+ type: Opaque
382
+ data:
383
+ webhook-secret: <base64-encoded-value>
384
+ api-key: <base64-encoded-value>
385
+ anthropic-api-key: <base64-encoded-value>
386
+ ```
387
+
388
+ Reference in agent:
389
+ ```yaml
390
+ env:
391
+ - name: WEBHOOK_SECRET
392
+ valueFrom:
393
+ secretKeyRef:
394
+ name: agent-secrets
395
+ key: webhook-secret
396
+ - name: API_KEY
397
+ valueFrom:
398
+ secretKeyRef:
399
+ name: agent-secrets
400
+ key: api-key
401
+ ```
402
+
403
+ ### Rate Limiting
404
+
405
+ **Always set rate limits:**
406
+ ```ruby
407
+ constraints do
408
+ requests_per_minute 30 # Prevent burst abuse
409
+ requests_per_hour 1000 # Hourly cap
410
+ requests_per_day 10000 # Daily cap
411
+ end
412
+ ```
413
+
414
+ **For public-facing agents:**
415
+ ```ruby
416
+ constraints do
417
+ requests_per_minute 10 # Conservative for public
418
+ requests_per_hour 300
419
+ requests_per_day 2000
420
+
421
+ daily_budget 1000 # $10/day max
422
+ end
423
+ ```
424
+
425
+ ## Performance Optimization
426
+
427
+ ### Timeouts
428
+
429
+ #### Set Appropriate Timeouts
430
+
431
+ **For quick operations:**
432
+ ```ruby
433
+ constraints do
434
+ timeout '30s' # Quick webhook responses
435
+ end
436
+ ```
437
+
438
+ **For data processing:**
439
+ ```ruby
440
+ constraints do
441
+ timeout '15m' # Enough for ETL
442
+ end
443
+ ```
444
+
445
+ **For complex analysis:**
446
+ ```ruby
447
+ constraints do
448
+ timeout '1h' # Long-running reports
449
+ end
450
+ ```
451
+
452
+ #### Step-Level Timeouts
453
+
454
+ ```ruby
455
+ workflow do
456
+ step :quick_check do
457
+ timeout '5s'
458
+ # Fast validation
459
+ end
460
+
461
+ step :slow_processing do
462
+ timeout '10m'
463
+ # Heavy computation
464
+ end
465
+ end
466
+ ```
467
+
468
+ ### Caching
469
+
470
+ #### Cache Expensive Operations
471
+
472
+ ```ruby
473
+ tool "fetch_exchange_rates" do
474
+ execute do |params|
475
+ # Check cache first
476
+ cache_key = "exchange_rates:#{Date.today}"
477
+ cached = Redis.current.get(cache_key)
478
+ return cached if cached
479
+
480
+ # Fetch from API
481
+ rates = fetch_from_api
482
+ result = rates.to_json
483
+
484
+ # Cache for 1 hour
485
+ Redis.current.setex(cache_key, 3600, result)
486
+
487
+ result
488
+ end
489
+ end
490
+ ```
491
+
492
+ ### Parallel Processing
493
+
494
+ **For independent steps:**
495
+ ```ruby
496
+ workflow do
497
+ # These can run in parallel
498
+ step :fetch_users do
499
+ tool 'database_query'
500
+ end
501
+
502
+ step :fetch_products do
503
+ tool 'database_query'
504
+ end
505
+
506
+ # This waits for both
507
+ step :combine do
508
+ depends_on [:fetch_users, :fetch_products]
509
+ # Merge results
510
+ end
511
+ end
512
+ ```
513
+
514
+ ### Resource Limits
515
+
516
+ **Match container resources:**
517
+ ```ruby
518
+ constraints do
519
+ memory '4Gi' # Match pod memory limit
520
+ timeout '30m'
521
+ end
522
+ ```
523
+
524
+ Pod spec:
525
+ ```yaml
526
+ resources:
527
+ requests:
528
+ memory: "2Gi"
529
+ cpu: "1000m"
530
+ limits:
531
+ memory: "4Gi"
532
+ cpu: "2000m"
533
+ ```
534
+
535
+ ## Testing Strategies
536
+
537
+ ### Unit Testing Tools
538
+
539
+ ```ruby
540
+ RSpec.describe 'MCP Tools' do
541
+ let(:mcp_def) { LanguageOperator::Dsl::McpServerDefinition.new('test') }
542
+
543
+ before do
544
+ mcp_def.tool('add') do
545
+ parameter :a do
546
+ type :number
547
+ required true
548
+ end
549
+
550
+ parameter :b do
551
+ type :number
552
+ required true
553
+ end
554
+
555
+ execute do |params|
556
+ params['a'] + params['b']
557
+ end
558
+ end
559
+ end
560
+
561
+ it 'adds numbers correctly' do
562
+ tool = mcp_def.tools['add']
563
+ result = tool.call('a' => 5, 'b' => 3)
564
+ expect(result).to eq(8)
565
+ end
566
+
567
+ it 'validates required parameters' do
568
+ tool = mcp_def.tools['add']
569
+ expect {
570
+ tool.call('a' => 5) # Missing 'b'
571
+ }.to raise_error(ArgumentError)
572
+ end
573
+ end
574
+ ```
575
+
576
+ ### Integration Testing Webhooks
577
+
578
+ ```ruby
579
+ RSpec.describe 'Webhook Integration' do
580
+ include Rack::Test::Methods
581
+
582
+ let(:agent) { create_agent_with_webhook }
583
+ let(:app) { agent.web_server.rack_app }
584
+
585
+ it 'handles webhook requests' do
586
+ post '/webhook', {
587
+ event: 'test',
588
+ data: { key: 'value' }
589
+ }.to_json, {
590
+ 'CONTENT_TYPE' => 'application/json',
591
+ 'X-Signature' => generate_signature
592
+ }
593
+
594
+ expect(last_response.status).to eq(200)
595
+ end
596
+
597
+ it 'rejects unauthorized requests' do
598
+ post '/webhook', {}, {
599
+ 'CONTENT_TYPE' => 'application/json'
600
+ # Missing signature
601
+ }
602
+
603
+ expect(last_response.status).to eq(401)
604
+ end
605
+ end
606
+ ```
607
+
608
+ ### Load Testing
609
+
610
+ ```bash
611
+ # Use Apache Bench for simple load tests
612
+ ab -n 1000 -c 10 -T application/json \
613
+ -p request.json \
614
+ http://localhost:8080/v1/chat/completions
615
+
616
+ # Use k6 for more sophisticated tests
617
+ k6 run load-test.js
618
+ ```
619
+
620
+ k6 script:
621
+ ```javascript
622
+ import http from 'k6/http';
623
+ import { check } from 'k6';
624
+
625
+ export const options = {
626
+ vus: 10,
627
+ duration: '30s',
628
+ };
629
+
630
+ export default function () {
631
+ const payload = JSON.stringify({
632
+ model: 'test-model',
633
+ messages: [{ role: 'user', content: 'Hello' }],
634
+ });
635
+
636
+ const params = {
637
+ headers: { 'Content-Type': 'application/json' },
638
+ };
639
+
640
+ const res = http.post('http://localhost:8080/v1/chat/completions', payload, params);
641
+
642
+ check(res, {
643
+ 'status is 200': (r) => r.status === 200,
644
+ 'response time < 500ms': (r) => r.timings.duration < 500,
645
+ });
646
+ }
647
+ ```
648
+
649
+ ## Debugging Tips
650
+
651
+ ### Enable Debug Logging
652
+
653
+ ```bash
654
+ # Set environment variable
655
+ export DEBUG=true
656
+ # or
657
+ export MCP_DEBUG=true
658
+
659
+ # Run agent
660
+ ruby agent.rb
661
+ ```
662
+
663
+ In code:
664
+ ```ruby
665
+ tool "debug_tool" do
666
+ execute do |params|
667
+ if ENV['DEBUG']
668
+ puts "Params: #{params.inspect}"
669
+ end
670
+
671
+ result = process(params)
672
+
673
+ if ENV['DEBUG']
674
+ puts "Result: #{result.inspect}"
675
+ end
676
+
677
+ result
678
+ end
679
+ end
680
+ ```
681
+
682
+ ### Structured Logging
683
+
684
+ ```ruby
685
+ require 'logger'
686
+
687
+ logger = Logger.new(STDOUT)
688
+ logger.level = ENV['LOG_LEVEL'] || Logger::INFO
689
+ logger.formatter = proc do |severity, datetime, progname, msg|
690
+ {
691
+ timestamp: datetime.iso8601,
692
+ severity: severity,
693
+ component: progname,
694
+ message: msg
695
+ }.to_json + "\n"
696
+ end
697
+
698
+ # In agent
699
+ step :process do
700
+ execute do |context|
701
+ logger.info("Processing started", user_id: context[:user_id])
702
+ result = process(context)
703
+ logger.info("Processing completed", duration: Time.now - start_time)
704
+ result
705
+ end
706
+ end
707
+ ```
708
+
709
+ ### Trace Workflow Execution
710
+
711
+ ```ruby
712
+ workflow do
713
+ before_step do |step_name|
714
+ puts "[#{Time.now}] Starting step: #{step_name}"
715
+ end
716
+
717
+ after_step do |step_name, result|
718
+ puts "[#{Time.now}] Completed step: #{step_name}"
719
+ puts "Result: #{result.inspect}"
720
+ end
721
+
722
+ on_error do |step_name, error|
723
+ puts "[#{Time.now}] Error in step #{step_name}: #{error.message}"
724
+ puts error.backtrace.join("\n")
725
+ end
726
+ end
727
+ ```
728
+
729
+ ### Monitor Resource Usage
730
+
731
+ ```ruby
732
+ require 'benchmark'
733
+
734
+ step :heavy_processing do
735
+ execute do |context|
736
+ memory_before = `ps -o rss= -p #{Process.pid}`.to_i
737
+
738
+ result = Benchmark.measure do
739
+ # Heavy processing
740
+ process_large_dataset(context[:data])
741
+ end
742
+
743
+ memory_after = `ps -o rss= -p #{Process.pid}`.to_i
744
+ memory_used = (memory_after - memory_before) / 1024.0 # MB
745
+
746
+ logger.info(
747
+ "Step completed",
748
+ duration: result.real,
749
+ memory_mb: memory_used
750
+ )
751
+ end
752
+ end
753
+ ```
754
+
755
+ ### Test in Isolation
756
+
757
+ ```ruby
758
+ # Test workflow steps independently
759
+ step_def = workflow.steps[:fetch_data]
760
+ result = step_def.execute(test_context)
761
+ puts result
762
+
763
+ # Test tools independently
764
+ tool = mcp_server.tools['process_csv']
765
+ result = tool.call('csv_data' => test_csv)
766
+ puts result
767
+ ```
768
+
769
+ ## Cost Optimization
770
+
771
+ ### Budget Management
772
+
773
+ **Multi-tier budgets:**
774
+ ```ruby
775
+ constraints do
776
+ hourly_budget 100 # $1/hour - prevents burst spending
777
+ daily_budget 1000 # $10/day - daily cap
778
+ requests_per_minute 30 # Rate limiting
779
+ end
780
+ ```
781
+
782
+ **For development:**
783
+ ```ruby
784
+ constraints do
785
+ daily_budget 100 # $1/day during development
786
+ token_budget 50000 # Limit token usage
787
+ end
788
+ ```
789
+
790
+ **For production:**
791
+ ```ruby
792
+ constraints do
793
+ hourly_budget 500 # $5/hour
794
+ daily_budget 5000 # $50/day
795
+ token_budget 1000000 # 1M tokens/day
796
+ end
797
+ ```
798
+
799
+ ### Prompt Optimization
800
+
801
+ **Avoid verbose system prompts:**
802
+
803
+ **Bad: Excessive detail (wastes tokens)**
804
+ ```ruby
805
+ system_prompt <<~PROMPT
806
+ You are a helpful assistant. You should always be polite.
807
+ You should always be respectful. You should always provide
808
+ accurate information. You should always cite your sources.
809
+ You should always... (500 more words)
810
+ PROMPT
811
+ ```
812
+
813
+ **Good: Concise and clear**
814
+ ```ruby
815
+ system_prompt <<~PROMPT
816
+ You are a technical support expert. Provide clear, accurate
817
+ solutions with step-by-step instructions. Cite sources when
818
+ referencing documentation.
819
+ PROMPT
820
+ ```
821
+
822
+ ### Use Appropriate Models
823
+
824
+ ```ruby
825
+ # For simple tasks - use smaller/cheaper models
826
+ agent "simple-classifier" do
827
+ # Configure via LLM_MODEL env var
828
+ # Use claude-3-haiku or gpt-3.5-turbo for simple tasks
829
+ end
830
+
831
+ # For complex tasks - use advanced models
832
+ agent "complex-analyst" do
833
+ # Use claude-3-opus or gpt-4 for complex reasoning
834
+ end
835
+ ```
836
+
837
+ ### Cache When Possible
838
+
839
+ ```ruby
840
+ tool "expensive_lookup" do
841
+ execute do |params|
842
+ cache_key = "lookup:#{params['query']}"
843
+
844
+ # Check cache
845
+ cached = Cache.get(cache_key)
846
+ return cached if cached
847
+
848
+ # Expensive operation
849
+ result = complex_api_call(params['query'])
850
+
851
+ # Cache for 1 hour
852
+ Cache.set(cache_key, result, ttl: 3600)
853
+
854
+ result
855
+ end
856
+ end
857
+ ```
858
+
859
+ ### Limit Response Length
860
+
861
+ ```ruby
862
+ as_chat_endpoint do
863
+ max_tokens 1000 # Limit response length
864
+ system_prompt "Keep responses under 200 words"
865
+ end
866
+ ```
867
+
868
+ ## Production Deployment Checklist
869
+
870
+ ### Pre-Deployment
871
+
872
+ - [ ] All secrets stored in Kubernetes Secrets (not hardcoded)
873
+ - [ ] Budget constraints configured (`daily_budget`, `hourly_budget`)
874
+ - [ ] Rate limits set (`requests_per_minute`, `requests_per_hour`)
875
+ - [ ] Timeouts configured (`timeout` at agent and step level)
876
+ - [ ] PII filtering enabled (`blocked_patterns` for SSN, credit cards, etc.)
877
+ - [ ] Webhook authentication implemented (HMAC, API key, etc.)
878
+ - [ ] Input validation configured (`validate` blocks on webhooks)
879
+ - [ ] Resource limits set (`memory`, matching pod limits)
880
+ - [ ] Error handling implemented (try/catch in tools, `on_error` in workflows)
881
+ - [ ] Logging configured (structured JSON logs)
882
+ - [ ] Health checks responsive (`/health`, `/ready`)
883
+
884
+ ### Security
885
+
886
+ - [ ] No hardcoded secrets or API keys
887
+ - [ ] All webhooks authenticated
888
+ - [ ] HTTPS/TLS enabled (via Gateway/Ingress)
889
+ - [ ] Content-type validation on all endpoints
890
+ - [ ] Request size limits (`max_body_size`)
891
+ - [ ] Rate limiting configured
892
+ - [ ] PII patterns blocked
893
+ - [ ] Sensitive topics filtered
894
+ - [ ] API gateway/ingress authentication (for public endpoints)
895
+
896
+ ### Testing
897
+
898
+ - [ ] Unit tests for all tools
899
+ - [ ] Integration tests for webhooks
900
+ - [ ] Load tests performed (verify rate limits)
901
+ - [ ] Error handling tested
902
+ - [ ] Timeout behavior verified
903
+ - [ ] Budget limits tested
904
+ - [ ] Streaming tested (if using chat endpoints)
905
+
906
+ ### Monitoring
907
+
908
+ - [ ] Metrics exported (Prometheus, CloudWatch, etc.)
909
+ - [ ] Logs aggregated (ELK, Loki, CloudWatch Logs)
910
+ - [ ] Alerts configured:
911
+ - [ ] Budget approaching limit
912
+ - [ ] High error rate
913
+ - [ ] Rate limit exceeded
914
+ - [ ] Slow response times
915
+ - [ ] Pod crashes/restarts
916
+ - [ ] Dashboards created (Grafana, CloudWatch)
917
+ - [ ] On-call runbook prepared
918
+
919
+ ### Performance
920
+
921
+ - [ ] Resource requests/limits appropriate
922
+ - [ ] Timeouts tuned for workload
923
+ - [ ] Caching implemented for expensive operations
924
+ - [ ] Parallel processing used where applicable
925
+ - [ ] Database queries optimized
926
+ - [ ] Connection pooling configured
927
+
928
+ ### Cost Management
929
+
930
+ - [ ] Budget constraints enforced
931
+ - [ ] Token budgets set
932
+ - [ ] Prompt optimized for efficiency
933
+ - [ ] Appropriate model selected (not over-powered)
934
+ - [ ] Caching implemented
935
+ - [ ] Cost tracking enabled
936
+ - [ ] Alerts for cost overruns
937
+
938
+ ### Documentation
939
+
940
+ - [ ] Agent purpose documented
941
+ - [ ] Webhook endpoints documented
942
+ - [ ] Tool schemas documented
943
+ - [ ] Environment variables documented
944
+ - [ ] Runbook created
945
+ - [ ] Incident response plan
946
+ - [ ] Rollback procedure documented
947
+
948
+ ### Deployment
949
+
950
+ - [ ] Staging environment tested
951
+ - [ ] Gradual rollout plan (canary or blue/green)
952
+ - [ ] Rollback plan ready
953
+ - [ ] Monitoring verified in production
954
+ - [ ] Load tested at production scale
955
+ - [ ] Backup/DR plan in place
956
+
957
+ ### Post-Deployment
958
+
959
+ - [ ] Monitor metrics for first 24 hours
960
+ - [ ] Review error logs
961
+ - [ ] Verify budget tracking
962
+ - [ ] Check resource utilization
963
+ - [ ] Gather user feedback
964
+ - [ ] Tune parameters based on real usage
965
+ - [ ] Document lessons learned
966
+
967
+ ## Production Configuration Example
968
+
969
+ ```ruby
970
+ agent "production-agent" do
971
+ description "Production-ready agent with best practices"
972
+ mode :reactive
973
+
974
+ # Chat endpoint or webhook
975
+ as_chat_endpoint do
976
+ system_prompt <<~PROMPT
977
+ You are a customer support assistant.
978
+ Provide clear, helpful responses.
979
+ Escalate to human for sensitive issues.
980
+ PROMPT
981
+
982
+ model "support-v1"
983
+ temperature 0.7
984
+ max_tokens 1500
985
+ end
986
+
987
+ # Security
988
+ constraints do
989
+ # Budget controls
990
+ hourly_budget 500 # $5/hour
991
+ daily_budget 5000 # $50/day
992
+ token_budget 1000000 # 1M tokens/day
993
+
994
+ # Rate limiting
995
+ requests_per_minute 60
996
+ requests_per_hour 2000
997
+ requests_per_day 20000
998
+
999
+ # Timeouts
1000
+ timeout '30s'
1001
+
1002
+ # PII protection
1003
+ blocked_patterns [
1004
+ /\b\d{3}-\d{2}-\d{4}\b/, # SSN
1005
+ /\b\d{16}\b/, # Credit card
1006
+ /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/, # Phone
1007
+ /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i, # Email
1008
+ /password\s*[:=]/i, # Password
1009
+ ]
1010
+
1011
+ # Content safety
1012
+ blocked_topics [
1013
+ 'violence',
1014
+ 'hate-speech',
1015
+ 'illegal-activity'
1016
+ ]
1017
+ end
1018
+ end
1019
+ ```
1020
+
1021
+ Corresponding Kubernetes deployment:
1022
+ ```yaml
1023
+ apiVersion: apps/v1
1024
+ kind: Deployment
1025
+ metadata:
1026
+ name: production-agent
1027
+ spec:
1028
+ replicas: 3 # High availability
1029
+ selector:
1030
+ matchLabels:
1031
+ app: production-agent
1032
+ template:
1033
+ metadata:
1034
+ labels:
1035
+ app: production-agent
1036
+ spec:
1037
+ containers:
1038
+ - name: agent
1039
+ image: agent-runtime:v1.0.0
1040
+ env:
1041
+ - name: AGENT_NAME
1042
+ value: "production-agent"
1043
+ - name: ANTHROPIC_API_KEY
1044
+ valueFrom:
1045
+ secretKeyRef:
1046
+ name: agent-secrets
1047
+ key: anthropic-api-key
1048
+ - name: LOG_LEVEL
1049
+ value: "INFO"
1050
+ resources:
1051
+ requests:
1052
+ memory: "1Gi"
1053
+ cpu: "500m"
1054
+ limits:
1055
+ memory: "2Gi"
1056
+ cpu: "1000m"
1057
+ livenessProbe:
1058
+ httpGet:
1059
+ path: /health
1060
+ port: 8080
1061
+ initialDelaySeconds: 10
1062
+ periodSeconds: 30
1063
+ readinessProbe:
1064
+ httpGet:
1065
+ path: /ready
1066
+ port: 8080
1067
+ initialDelaySeconds: 5
1068
+ periodSeconds: 10
1069
+ ```
1070
+
1071
+ ## See Also
1072
+
1073
+ - [Agent Reference](agent-reference.md) - Complete agent DSL reference
1074
+ - [Workflows](workflows.md) - Workflow definition guide
1075
+ - [Constraints](constraints.md) - Resource and behavior limits
1076
+ - [Webhooks](webhooks.md) - Reactive agent configuration
1077
+ - [MCP Integration](mcp-integration.md) - Tool server capabilities
1078
+ - [Chat Endpoints](chat-endpoints.md) - OpenAI-compatible endpoint guide