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.
- checksums.yaml +4 -4
- data/.rubocop.yml +125 -0
- data/CHANGELOG.md +53 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +284 -0
- data/LICENSE +229 -21
- data/Makefile +77 -0
- data/README.md +3 -11
- data/Rakefile +34 -0
- data/bin/aictl +7 -0
- data/completions/_aictl +232 -0
- data/completions/aictl.bash +121 -0
- data/completions/aictl.fish +114 -0
- data/docs/architecture/agent-runtime.md +585 -0
- data/docs/dsl/agent-reference.md +591 -0
- data/docs/dsl/best-practices.md +1078 -0
- data/docs/dsl/chat-endpoints.md +895 -0
- data/docs/dsl/constraints.md +671 -0
- data/docs/dsl/mcp-integration.md +1177 -0
- data/docs/dsl/webhooks.md +932 -0
- data/docs/dsl/workflows.md +744 -0
- data/examples/README.md +569 -0
- data/examples/agent_example.rb +86 -0
- data/examples/chat_endpoint_agent.rb +118 -0
- data/examples/github_webhook_agent.rb +171 -0
- data/examples/mcp_agent.rb +158 -0
- data/examples/oauth_callback_agent.rb +296 -0
- data/examples/stripe_webhook_agent.rb +219 -0
- data/examples/webhook_agent.rb +80 -0
- data/lib/language_operator/agent/base.rb +110 -0
- data/lib/language_operator/agent/executor.rb +440 -0
- data/lib/language_operator/agent/instrumentation.rb +54 -0
- data/lib/language_operator/agent/metrics_tracker.rb +183 -0
- data/lib/language_operator/agent/safety/ast_validator.rb +272 -0
- data/lib/language_operator/agent/safety/audit_logger.rb +104 -0
- data/lib/language_operator/agent/safety/budget_tracker.rb +175 -0
- data/lib/language_operator/agent/safety/content_filter.rb +93 -0
- data/lib/language_operator/agent/safety/manager.rb +207 -0
- data/lib/language_operator/agent/safety/rate_limiter.rb +150 -0
- data/lib/language_operator/agent/safety/safe_executor.rb +115 -0
- data/lib/language_operator/agent/scheduler.rb +183 -0
- data/lib/language_operator/agent/telemetry.rb +116 -0
- data/lib/language_operator/agent/web_server.rb +610 -0
- data/lib/language_operator/agent/webhook_authenticator.rb +226 -0
- data/lib/language_operator/agent.rb +149 -0
- data/lib/language_operator/cli/commands/agent.rb +1252 -0
- data/lib/language_operator/cli/commands/cluster.rb +335 -0
- data/lib/language_operator/cli/commands/install.rb +404 -0
- data/lib/language_operator/cli/commands/model.rb +266 -0
- data/lib/language_operator/cli/commands/persona.rb +396 -0
- data/lib/language_operator/cli/commands/quickstart.rb +22 -0
- data/lib/language_operator/cli/commands/status.rb +156 -0
- data/lib/language_operator/cli/commands/tool.rb +537 -0
- data/lib/language_operator/cli/commands/use.rb +47 -0
- data/lib/language_operator/cli/errors/handler.rb +180 -0
- data/lib/language_operator/cli/errors/suggestions.rb +176 -0
- data/lib/language_operator/cli/formatters/code_formatter.rb +81 -0
- data/lib/language_operator/cli/formatters/log_formatter.rb +290 -0
- data/lib/language_operator/cli/formatters/progress_formatter.rb +53 -0
- data/lib/language_operator/cli/formatters/table_formatter.rb +179 -0
- data/lib/language_operator/cli/formatters/value_formatter.rb +113 -0
- data/lib/language_operator/cli/helpers/cluster_context.rb +62 -0
- data/lib/language_operator/cli/helpers/cluster_validator.rb +101 -0
- data/lib/language_operator/cli/helpers/editor_helper.rb +58 -0
- data/lib/language_operator/cli/helpers/kubeconfig_validator.rb +167 -0
- data/lib/language_operator/cli/helpers/resource_dependency_checker.rb +74 -0
- data/lib/language_operator/cli/helpers/schedule_builder.rb +108 -0
- data/lib/language_operator/cli/helpers/user_prompts.rb +69 -0
- data/lib/language_operator/cli/main.rb +232 -0
- data/lib/language_operator/cli/templates/tools/generic.yaml +66 -0
- data/lib/language_operator/cli/wizards/agent_wizard.rb +246 -0
- data/lib/language_operator/cli/wizards/quickstart_wizard.rb +588 -0
- data/lib/language_operator/client/base.rb +214 -0
- data/lib/language_operator/client/config.rb +136 -0
- data/lib/language_operator/client/cost_calculator.rb +37 -0
- data/lib/language_operator/client/mcp_connector.rb +123 -0
- data/lib/language_operator/client.rb +19 -0
- data/lib/language_operator/config/cluster_config.rb +101 -0
- data/lib/language_operator/config/tool_patterns.yaml +57 -0
- data/lib/language_operator/config/tool_registry.rb +96 -0
- data/lib/language_operator/config.rb +138 -0
- data/lib/language_operator/dsl/adapter.rb +124 -0
- data/lib/language_operator/dsl/agent_context.rb +90 -0
- data/lib/language_operator/dsl/agent_definition.rb +427 -0
- data/lib/language_operator/dsl/chat_endpoint_definition.rb +115 -0
- data/lib/language_operator/dsl/config.rb +119 -0
- data/lib/language_operator/dsl/context.rb +50 -0
- data/lib/language_operator/dsl/execution_context.rb +47 -0
- data/lib/language_operator/dsl/helpers.rb +109 -0
- data/lib/language_operator/dsl/http.rb +184 -0
- data/lib/language_operator/dsl/mcp_server_definition.rb +73 -0
- data/lib/language_operator/dsl/parameter_definition.rb +124 -0
- data/lib/language_operator/dsl/registry.rb +36 -0
- data/lib/language_operator/dsl/shell.rb +125 -0
- data/lib/language_operator/dsl/tool_definition.rb +112 -0
- data/lib/language_operator/dsl/webhook_authentication.rb +114 -0
- data/lib/language_operator/dsl/webhook_definition.rb +106 -0
- data/lib/language_operator/dsl/workflow_definition.rb +259 -0
- data/lib/language_operator/dsl.rb +160 -0
- data/lib/language_operator/errors.rb +60 -0
- data/lib/language_operator/kubernetes/client.rb +279 -0
- data/lib/language_operator/kubernetes/resource_builder.rb +194 -0
- data/lib/language_operator/loggable.rb +47 -0
- data/lib/language_operator/logger.rb +141 -0
- data/lib/language_operator/retry.rb +123 -0
- data/lib/language_operator/retryable.rb +132 -0
- data/lib/language_operator/tool_loader.rb +242 -0
- data/lib/language_operator/validators.rb +170 -0
- data/lib/language_operator/version.rb +1 -1
- data/lib/language_operator.rb +65 -3
- data/requirements/tasks/challenge.md +9 -0
- data/requirements/tasks/iterate.md +36 -0
- data/requirements/tasks/optimize.md +21 -0
- data/requirements/tasks/tag.md +5 -0
- data/test_agent_dsl.rb +108 -0
- 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
|