language-operator 0.0.1 → 0.1.31

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 (120) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +125 -0
  3. data/CHANGELOG.md +88 -0
  4. data/Gemfile +8 -0
  5. data/Gemfile.lock +284 -0
  6. data/LICENSE +229 -21
  7. data/Makefile +82 -0
  8. data/README.md +3 -11
  9. data/Rakefile +63 -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/SCHEMA_VERSION.md +250 -0
  16. data/docs/dsl/agent-reference.md +604 -0
  17. data/docs/dsl/best-practices.md +1078 -0
  18. data/docs/dsl/chat-endpoints.md +895 -0
  19. data/docs/dsl/constraints.md +671 -0
  20. data/docs/dsl/mcp-integration.md +1177 -0
  21. data/docs/dsl/webhooks.md +932 -0
  22. data/docs/dsl/workflows.md +744 -0
  23. data/lib/language_operator/agent/base.rb +110 -0
  24. data/lib/language_operator/agent/executor.rb +440 -0
  25. data/lib/language_operator/agent/instrumentation.rb +54 -0
  26. data/lib/language_operator/agent/metrics_tracker.rb +183 -0
  27. data/lib/language_operator/agent/safety/ast_validator.rb +272 -0
  28. data/lib/language_operator/agent/safety/audit_logger.rb +104 -0
  29. data/lib/language_operator/agent/safety/budget_tracker.rb +175 -0
  30. data/lib/language_operator/agent/safety/content_filter.rb +93 -0
  31. data/lib/language_operator/agent/safety/manager.rb +207 -0
  32. data/lib/language_operator/agent/safety/rate_limiter.rb +150 -0
  33. data/lib/language_operator/agent/safety/safe_executor.rb +127 -0
  34. data/lib/language_operator/agent/scheduler.rb +183 -0
  35. data/lib/language_operator/agent/telemetry.rb +116 -0
  36. data/lib/language_operator/agent/web_server.rb +610 -0
  37. data/lib/language_operator/agent/webhook_authenticator.rb +226 -0
  38. data/lib/language_operator/agent.rb +149 -0
  39. data/lib/language_operator/cli/commands/agent.rb +1205 -0
  40. data/lib/language_operator/cli/commands/cluster.rb +371 -0
  41. data/lib/language_operator/cli/commands/install.rb +404 -0
  42. data/lib/language_operator/cli/commands/model.rb +266 -0
  43. data/lib/language_operator/cli/commands/persona.rb +393 -0
  44. data/lib/language_operator/cli/commands/quickstart.rb +22 -0
  45. data/lib/language_operator/cli/commands/status.rb +143 -0
  46. data/lib/language_operator/cli/commands/system.rb +772 -0
  47. data/lib/language_operator/cli/commands/tool.rb +537 -0
  48. data/lib/language_operator/cli/commands/use.rb +47 -0
  49. data/lib/language_operator/cli/errors/handler.rb +180 -0
  50. data/lib/language_operator/cli/errors/suggestions.rb +176 -0
  51. data/lib/language_operator/cli/formatters/code_formatter.rb +77 -0
  52. data/lib/language_operator/cli/formatters/log_formatter.rb +288 -0
  53. data/lib/language_operator/cli/formatters/progress_formatter.rb +49 -0
  54. data/lib/language_operator/cli/formatters/status_formatter.rb +37 -0
  55. data/lib/language_operator/cli/formatters/table_formatter.rb +163 -0
  56. data/lib/language_operator/cli/formatters/value_formatter.rb +113 -0
  57. data/lib/language_operator/cli/helpers/cluster_context.rb +62 -0
  58. data/lib/language_operator/cli/helpers/cluster_validator.rb +101 -0
  59. data/lib/language_operator/cli/helpers/editor_helper.rb +58 -0
  60. data/lib/language_operator/cli/helpers/kubeconfig_validator.rb +167 -0
  61. data/lib/language_operator/cli/helpers/pastel_helper.rb +24 -0
  62. data/lib/language_operator/cli/helpers/resource_dependency_checker.rb +74 -0
  63. data/lib/language_operator/cli/helpers/schedule_builder.rb +108 -0
  64. data/lib/language_operator/cli/helpers/user_prompts.rb +69 -0
  65. data/lib/language_operator/cli/main.rb +236 -0
  66. data/lib/language_operator/cli/templates/tools/generic.yaml +66 -0
  67. data/lib/language_operator/cli/wizards/agent_wizard.rb +246 -0
  68. data/lib/language_operator/cli/wizards/quickstart_wizard.rb +588 -0
  69. data/lib/language_operator/client/base.rb +214 -0
  70. data/lib/language_operator/client/config.rb +136 -0
  71. data/lib/language_operator/client/cost_calculator.rb +37 -0
  72. data/lib/language_operator/client/mcp_connector.rb +123 -0
  73. data/lib/language_operator/client.rb +19 -0
  74. data/lib/language_operator/config/cluster_config.rb +101 -0
  75. data/lib/language_operator/config/tool_patterns.yaml +57 -0
  76. data/lib/language_operator/config/tool_registry.rb +96 -0
  77. data/lib/language_operator/config.rb +138 -0
  78. data/lib/language_operator/dsl/adapter.rb +124 -0
  79. data/lib/language_operator/dsl/agent_context.rb +90 -0
  80. data/lib/language_operator/dsl/agent_definition.rb +427 -0
  81. data/lib/language_operator/dsl/chat_endpoint_definition.rb +115 -0
  82. data/lib/language_operator/dsl/config.rb +119 -0
  83. data/lib/language_operator/dsl/context.rb +50 -0
  84. data/lib/language_operator/dsl/execution_context.rb +47 -0
  85. data/lib/language_operator/dsl/helpers.rb +109 -0
  86. data/lib/language_operator/dsl/http.rb +184 -0
  87. data/lib/language_operator/dsl/mcp_server_definition.rb +73 -0
  88. data/lib/language_operator/dsl/parameter_definition.rb +124 -0
  89. data/lib/language_operator/dsl/registry.rb +36 -0
  90. data/lib/language_operator/dsl/schema.rb +1102 -0
  91. data/lib/language_operator/dsl/shell.rb +125 -0
  92. data/lib/language_operator/dsl/tool_definition.rb +112 -0
  93. data/lib/language_operator/dsl/webhook_authentication.rb +114 -0
  94. data/lib/language_operator/dsl/webhook_definition.rb +106 -0
  95. data/lib/language_operator/dsl/workflow_definition.rb +259 -0
  96. data/lib/language_operator/dsl.rb +161 -0
  97. data/lib/language_operator/errors.rb +60 -0
  98. data/lib/language_operator/kubernetes/client.rb +279 -0
  99. data/lib/language_operator/kubernetes/resource_builder.rb +194 -0
  100. data/lib/language_operator/loggable.rb +47 -0
  101. data/lib/language_operator/logger.rb +141 -0
  102. data/lib/language_operator/retry.rb +123 -0
  103. data/lib/language_operator/retryable.rb +132 -0
  104. data/lib/language_operator/templates/README.md +23 -0
  105. data/lib/language_operator/templates/examples/agent_synthesis.tmpl +115 -0
  106. data/lib/language_operator/templates/examples/persona_distillation.tmpl +19 -0
  107. data/lib/language_operator/templates/schema/.gitkeep +0 -0
  108. data/lib/language_operator/templates/schema/CHANGELOG.md +93 -0
  109. data/lib/language_operator/templates/schema/agent_dsl_openapi.yaml +306 -0
  110. data/lib/language_operator/templates/schema/agent_dsl_schema.json +452 -0
  111. data/lib/language_operator/tool_loader.rb +242 -0
  112. data/lib/language_operator/validators.rb +170 -0
  113. data/lib/language_operator/version.rb +1 -1
  114. data/lib/language_operator.rb +65 -3
  115. data/requirements/tasks/challenge.md +9 -0
  116. data/requirements/tasks/iterate.md +36 -0
  117. data/requirements/tasks/optimize.md +21 -0
  118. data/requirements/tasks/tag.md +5 -0
  119. data/test_agent_dsl.rb +108 -0
  120. metadata +507 -20
@@ -0,0 +1,932 @@
1
+ # Webhook Guide
2
+
3
+ Complete guide to configuring webhook endpoints for reactive agents.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Overview](#overview)
8
+ - [Basic Webhook Configuration](#basic-webhook-configuration)
9
+ - [HTTP Methods](#http-methods)
10
+ - [Authentication](#authentication)
11
+ - [Request Validation](#request-validation)
12
+ - [Event Handling](#event-handling)
13
+ - [Complete Examples](#complete-examples)
14
+
15
+ ## Overview
16
+
17
+ Webhooks enable agents to respond to external events from services like GitHub, Stripe, Slack, and custom applications.
18
+
19
+ **Key Features:**
20
+ - Multiple authentication methods (HMAC, API key, Bearer token, Basic auth)
21
+ - Request validation (headers, content-type, custom rules)
22
+ - Automatic routing via UUID-based subdomains
23
+ - Integration with workflow execution
24
+
25
+ ## Basic Webhook Configuration
26
+
27
+ Define a webhook endpoint in a reactive agent:
28
+
29
+ ```ruby
30
+ agent "webhook-handler" do
31
+ description "Handle webhook events"
32
+
33
+ mode :reactive
34
+
35
+ webhook "/events" do
36
+ method :post
37
+ # Additional configuration...
38
+ end
39
+
40
+ on_webhook_event do |event|
41
+ # Process the event
42
+ puts "Received: #{event.inspect}"
43
+ end
44
+ end
45
+ ```
46
+
47
+ **URL Structure:**
48
+ Each agent gets a unique subdomain based on its UUID:
49
+ ```
50
+ https://<agent-uuid>.webhooks.your-domain.com/events
51
+ ```
52
+
53
+ The operator automatically creates routing for this subdomain.
54
+
55
+ ## HTTP Methods
56
+
57
+ Specify which HTTP methods the webhook accepts:
58
+
59
+ ### Single Method
60
+
61
+ ```ruby
62
+ webhook "/github/pr" do
63
+ method :post # Only POST requests
64
+ end
65
+ ```
66
+
67
+ ### Multiple Methods
68
+
69
+ ```ruby
70
+ webhook "/api/data" do
71
+ methods [:get, :post, :put] # Accept GET, POST, or PUT
72
+ end
73
+ ```
74
+
75
+ **Supported methods:**
76
+ - `:get`
77
+ - `:post`
78
+ - `:put`
79
+ - `:delete`
80
+ - `:patch`
81
+ - `:head`
82
+ - `:options`
83
+
84
+ ## Authentication
85
+
86
+ Webhooks support multiple authentication methods to verify request origin.
87
+
88
+ ### HMAC Signature Verification
89
+
90
+ Verify requests using HMAC signatures (GitHub, Stripe style):
91
+
92
+ ```ruby
93
+ webhook "/github/events" do
94
+ method :post
95
+
96
+ authenticate do
97
+ verify_signature(
98
+ header: 'X-Hub-Signature-256',
99
+ secret: ENV['GITHUB_WEBHOOK_SECRET'],
100
+ algorithm: :sha256
101
+ )
102
+ end
103
+ end
104
+ ```
105
+
106
+ **Parameters:**
107
+ - `header` (String): HTTP header containing the signature
108
+ - `secret` (String): Shared secret for verification
109
+ - `algorithm` (Symbol): Hash algorithm (`:sha1`, `:sha256`, `:sha512`)
110
+
111
+ **How it works:**
112
+ 1. Receiver computes HMAC of request body using secret
113
+ 2. Compares computed signature with header value
114
+ 3. Rejects request if signatures don't match
115
+
116
+ **Common Patterns:**
117
+
118
+ GitHub webhooks:
119
+ ```ruby
120
+ verify_signature(
121
+ header: 'X-Hub-Signature-256',
122
+ secret: ENV['GITHUB_WEBHOOK_SECRET'],
123
+ algorithm: :sha256
124
+ )
125
+ ```
126
+
127
+ Stripe webhooks:
128
+ ```ruby
129
+ verify_signature(
130
+ header: 'Stripe-Signature',
131
+ secret: ENV['STRIPE_WEBHOOK_SECRET'],
132
+ algorithm: :sha256
133
+ )
134
+ ```
135
+
136
+ ### API Key Authentication
137
+
138
+ Verify requests using API keys in headers or query parameters:
139
+
140
+ ```ruby
141
+ webhook "/api/events" do
142
+ method :post
143
+
144
+ authenticate do
145
+ verify_api_key(
146
+ header: 'X-API-Key',
147
+ secret: ENV['WEBHOOK_API_KEY']
148
+ )
149
+ end
150
+ end
151
+ ```
152
+
153
+ **Header-based:**
154
+ ```ruby
155
+ verify_api_key(
156
+ header: 'X-API-Key',
157
+ secret: ENV['API_KEY']
158
+ )
159
+ ```
160
+
161
+ **Query parameter:**
162
+ ```ruby
163
+ verify_api_key(
164
+ param: 'api_key',
165
+ secret: ENV['API_KEY']
166
+ )
167
+ ```
168
+
169
+ ### Bearer Token Authentication
170
+
171
+ OAuth-style bearer token authentication:
172
+
173
+ ```ruby
174
+ webhook "/api/events" do
175
+ method :post
176
+
177
+ authenticate do
178
+ verify_bearer_token(
179
+ token: ENV['BEARER_TOKEN']
180
+ )
181
+ end
182
+ end
183
+ ```
184
+
185
+ **Expected header:**
186
+ ```
187
+ Authorization: Bearer <token>
188
+ ```
189
+
190
+ ### Basic Auth
191
+
192
+ HTTP Basic Authentication:
193
+
194
+ ```ruby
195
+ webhook "/secure/endpoint" do
196
+ method :post
197
+
198
+ authenticate do
199
+ basic_auth(
200
+ username: ENV['WEBHOOK_USERNAME'],
201
+ password: ENV['WEBHOOK_PASSWORD']
202
+ )
203
+ end
204
+ end
205
+ ```
206
+
207
+ **Expected header:**
208
+ ```
209
+ Authorization: Basic <base64(username:password)>
210
+ ```
211
+
212
+ ### Custom Authentication
213
+
214
+ Implement custom authentication logic:
215
+
216
+ ```ruby
217
+ webhook "/custom/auth" do
218
+ method :post
219
+
220
+ authenticate do
221
+ custom do |request|
222
+ # Custom validation logic
223
+ api_key = request.headers['X-Custom-Auth']
224
+ valid_keys = ENV['VALID_API_KEYS'].split(',')
225
+
226
+ if valid_keys.include?(api_key)
227
+ true # Authentication succeeded
228
+ else
229
+ false # Authentication failed
230
+ end
231
+ end
232
+ end
233
+ end
234
+ ```
235
+
236
+ ### Composite Authentication
237
+
238
+ Require multiple authentication methods (all must pass):
239
+
240
+ ```ruby
241
+ webhook "/highly-secure" do
242
+ method :post
243
+
244
+ authenticate do
245
+ all_of do
246
+ verify_api_key header: 'X-API-Key', secret: ENV['API_KEY']
247
+ verify_signature header: 'X-Signature', secret: ENV['HMAC_SECRET'], algorithm: :sha256
248
+ end
249
+ end
250
+ end
251
+ ```
252
+
253
+ Accept any of multiple authentication methods (any one passes):
254
+
255
+ ```ruby
256
+ webhook "/flexible-auth" do
257
+ method :post
258
+
259
+ authenticate do
260
+ any_of do
261
+ verify_api_key header: 'X-API-Key', secret: ENV['API_KEY']
262
+ verify_bearer_token token: ENV['BEARER_TOKEN']
263
+ basic_auth username: ENV['USERNAME'], password: ENV['PASSWORD']
264
+ end
265
+ end
266
+ end
267
+ ```
268
+
269
+ ## Request Validation
270
+
271
+ Validate incoming requests beyond authentication.
272
+
273
+ ### Content-Type Validation
274
+
275
+ Require specific content types:
276
+
277
+ ```ruby
278
+ webhook "/json-only" do
279
+ method :post
280
+
281
+ validate do
282
+ content_type 'application/json'
283
+ end
284
+ end
285
+ ```
286
+
287
+ **Multiple acceptable types:**
288
+ ```ruby
289
+ validate do
290
+ content_type ['application/json', 'application/x-www-form-urlencoded']
291
+ end
292
+ ```
293
+
294
+ ### Header Validation
295
+
296
+ Require specific headers to be present:
297
+
298
+ ```ruby
299
+ webhook "/strict" do
300
+ method :post
301
+
302
+ validate do
303
+ require_headers ['X-Event-Type', 'X-Request-ID']
304
+ end
305
+ end
306
+ ```
307
+
308
+ **Header value validation:**
309
+ ```ruby
310
+ validate do
311
+ header_matches 'X-Event-Type', /^(push|pull_request|issues)$/
312
+ end
313
+ ```
314
+
315
+ ### Request Size Limits
316
+
317
+ Limit request body size:
318
+
319
+ ```ruby
320
+ webhook "/limited" do
321
+ method :post
322
+
323
+ validate do
324
+ max_body_size '1MB' # Reject requests larger than 1MB
325
+ end
326
+ end
327
+ ```
328
+
329
+ **Supported formats:**
330
+ - `'1KB'` - 1 Kilobyte
331
+ - `'500KB'` - 500 Kilobytes
332
+ - `'1MB'` - 1 Megabyte
333
+ - `'10MB'` - 10 Megabytes
334
+
335
+ ### Custom Validation
336
+
337
+ Implement custom validation rules:
338
+
339
+ ```ruby
340
+ webhook "/custom-validation" do
341
+ method :post
342
+
343
+ validate do
344
+ custom do |request|
345
+ # Parse and validate request body
346
+ begin
347
+ body = JSON.parse(request.body.read)
348
+ body.key?('event_type') && body.key?('data')
349
+ rescue JSON::ParserError
350
+ false
351
+ end
352
+ end
353
+ end
354
+ end
355
+ ```
356
+
357
+ ### Combined Validation
358
+
359
+ ```ruby
360
+ webhook "/comprehensive-validation" do
361
+ method :post
362
+
363
+ validate do
364
+ content_type 'application/json'
365
+ max_body_size '5MB'
366
+ require_headers ['X-Event-Type', 'X-Request-ID']
367
+
368
+ custom do |request|
369
+ # Additional custom checks
370
+ event_type = request.headers['X-Event-Type']
371
+ ['user.created', 'user.updated', 'user.deleted'].include?(event_type)
372
+ end
373
+ end
374
+ end
375
+ ```
376
+
377
+ ## Event Handling
378
+
379
+ Process webhook events in your agent.
380
+
381
+ ### Basic Event Handler
382
+
383
+ ```ruby
384
+ agent "event-processor" do
385
+ mode :reactive
386
+
387
+ webhook "/events" do
388
+ method :post
389
+ end
390
+
391
+ on_webhook_event do |event|
392
+ puts "Event received: #{event['type']}"
393
+
394
+ # Access event data
395
+ user_id = event.dig('data', 'user_id')
396
+ action = event['action']
397
+
398
+ # Perform actions...
399
+ end
400
+ end
401
+ ```
402
+
403
+ ### Event Handler with Workflow
404
+
405
+ Trigger workflows from webhook events:
406
+
407
+ ```ruby
408
+ agent "github-pr-handler" do
409
+ mode :reactive
410
+
411
+ webhook "/github/pr" do
412
+ method :post
413
+ authenticate do
414
+ verify_signature(
415
+ header: 'X-Hub-Signature-256',
416
+ secret: ENV['GITHUB_WEBHOOK_SECRET'],
417
+ algorithm: :sha256
418
+ )
419
+ end
420
+ end
421
+
422
+ on_webhook_event do |event|
423
+ # Event data available in workflow context
424
+ @event_data = event
425
+ end
426
+
427
+ workflow do
428
+ step :extract_pr_info do
429
+ execute do |context|
430
+ pr = context[:event].dig('pull_request')
431
+ {
432
+ number: pr['number'],
433
+ title: pr['title'],
434
+ author: pr.dig('user', 'login'),
435
+ diff_url: pr['diff_url']
436
+ }
437
+ end
438
+ end
439
+
440
+ step :fetch_diff do
441
+ depends_on :extract_pr_info
442
+ tool 'http_get'
443
+ params url: '{extract_pr_info.diff_url}'
444
+ end
445
+
446
+ step :review do
447
+ depends_on :fetch_diff
448
+ prompt "Review this pull request code: {fetch_diff.output}"
449
+ end
450
+
451
+ step :post_comment do
452
+ depends_on :review
453
+ tool 'github_api'
454
+ params(
455
+ action: 'create_comment',
456
+ issue_number: '{extract_pr_info.number}',
457
+ body: '{review.output}'
458
+ )
459
+ end
460
+ end
461
+ end
462
+ ```
463
+
464
+ ### Event Filtering
465
+
466
+ Process only specific event types:
467
+
468
+ ```ruby
469
+ on_webhook_event do |event|
470
+ event_type = event['type']
471
+
472
+ case event_type
473
+ when 'pull_request.opened'
474
+ # Handle new PR
475
+ handle_new_pr(event)
476
+ when 'pull_request.closed'
477
+ # Handle closed PR
478
+ handle_closed_pr(event)
479
+ else
480
+ # Ignore other events
481
+ puts "Ignoring event type: #{event_type}"
482
+ end
483
+ end
484
+ ```
485
+
486
+ ## Complete Examples
487
+
488
+ ### GitHub Pull Request Reviewer
489
+
490
+ ```ruby
491
+ agent "github-pr-reviewer" do
492
+ description "Automatically review pull requests"
493
+
494
+ mode :reactive
495
+
496
+ persona <<~PERSONA
497
+ You are a senior software engineer conducting code reviews.
498
+ Focus on correctness, security, performance, and maintainability.
499
+ Provide constructive, specific feedback.
500
+ PERSONA
501
+
502
+ webhook "/github/pull-request" do
503
+ method :post
504
+
505
+ # GitHub webhook authentication
506
+ authenticate do
507
+ verify_signature(
508
+ header: 'X-Hub-Signature-256',
509
+ secret: ENV['GITHUB_WEBHOOK_SECRET'],
510
+ algorithm: :sha256
511
+ )
512
+ end
513
+
514
+ # Validate GitHub webhook format
515
+ validate do
516
+ content_type 'application/json'
517
+ require_headers ['X-GitHub-Event', 'X-GitHub-Delivery']
518
+ max_body_size '10MB'
519
+ end
520
+ end
521
+
522
+ on_webhook_event do |event|
523
+ # Filter to only PR open/sync events
524
+ gh_event = event.headers['X-GitHub-Event']
525
+ return unless gh_event == 'pull_request'
526
+
527
+ action = event.dig('body', 'action')
528
+ return unless ['opened', 'synchronize'].include?(action)
529
+
530
+ # Event passes filters, workflow will execute
531
+ end
532
+
533
+ workflow do
534
+ step :extract_pr do
535
+ execute do |context|
536
+ pr = context[:event].dig('body', 'pull_request')
537
+ {
538
+ number: pr['number'],
539
+ title: pr['title'],
540
+ body: pr['body'],
541
+ diff_url: pr['diff_url'],
542
+ repo_full_name: context[:event].dig('body', 'repository', 'full_name')
543
+ }
544
+ end
545
+ end
546
+
547
+ step :fetch_diff do
548
+ depends_on :extract_pr
549
+ tool 'github_api'
550
+ params(
551
+ action: 'get_pr_diff',
552
+ repo: '{extract_pr.repo_full_name}',
553
+ pr_number: '{extract_pr.number}'
554
+ )
555
+ end
556
+
557
+ step :review_code do
558
+ depends_on [:extract_pr, :fetch_diff]
559
+ prompt <<~PROMPT
560
+ Review this pull request:
561
+
562
+ Title: {extract_pr.title}
563
+ Description: {extract_pr.body}
564
+
565
+ Code changes:
566
+ {fetch_diff.output}
567
+
568
+ Provide a detailed code review covering:
569
+ 1. Code correctness
570
+ 2. Security issues
571
+ 3. Performance concerns
572
+ 4. Best practices
573
+ 5. Suggestions for improvement
574
+
575
+ Be specific and constructive.
576
+ PROMPT
577
+ end
578
+
579
+ step :post_review do
580
+ depends_on [:extract_pr, :review_code]
581
+ tool 'github_api'
582
+ params(
583
+ action: 'create_review_comment',
584
+ repo: '{extract_pr.repo_full_name}',
585
+ pr_number: '{extract_pr.number}',
586
+ body: '{review_code.output}'
587
+ )
588
+ end
589
+ end
590
+
591
+ constraints do
592
+ timeout '10m'
593
+ requests_per_hour 100
594
+ daily_budget 1000 # $10/day
595
+ end
596
+ end
597
+ ```
598
+
599
+ ### Stripe Payment Processor
600
+
601
+ ```ruby
602
+ agent "stripe-payment-handler" do
603
+ description "Process Stripe payment events"
604
+
605
+ mode :reactive
606
+
607
+ webhook "/stripe/events" do
608
+ method :post
609
+
610
+ # Stripe webhook signature verification
611
+ authenticate do
612
+ verify_signature(
613
+ header: 'Stripe-Signature',
614
+ secret: ENV['STRIPE_WEBHOOK_SECRET'],
615
+ algorithm: :sha256
616
+ )
617
+ end
618
+
619
+ validate do
620
+ content_type 'application/json'
621
+ end
622
+ end
623
+
624
+ on_webhook_event do |event|
625
+ event_type = event.dig('body', 'type')
626
+
627
+ case event_type
628
+ when 'payment_intent.succeeded'
629
+ handle_successful_payment(event)
630
+ when 'payment_intent.payment_failed'
631
+ handle_failed_payment(event)
632
+ when 'customer.subscription.created'
633
+ handle_new_subscription(event)
634
+ else
635
+ puts "Unhandled event: #{event_type}"
636
+ end
637
+ end
638
+
639
+ workflow do
640
+ step :extract_payment do
641
+ execute do |context|
642
+ event_data = context[:event].dig('body', 'data', 'object')
643
+ {
644
+ payment_id: event_data['id'],
645
+ amount: event_data['amount'],
646
+ currency: event_data['currency'],
647
+ customer_id: event_data['customer'],
648
+ status: event_data['status']
649
+ }
650
+ end
651
+ end
652
+
653
+ step :update_database do
654
+ depends_on :extract_payment
655
+ tool 'database_update'
656
+ params(
657
+ table: 'payments',
658
+ where: { stripe_payment_id: '{extract_payment.payment_id}' },
659
+ data: {
660
+ status: '{extract_payment.status}',
661
+ updated_at: 'NOW()'
662
+ }
663
+ )
664
+ end
665
+
666
+ step :send_confirmation do
667
+ depends_on :extract_payment
668
+ tool 'send_email'
669
+ params(
670
+ to: '{extract_payment.customer_email}',
671
+ subject: 'Payment Confirmation',
672
+ body: 'Your payment of {extract_payment.amount} {extract_payment.currency} was successful'
673
+ )
674
+ end
675
+ end
676
+
677
+ constraints do
678
+ timeout '30s' # Process quickly
679
+ requests_per_minute 100 # High throughput
680
+ hourly_budget 100 # $1/hour
681
+ end
682
+ end
683
+ ```
684
+
685
+ ### Custom Application Webhook
686
+
687
+ ```ruby
688
+ agent "custom-app-handler" do
689
+ description "Handle events from custom application"
690
+
691
+ mode :reactive
692
+
693
+ webhook "/app/events" do
694
+ methods [:post, :put]
695
+
696
+ # Flexible authentication
697
+ authenticate do
698
+ any_of do
699
+ verify_api_key header: 'X-API-Key', secret: ENV['APP_API_KEY']
700
+ verify_bearer_token token: ENV['APP_BEARER_TOKEN']
701
+ end
702
+ end
703
+
704
+ validate do
705
+ content_type 'application/json'
706
+ max_body_size '5MB'
707
+
708
+ custom do |request|
709
+ # Ensure required fields present
710
+ body = JSON.parse(request.body.read)
711
+ body['event_type'] && body['timestamp'] && body['data']
712
+ rescue JSON::ParserError
713
+ false
714
+ end
715
+ end
716
+ end
717
+
718
+ on_webhook_event do |event|
719
+ # Process event...
720
+ end
721
+
722
+ constraints do
723
+ timeout '1m'
724
+ requests_per_minute 50
725
+ daily_budget 500
726
+ end
727
+ end
728
+ ```
729
+
730
+ ### Slack Command Handler
731
+
732
+ ```ruby
733
+ agent "slack-bot" do
734
+ description "Respond to Slack slash commands"
735
+
736
+ mode :reactive
737
+
738
+ webhook "/slack/commands" do
739
+ method :post
740
+
741
+ # Slack uses token verification
742
+ authenticate do
743
+ custom do |request|
744
+ token = request.params['token']
745
+ token == ENV['SLACK_VERIFICATION_TOKEN']
746
+ end
747
+ end
748
+
749
+ validate do
750
+ content_type 'application/x-www-form-urlencoded'
751
+ end
752
+ end
753
+
754
+ on_webhook_event do |event|
755
+ command = event['command'] # e.g., '/deploy'
756
+ text = event['text'] # command arguments
757
+ user = event['user_name']
758
+
759
+ # Process command...
760
+ end
761
+
762
+ workflow do
763
+ step :parse_command do
764
+ execute do |context|
765
+ command = context[:event]['command']
766
+ text = context[:event]['text']
767
+
768
+ {
769
+ command: command,
770
+ args: text.split(' '),
771
+ user: context[:event]['user_name']
772
+ }
773
+ end
774
+ end
775
+
776
+ step :execute_command do
777
+ depends_on :parse_command
778
+ prompt "Execute this Slack command: {parse_command.command} {parse_command.args}"
779
+ end
780
+
781
+ step :respond_to_slack do
782
+ depends_on :execute_command
783
+ tool 'slack_respond'
784
+ params(
785
+ response_url: '{event.response_url}',
786
+ text: '{execute_command.output}'
787
+ )
788
+ end
789
+ end
790
+
791
+ constraints do
792
+ timeout '3s' # Slack requires fast responses
793
+ requests_per_minute 30
794
+ end
795
+ end
796
+ ```
797
+
798
+ ## Security Best Practices
799
+
800
+ ### Always Use Authentication
801
+
802
+ Never expose webhooks without authentication:
803
+
804
+ ```ruby
805
+ # INSECURE - Don't do this
806
+ webhook "/insecure" do
807
+ method :post
808
+ # No authentication!
809
+ end
810
+
811
+ # SECURE - Always authenticate
812
+ webhook "/secure" do
813
+ method :post
814
+ authenticate do
815
+ verify_signature(...)
816
+ end
817
+ end
818
+ ```
819
+
820
+ ### Use HTTPS
821
+
822
+ Webhooks are automatically served over HTTPS via the Gateway. Ensure:
823
+ - TLS certificates are properly configured
824
+ - No HTTP fallback is enabled
825
+
826
+ ### Validate Request Size
827
+
828
+ Always limit request size to prevent DoS:
829
+
830
+ ```ruby
831
+ validate do
832
+ max_body_size '10MB'
833
+ end
834
+ ```
835
+
836
+ ### Store Secrets Securely
837
+
838
+ Use Kubernetes Secrets for webhook secrets:
839
+
840
+ ```yaml
841
+ apiVersion: v1
842
+ kind: Secret
843
+ metadata:
844
+ name: webhook-secrets
845
+ data:
846
+ github-webhook-secret: <base64-encoded-secret>
847
+ stripe-webhook-secret: <base64-encoded-secret>
848
+ ```
849
+
850
+ Reference in agent environment:
851
+
852
+ ```ruby
853
+ authenticate do
854
+ verify_signature(
855
+ secret: ENV['GITHUB_WEBHOOK_SECRET'] # From K8s Secret
856
+ )
857
+ end
858
+ ```
859
+
860
+ ### Implement Rate Limiting
861
+
862
+ Protect against abuse:
863
+
864
+ ```ruby
865
+ constraints do
866
+ requests_per_minute 30
867
+ requests_per_hour 500
868
+ end
869
+ ```
870
+
871
+ ### Log Webhook Activity
872
+
873
+ Enable audit logging for security monitoring:
874
+
875
+ ```ruby
876
+ on_webhook_event do |event|
877
+ # Log webhook receipt
878
+ AuditLog.record(
879
+ event: 'webhook_received',
880
+ source_ip: event.request.ip,
881
+ user_agent: event.request.user_agent,
882
+ payload_size: event.request.content_length
883
+ )
884
+
885
+ # Process event...
886
+ end
887
+ ```
888
+
889
+ ## Troubleshooting
890
+
891
+ ### Webhook Not Receiving Events
892
+
893
+ 1. **Check DNS**: Verify subdomain resolves correctly
894
+ ```bash
895
+ dig <agent-uuid>.webhooks.your-domain.com
896
+ ```
897
+
898
+ 2. **Check Gateway routing**: Verify HTTPRoute is created
899
+ ```bash
900
+ kubectl get httproute -n language-operator-system
901
+ ```
902
+
903
+ 3. **Check agent status**: Verify agent is running
904
+ ```bash
905
+ kubectl get languageagent <agent-name> -o yaml
906
+ ```
907
+
908
+ 4. **Check webhook URL**: Get the correct URL from agent status
909
+ ```bash
910
+ kubectl get languageagent <agent-name> -o jsonpath='{.status.webhookURLs}'
911
+ ```
912
+
913
+ ### Authentication Failures
914
+
915
+ 1. **Verify secret**: Ensure correct secret is configured
916
+ 2. **Check signature algorithm**: Ensure it matches the sender's algorithm
917
+ 3. **Inspect headers**: Log incoming headers to verify format
918
+ 4. **Test with curl**: Send a test request with correct authentication
919
+
920
+ ### Event Not Processing
921
+
922
+ 1. **Check filters**: Ensure `on_webhook_event` logic isn't filtering out events
923
+ 2. **Check logs**: Review agent logs for errors
924
+ 3. **Verify workflow**: Test workflow execution separately
925
+ 4. **Check constraints**: Ensure rate limits aren't being exceeded
926
+
927
+ ## See Also
928
+
929
+ - [Agent Reference](agent-reference.md) - Complete agent DSL reference
930
+ - [Workflows](workflows.md) - Workflow definition guide
931
+ - [Constraints](constraints.md) - Resource and behavior limits
932
+ - [Best Practices](best-practices.md) - Production deployment patterns