language-operator 0.1.61 → 0.1.62
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/.claude/commands/persona.md +9 -0
- data/.claude/commands/task.md +46 -1
- data/.rubocop.yml +13 -0
- data/.rubocop_custom/use_ux_helper.rb +44 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +12 -1
- data/Makefile +26 -7
- data/Makefile.common +50 -0
- data/bin/aictl +8 -1
- data/components/agent/Gemfile +1 -1
- data/components/agent/bin/langop-agent +7 -0
- data/docs/README.md +58 -0
- data/docs/{dsl/best-practices.md → best-practices.md} +4 -4
- data/docs/cli-reference.md +274 -0
- data/docs/{dsl/constraints.md → constraints.md} +5 -5
- data/docs/how-agents-work.md +156 -0
- data/docs/installation.md +218 -0
- data/docs/quickstart.md +299 -0
- data/docs/understanding-generated-code.md +265 -0
- data/docs/using-tools.md +457 -0
- data/docs/webhooks.md +509 -0
- data/examples/ux_helpers_demo.rb +296 -0
- data/lib/language_operator/agent/base.rb +11 -1
- data/lib/language_operator/agent/executor.rb +23 -6
- data/lib/language_operator/agent/safety/safe_executor.rb +41 -39
- data/lib/language_operator/agent/task_executor.rb +346 -63
- data/lib/language_operator/agent/web_server.rb +110 -14
- data/lib/language_operator/agent/webhook_authenticator.rb +39 -5
- data/lib/language_operator/agent.rb +88 -2
- data/lib/language_operator/cli/base_command.rb +17 -11
- data/lib/language_operator/cli/command_loader.rb +72 -0
- data/lib/language_operator/cli/commands/agent/base.rb +837 -0
- data/lib/language_operator/cli/commands/agent/code_operations.rb +102 -0
- data/lib/language_operator/cli/commands/agent/helpers/cluster_llm_client.rb +116 -0
- data/lib/language_operator/cli/commands/agent/helpers/code_parser.rb +115 -0
- data/lib/language_operator/cli/commands/agent/helpers/synthesis_watcher.rb +96 -0
- data/lib/language_operator/cli/commands/agent/learning.rb +289 -0
- data/lib/language_operator/cli/commands/agent/lifecycle.rb +102 -0
- data/lib/language_operator/cli/commands/agent/logs.rb +125 -0
- data/lib/language_operator/cli/commands/agent/workspace.rb +327 -0
- data/lib/language_operator/cli/commands/cluster.rb +129 -84
- data/lib/language_operator/cli/commands/install.rb +1 -1
- data/lib/language_operator/cli/commands/model/base.rb +215 -0
- data/lib/language_operator/cli/commands/model/test.rb +165 -0
- data/lib/language_operator/cli/commands/persona.rb +16 -34
- data/lib/language_operator/cli/commands/quickstart.rb +3 -2
- data/lib/language_operator/cli/commands/status.rb +40 -67
- data/lib/language_operator/cli/commands/system/base.rb +44 -0
- data/lib/language_operator/cli/commands/system/exec.rb +147 -0
- data/lib/language_operator/cli/commands/system/helpers/llm_synthesis.rb +183 -0
- data/lib/language_operator/cli/commands/system/helpers/pod_manager.rb +212 -0
- data/lib/language_operator/cli/commands/system/helpers/template_loader.rb +57 -0
- data/lib/language_operator/cli/commands/system/helpers/template_validator.rb +174 -0
- data/lib/language_operator/cli/commands/system/schema.rb +92 -0
- data/lib/language_operator/cli/commands/system/synthesis_template.rb +151 -0
- data/lib/language_operator/cli/commands/system/synthesize.rb +224 -0
- data/lib/language_operator/cli/commands/system/validate_template.rb +130 -0
- data/lib/language_operator/cli/commands/tool/base.rb +271 -0
- data/lib/language_operator/cli/commands/tool/install.rb +255 -0
- data/lib/language_operator/cli/commands/tool/search.rb +69 -0
- data/lib/language_operator/cli/commands/tool/test.rb +115 -0
- data/lib/language_operator/cli/commands/use.rb +29 -6
- data/lib/language_operator/cli/errors/handler.rb +20 -17
- data/lib/language_operator/cli/errors/suggestions.rb +3 -5
- data/lib/language_operator/cli/errors/thor_errors.rb +55 -0
- data/lib/language_operator/cli/formatters/code_formatter.rb +4 -11
- data/lib/language_operator/cli/formatters/log_formatter.rb +8 -15
- data/lib/language_operator/cli/formatters/progress_formatter.rb +6 -8
- data/lib/language_operator/cli/formatters/status_formatter.rb +26 -7
- data/lib/language_operator/cli/formatters/table_formatter.rb +47 -36
- data/lib/language_operator/cli/formatters/value_formatter.rb +75 -0
- data/lib/language_operator/cli/helpers/cluster_context.rb +5 -3
- data/lib/language_operator/cli/helpers/kubeconfig_validator.rb +2 -1
- data/lib/language_operator/cli/helpers/label_utils.rb +97 -0
- data/lib/language_operator/{ux/concerns/provider_helpers.rb → cli/helpers/provider_helper.rb} +10 -29
- data/lib/language_operator/cli/helpers/schedule_builder.rb +21 -1
- data/lib/language_operator/cli/helpers/user_prompts.rb +19 -11
- data/lib/language_operator/cli/helpers/ux_helper.rb +538 -0
- data/lib/language_operator/{ux/concerns/input_validation.rb → cli/helpers/validation_helper.rb} +13 -66
- data/lib/language_operator/cli/main.rb +50 -40
- data/lib/language_operator/cli/templates/tools/generic.yaml +3 -0
- data/lib/language_operator/cli/wizards/agent_wizard.rb +12 -20
- data/lib/language_operator/cli/wizards/model_wizard.rb +271 -0
- data/lib/language_operator/cli/wizards/quickstart_wizard.rb +8 -34
- data/lib/language_operator/client/base.rb +28 -0
- data/lib/language_operator/client/config.rb +4 -1
- data/lib/language_operator/client/mcp_connector.rb +1 -1
- data/lib/language_operator/config/cluster_config.rb +3 -2
- data/lib/language_operator/config.rb +38 -11
- data/lib/language_operator/constants/kubernetes_labels.rb +80 -0
- data/lib/language_operator/constants.rb +13 -0
- data/lib/language_operator/dsl/http.rb +127 -10
- data/lib/language_operator/dsl.rb +153 -6
- data/lib/language_operator/errors.rb +50 -0
- data/lib/language_operator/kubernetes/client.rb +11 -6
- data/lib/language_operator/kubernetes/resource_builder.rb +58 -84
- data/lib/language_operator/templates/schema/agent_dsl_openapi.yaml +1 -1
- data/lib/language_operator/templates/schema/agent_dsl_schema.json +1 -1
- data/lib/language_operator/type_coercion.rb +118 -34
- data/lib/language_operator/utils/secure_path.rb +74 -0
- data/lib/language_operator/utils.rb +7 -0
- data/lib/language_operator/validators.rb +54 -2
- data/lib/language_operator/version.rb +1 -1
- data/synth/001/Makefile +10 -2
- data/synth/001/agent.rb +16 -15
- data/synth/001/output.log +27 -10
- data/synth/002/Makefile +10 -2
- data/synth/003/Makefile +1 -1
- data/synth/003/README.md +205 -133
- data/synth/003/agent.optimized.rb +66 -0
- data/synth/003/agent.synthesized.rb +41 -0
- metadata +111 -35
- data/docs/dsl/agent-reference.md +0 -604
- data/docs/dsl/mcp-integration.md +0 -1177
- data/docs/dsl/webhooks.md +0 -932
- data/docs/dsl/workflows.md +0 -744
- data/lib/language_operator/cli/commands/agent.rb +0 -1712
- data/lib/language_operator/cli/commands/model.rb +0 -366
- data/lib/language_operator/cli/commands/system.rb +0 -1259
- data/lib/language_operator/cli/commands/tool.rb +0 -654
- data/lib/language_operator/cli/formatters/optimization_formatter.rb +0 -226
- data/lib/language_operator/cli/helpers/pastel_helper.rb +0 -24
- data/lib/language_operator/learning/adapters/base_adapter.rb +0 -149
- data/lib/language_operator/learning/adapters/jaeger_adapter.rb +0 -221
- data/lib/language_operator/learning/adapters/signoz_adapter.rb +0 -435
- data/lib/language_operator/learning/adapters/tempo_adapter.rb +0 -239
- data/lib/language_operator/learning/optimizer.rb +0 -319
- data/lib/language_operator/learning/pattern_detector.rb +0 -260
- data/lib/language_operator/learning/task_synthesizer.rb +0 -288
- data/lib/language_operator/learning/trace_analyzer.rb +0 -285
- data/lib/language_operator/templates/task_synthesis.tmpl +0 -98
- data/lib/language_operator/ux/base.rb +0 -81
- data/lib/language_operator/ux/concerns/README.md +0 -155
- data/lib/language_operator/ux/concerns/headings.rb +0 -90
- data/lib/language_operator/ux/create_agent.rb +0 -255
- data/lib/language_operator/ux/create_model.rb +0 -267
- data/lib/language_operator/ux/quickstart.rb +0 -594
- data/synth/003/agent.rb +0 -41
- data/synth/003/output.log +0 -68
- /data/docs/{architecture/agent-runtime.md → agent-internals.md} +0 -0
- /data/docs/{dsl/chat-endpoints.md → chat-endpoints.md} +0 -0
- /data/docs/{dsl/SCHEMA_VERSION.md → schema-versioning.md} +0 -0
data/docs/webhooks.md
ADDED
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
# Webhooks
|
|
2
|
+
|
|
3
|
+
Language Operator agents can respond to webhooks from GitHub, Stripe, Slack, and other services. This guide shows how webhook agents work and what they look like when synthesized.
|
|
4
|
+
|
|
5
|
+
## How Webhook Agents Work
|
|
6
|
+
|
|
7
|
+
When you describe an agent that responds to external events, Language Operator creates a reactive agent with webhook endpoints.
|
|
8
|
+
|
|
9
|
+
### Creating Webhook Agents
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
aictl agent create github-pr-reviewer
|
|
13
|
+
# Wizard asks:
|
|
14
|
+
# - What service sends webhooks? (GitHub, Stripe, Slack, custom)
|
|
15
|
+
# - What events should trigger the agent? (pull_request, push, etc.)
|
|
16
|
+
# - What should the agent do when triggered?
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Language Operator automatically:
|
|
20
|
+
1. Sets up secure webhook endpoints
|
|
21
|
+
2. Configures authentication (HMAC, API keys, etc.)
|
|
22
|
+
3. Handles payload parsing and validation
|
|
23
|
+
4. Routes events to your agent logic
|
|
24
|
+
|
|
25
|
+
## Webhook Agent Structure
|
|
26
|
+
|
|
27
|
+
### Basic Structure
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
agent "github-pr-reviewer" do
|
|
31
|
+
description "Reviews pull requests and provides feedback"
|
|
32
|
+
mode :reactive
|
|
33
|
+
|
|
34
|
+
# Webhook configuration
|
|
35
|
+
webhook do
|
|
36
|
+
endpoint "github"
|
|
37
|
+
authentication :hmac_sha256
|
|
38
|
+
secret ENV['GITHUB_WEBHOOK_SECRET']
|
|
39
|
+
events ['pull_request.opened', 'pull_request.synchronize']
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Event processing tasks
|
|
43
|
+
task :analyze_pr,
|
|
44
|
+
instructions: "analyze the pull request changes and identify issues",
|
|
45
|
+
inputs: { pr_number: 'integer', diff: 'string', files: 'array' },
|
|
46
|
+
outputs: { issues: 'array', suggestion: 'string' }
|
|
47
|
+
|
|
48
|
+
# Main webhook handler
|
|
49
|
+
main do |webhook_payload|
|
|
50
|
+
# Extract PR information
|
|
51
|
+
pr_data = execute_task(:extract_pr_info, inputs: webhook_payload)
|
|
52
|
+
|
|
53
|
+
# Analyze the changes
|
|
54
|
+
analysis = execute_task(:analyze_pr, inputs: pr_data)
|
|
55
|
+
|
|
56
|
+
# Post review comment
|
|
57
|
+
execute_task(:post_review, inputs: analysis.merge(pr_data))
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
output do |outputs|
|
|
61
|
+
# Results are handled by tasks (posting comments, etc.)
|
|
62
|
+
{ status: 'review_posted', timestamp: Time.now }
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Common Webhook Patterns
|
|
68
|
+
|
|
69
|
+
### GitHub Integration
|
|
70
|
+
|
|
71
|
+
**Pull Request Reviews**:
|
|
72
|
+
```ruby
|
|
73
|
+
agent "pr-reviewer" do
|
|
74
|
+
description "Automatically reviews pull requests for code quality"
|
|
75
|
+
mode :reactive
|
|
76
|
+
|
|
77
|
+
webhook do
|
|
78
|
+
endpoint "github"
|
|
79
|
+
authentication :hmac_sha256
|
|
80
|
+
events ['pull_request.opened', 'pull_request.synchronize']
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
task :fetch_pr_diff,
|
|
84
|
+
instructions: "get the diff and changed files for the pull request",
|
|
85
|
+
inputs: { pr_number: 'integer', repo: 'string' },
|
|
86
|
+
outputs: { diff: 'string', files: 'array' }
|
|
87
|
+
|
|
88
|
+
task :review_code,
|
|
89
|
+
instructions: "analyze code for bugs, style issues, and best practices",
|
|
90
|
+
inputs: { diff: 'string', files: 'array' },
|
|
91
|
+
outputs: { issues: 'array', overall_rating: 'string' }
|
|
92
|
+
|
|
93
|
+
task :post_review,
|
|
94
|
+
instructions: "post review comments on the pull request",
|
|
95
|
+
inputs: { pr_number: 'integer', issues: 'array', rating: 'string' },
|
|
96
|
+
outputs: { comment_posted: 'boolean' }
|
|
97
|
+
|
|
98
|
+
main do |webhook_payload|
|
|
99
|
+
pr_info = {
|
|
100
|
+
pr_number: webhook_payload['pull_request']['number'],
|
|
101
|
+
repo: webhook_payload['repository']['full_name']
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
diff_data = execute_task(:fetch_pr_diff, inputs: pr_info)
|
|
105
|
+
review = execute_task(:review_code, inputs: diff_data)
|
|
106
|
+
execute_task(:post_review, inputs: review.merge(pr_info))
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Issue Management**:
|
|
112
|
+
```ruby
|
|
113
|
+
agent "issue-triager" do
|
|
114
|
+
description "Automatically triages and labels GitHub issues"
|
|
115
|
+
mode :reactive
|
|
116
|
+
|
|
117
|
+
webhook do
|
|
118
|
+
endpoint "github"
|
|
119
|
+
events ['issues.opened']
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
task :classify_issue,
|
|
123
|
+
instructions: "classify issue type and priority based on title and description",
|
|
124
|
+
inputs: { title: 'string', body: 'string' },
|
|
125
|
+
outputs: { type: 'string', priority: 'string', labels: 'array' }
|
|
126
|
+
|
|
127
|
+
task :assign_issue,
|
|
128
|
+
instructions: "assign issue to appropriate team member based on classification",
|
|
129
|
+
inputs: { type: 'string', priority: 'string' },
|
|
130
|
+
outputs: { assignee: 'string' }
|
|
131
|
+
|
|
132
|
+
main do |webhook_payload|
|
|
133
|
+
issue_data = {
|
|
134
|
+
title: webhook_payload['issue']['title'],
|
|
135
|
+
body: webhook_payload['issue']['body']
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
classification = execute_task(:classify_issue, inputs: issue_data)
|
|
139
|
+
assignment = execute_task(:assign_issue, inputs: classification)
|
|
140
|
+
|
|
141
|
+
# Apply labels and assignment
|
|
142
|
+
execute_task(:update_issue, inputs: {
|
|
143
|
+
issue_number: webhook_payload['issue']['number'],
|
|
144
|
+
labels: classification[:labels],
|
|
145
|
+
assignee: assignment[:assignee]
|
|
146
|
+
})
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Stripe Integration
|
|
152
|
+
|
|
153
|
+
**Payment Processing**:
|
|
154
|
+
```ruby
|
|
155
|
+
agent "payment-processor" do
|
|
156
|
+
description "Handles successful payments and sends notifications"
|
|
157
|
+
mode :reactive
|
|
158
|
+
|
|
159
|
+
webhook do
|
|
160
|
+
endpoint "stripe"
|
|
161
|
+
authentication :stripe_signature
|
|
162
|
+
events ['payment_intent.succeeded']
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
task :extract_payment_info,
|
|
166
|
+
instructions: "extract customer and payment details from Stripe payload",
|
|
167
|
+
inputs: { stripe_payload: 'hash' },
|
|
168
|
+
outputs: { customer_id: 'string', amount: 'number', currency: 'string' }
|
|
169
|
+
|
|
170
|
+
task :send_receipt,
|
|
171
|
+
instructions: "send payment receipt email to customer",
|
|
172
|
+
inputs: { customer_id: 'string', amount: 'number', currency: 'string' },
|
|
173
|
+
outputs: { email_sent: 'boolean' }
|
|
174
|
+
|
|
175
|
+
task :update_subscription,
|
|
176
|
+
instructions: "update customer subscription status in database",
|
|
177
|
+
inputs: { customer_id: 'string', amount: 'number' },
|
|
178
|
+
outputs: { subscription_updated: 'boolean' }
|
|
179
|
+
|
|
180
|
+
main do |webhook_payload|
|
|
181
|
+
payment_info = execute_task(:extract_payment_info,
|
|
182
|
+
inputs: { stripe_payload: webhook_payload })
|
|
183
|
+
|
|
184
|
+
# Send receipt and update subscription in parallel
|
|
185
|
+
execute_parallel([
|
|
186
|
+
{ name: :send_receipt, inputs: payment_info },
|
|
187
|
+
{ name: :update_subscription, inputs: payment_info }
|
|
188
|
+
])
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Slack Integration
|
|
194
|
+
|
|
195
|
+
**Command Handler**:
|
|
196
|
+
```ruby
|
|
197
|
+
agent "slack-bot" do
|
|
198
|
+
description "Handles slack slash commands and interactive messages"
|
|
199
|
+
mode :reactive
|
|
200
|
+
|
|
201
|
+
webhook do
|
|
202
|
+
endpoint "slack"
|
|
203
|
+
authentication :slack_verification
|
|
204
|
+
events ['slash_command', 'interactive_message']
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
task :parse_command,
|
|
208
|
+
instructions: "parse slack command and extract parameters",
|
|
209
|
+
inputs: { command: 'string', text: 'string' },
|
|
210
|
+
outputs: { action: 'string', params: 'hash' }
|
|
211
|
+
|
|
212
|
+
task :execute_action,
|
|
213
|
+
instructions: "execute the requested action with given parameters",
|
|
214
|
+
inputs: { action: 'string', params: 'hash' },
|
|
215
|
+
outputs: { result: 'string', success: 'boolean' }
|
|
216
|
+
|
|
217
|
+
main do |webhook_payload|
|
|
218
|
+
if webhook_payload['type'] == 'slash_command'
|
|
219
|
+
command_info = {
|
|
220
|
+
command: webhook_payload['command'],
|
|
221
|
+
text: webhook_payload['text']
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
parsed = execute_task(:parse_command, inputs: command_info)
|
|
225
|
+
result = execute_task(:execute_action, inputs: parsed)
|
|
226
|
+
|
|
227
|
+
# Respond to Slack
|
|
228
|
+
execute_task(:send_slack_response, inputs: {
|
|
229
|
+
response_url: webhook_payload['response_url'],
|
|
230
|
+
message: result[:result]
|
|
231
|
+
})
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Custom Webhooks
|
|
238
|
+
|
|
239
|
+
**API Integration**:
|
|
240
|
+
```ruby
|
|
241
|
+
agent "api-monitor" do
|
|
242
|
+
description "Monitors API health via webhooks and alerts on issues"
|
|
243
|
+
mode :reactive
|
|
244
|
+
|
|
245
|
+
webhook do
|
|
246
|
+
endpoint "custom"
|
|
247
|
+
authentication :api_key
|
|
248
|
+
path "/health-check"
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
task :analyze_health_data,
|
|
252
|
+
instructions: "analyze API health metrics and identify problems",
|
|
253
|
+
inputs: { metrics: 'hash' },
|
|
254
|
+
outputs: { status: 'string', issues: 'array', alerts_needed: 'boolean' }
|
|
255
|
+
|
|
256
|
+
task :send_alerts,
|
|
257
|
+
instructions: "send alerts to operations team via multiple channels",
|
|
258
|
+
inputs: { issues: 'array', severity: 'string' },
|
|
259
|
+
outputs: { alerts_sent: 'array' }
|
|
260
|
+
|
|
261
|
+
main do |webhook_payload|
|
|
262
|
+
analysis = execute_task(:analyze_health_data,
|
|
263
|
+
inputs: { metrics: webhook_payload })
|
|
264
|
+
|
|
265
|
+
if analysis[:alerts_needed]
|
|
266
|
+
execute_task(:send_alerts, inputs: {
|
|
267
|
+
issues: analysis[:issues],
|
|
268
|
+
severity: analysis[:status]
|
|
269
|
+
})
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Webhook Configuration
|
|
276
|
+
|
|
277
|
+
### Authentication Methods
|
|
278
|
+
|
|
279
|
+
Language Operator supports multiple authentication methods:
|
|
280
|
+
|
|
281
|
+
**HMAC Signature Verification** (GitHub, Stripe):
|
|
282
|
+
```ruby
|
|
283
|
+
webhook do
|
|
284
|
+
endpoint "github"
|
|
285
|
+
authentication :hmac_sha256
|
|
286
|
+
secret ENV['GITHUB_WEBHOOK_SECRET']
|
|
287
|
+
end
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**API Key Authentication**:
|
|
291
|
+
```ruby
|
|
292
|
+
webhook do
|
|
293
|
+
endpoint "custom"
|
|
294
|
+
authentication :api_key
|
|
295
|
+
api_key ENV['WEBHOOK_API_KEY']
|
|
296
|
+
header "X-API-Key" # Custom header name
|
|
297
|
+
end
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Bearer Token Authentication**:
|
|
301
|
+
```ruby
|
|
302
|
+
webhook do
|
|
303
|
+
endpoint "custom"
|
|
304
|
+
authentication :bearer_token
|
|
305
|
+
token ENV['WEBHOOK_TOKEN']
|
|
306
|
+
end
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**Custom Authentication**:
|
|
310
|
+
```ruby
|
|
311
|
+
webhook do
|
|
312
|
+
endpoint "custom"
|
|
313
|
+
authentication :custom
|
|
314
|
+
validate do |headers, body|
|
|
315
|
+
# Custom validation logic
|
|
316
|
+
headers['X-Custom-Auth'] == ENV['CUSTOM_SECRET']
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Event Filtering
|
|
322
|
+
|
|
323
|
+
Filter specific events to reduce noise:
|
|
324
|
+
|
|
325
|
+
```ruby
|
|
326
|
+
webhook do
|
|
327
|
+
endpoint "github"
|
|
328
|
+
events [
|
|
329
|
+
'pull_request.opened',
|
|
330
|
+
'pull_request.synchronize',
|
|
331
|
+
'issues.opened'
|
|
332
|
+
]
|
|
333
|
+
|
|
334
|
+
# Additional filters
|
|
335
|
+
filters do
|
|
336
|
+
branch 'main' # Only main branch
|
|
337
|
+
repository 'company/main-repo' # Specific repository
|
|
338
|
+
label_present 'needs-review' # Must have label
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Webhook Endpoints
|
|
344
|
+
|
|
345
|
+
### Automatic URL Generation
|
|
346
|
+
|
|
347
|
+
Language Operator automatically generates secure webhook URLs:
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
https://webhooks.your-cluster.com/agents/{agent-id}/webhook/{endpoint}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
**Examples**:
|
|
354
|
+
- `https://webhooks.company.com/agents/pr-reviewer-abc123/webhook/github`
|
|
355
|
+
- `https://webhooks.company.com/agents/payment-processor-def456/webhook/stripe`
|
|
356
|
+
|
|
357
|
+
### Custom Paths
|
|
358
|
+
|
|
359
|
+
For custom integrations, specify custom paths:
|
|
360
|
+
|
|
361
|
+
```ruby
|
|
362
|
+
webhook do
|
|
363
|
+
endpoint "custom"
|
|
364
|
+
path "/api/v1/health-check" # Custom path
|
|
365
|
+
methods ['POST', 'PUT'] # Allowed HTTP methods
|
|
366
|
+
end
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## Security Features
|
|
370
|
+
|
|
371
|
+
### Request Validation
|
|
372
|
+
|
|
373
|
+
All webhook requests are validated:
|
|
374
|
+
- **Signature verification**: HMAC signatures verified automatically
|
|
375
|
+
- **Content-type checking**: Ensures proper JSON/form data
|
|
376
|
+
- **Rate limiting**: Prevents abuse and DoS attacks
|
|
377
|
+
- **IP whitelisting**: Restrict access to known service IPs
|
|
378
|
+
|
|
379
|
+
### Payload Sanitization
|
|
380
|
+
|
|
381
|
+
Webhook payloads are automatically sanitized:
|
|
382
|
+
- Potentially dangerous fields are filtered
|
|
383
|
+
- Large payloads are truncated if needed
|
|
384
|
+
- Sensitive information is masked in logs
|
|
385
|
+
|
|
386
|
+
## Error Handling
|
|
387
|
+
|
|
388
|
+
Webhook agents handle errors gracefully:
|
|
389
|
+
|
|
390
|
+
```ruby
|
|
391
|
+
main do |webhook_payload|
|
|
392
|
+
begin
|
|
393
|
+
# Normal processing
|
|
394
|
+
result = execute_task(:process_webhook, inputs: webhook_payload)
|
|
395
|
+
result
|
|
396
|
+
rescue => e
|
|
397
|
+
# Log error and return appropriate response
|
|
398
|
+
logger.error("Webhook processing failed: #{e.message}")
|
|
399
|
+
|
|
400
|
+
# Return error response
|
|
401
|
+
{
|
|
402
|
+
status: 'error',
|
|
403
|
+
message: 'Processing failed',
|
|
404
|
+
timestamp: Time.now
|
|
405
|
+
}
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Retry Logic
|
|
411
|
+
|
|
412
|
+
Failed webhooks are automatically retried:
|
|
413
|
+
- Exponential backoff for temporary failures
|
|
414
|
+
- Dead letter queue for permanent failures
|
|
415
|
+
- Alerting when retry limits exceeded
|
|
416
|
+
|
|
417
|
+
## Monitoring and Debugging
|
|
418
|
+
|
|
419
|
+
### Webhook Logs
|
|
420
|
+
|
|
421
|
+
Monitor webhook activity:
|
|
422
|
+
|
|
423
|
+
```bash
|
|
424
|
+
# View webhook logs
|
|
425
|
+
aictl agent logs pr-reviewer --webhooks-only
|
|
426
|
+
|
|
427
|
+
# Follow webhook activity in real-time
|
|
428
|
+
aictl agent logs pr-reviewer --follow --filter webhook
|
|
429
|
+
|
|
430
|
+
# View specific webhook processing
|
|
431
|
+
aictl agent webhook-logs pr-reviewer --webhook-id abc123
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Webhook Testing
|
|
435
|
+
|
|
436
|
+
Test webhooks during development:
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
# Test webhook endpoint
|
|
440
|
+
aictl agent test-webhook pr-reviewer \
|
|
441
|
+
--payload ./test-payload.json \
|
|
442
|
+
--event pull_request.opened
|
|
443
|
+
|
|
444
|
+
# Simulate webhook with custom data
|
|
445
|
+
aictl agent simulate-webhook pr-reviewer \
|
|
446
|
+
--github-pr 123 \
|
|
447
|
+
--repository company/main-repo
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## Performance Optimization
|
|
451
|
+
|
|
452
|
+
### Parallel Processing
|
|
453
|
+
|
|
454
|
+
Process webhooks efficiently using parallel task execution:
|
|
455
|
+
|
|
456
|
+
```ruby
|
|
457
|
+
main do |webhook_payload|
|
|
458
|
+
# Process multiple aspects in parallel
|
|
459
|
+
results = execute_parallel([
|
|
460
|
+
{ name: :validate_payload, inputs: webhook_payload },
|
|
461
|
+
{ name: :fetch_context, inputs: webhook_payload },
|
|
462
|
+
{ name: :check_permissions, inputs: webhook_payload }
|
|
463
|
+
])
|
|
464
|
+
|
|
465
|
+
# Continue with main processing
|
|
466
|
+
if results.all? { |r| r[:valid] }
|
|
467
|
+
execute_task(:main_processing, inputs: webhook_payload)
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Webhook Queuing
|
|
473
|
+
|
|
474
|
+
High-volume webhooks are queued automatically:
|
|
475
|
+
- Asynchronous processing for non-urgent webhooks
|
|
476
|
+
- Priority queues for critical events
|
|
477
|
+
- Batch processing for similar events
|
|
478
|
+
|
|
479
|
+
## Best Practices
|
|
480
|
+
|
|
481
|
+
### Security
|
|
482
|
+
- Always use proper authentication (HMAC, API keys)
|
|
483
|
+
- Validate webhook sources and signatures
|
|
484
|
+
- Sanitize and validate all input data
|
|
485
|
+
- Use environment variables for secrets
|
|
486
|
+
|
|
487
|
+
### Performance
|
|
488
|
+
- Process webhooks asynchronously when possible
|
|
489
|
+
- Use parallel execution for independent tasks
|
|
490
|
+
- Cache frequently accessed data
|
|
491
|
+
- Monitor response times and optimize bottlenecks
|
|
492
|
+
|
|
493
|
+
### Reliability
|
|
494
|
+
- Implement proper error handling and retries
|
|
495
|
+
- Log all webhook activity for debugging
|
|
496
|
+
- Test webhook processing with realistic payloads
|
|
497
|
+
- Monitor webhook endpoint availability
|
|
498
|
+
|
|
499
|
+
### Scalability
|
|
500
|
+
- Design for high webhook volumes
|
|
501
|
+
- Use efficient data structures and algorithms
|
|
502
|
+
- Consider webhook batching for similar events
|
|
503
|
+
- Scale webhook processing horizontally
|
|
504
|
+
|
|
505
|
+
## Next Steps
|
|
506
|
+
|
|
507
|
+
- **[Understanding Generated Code](understanding-generated-code.md)** - Learn to read webhook agent code
|
|
508
|
+
- **[Using Tools](using-tools.md)** - How webhook agents use external services
|
|
509
|
+
- **[Agent Configuration](agent-configuration.md)** - Configure webhook settings and limits
|