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,744 @@
1
+ # Workflow Guide
2
+
3
+ Complete guide to defining workflows in the Language Operator agent DSL.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Overview](#overview)
8
+ - [Workflow Definition](#workflow-definition)
9
+ - [Step Types](#step-types)
10
+ - [Step Dependencies](#step-dependencies)
11
+ - [Parameter Passing](#parameter-passing)
12
+ - [Error Handling](#error-handling)
13
+ - [Complete Examples](#complete-examples)
14
+
15
+ ## Overview
16
+
17
+ Workflows define step-by-step execution plans for agents. Each step can:
18
+ - Call external tools
19
+ - Execute LLM prompts
20
+ - Run custom code
21
+ - Depend on previous steps
22
+ - Pass data between steps
23
+
24
+ ## Workflow Definition
25
+
26
+ Define a workflow inside an agent block:
27
+
28
+ ```ruby
29
+ agent "workflow-agent" do
30
+ workflow do
31
+ step :step_name do
32
+ # Step configuration
33
+ end
34
+ end
35
+ end
36
+ ```
37
+
38
+ ## Step Types
39
+
40
+ ### Tool Invocation Steps
41
+
42
+ Execute external tools (MCP servers, APIs, etc.):
43
+
44
+ ```ruby
45
+ workflow do
46
+ step :fetch_data do
47
+ tool 'database_query'
48
+ params(
49
+ query: 'SELECT * FROM users WHERE active = true',
50
+ database: 'production'
51
+ )
52
+ end
53
+ end
54
+ ```
55
+
56
+ **Components:**
57
+ - `tool` (String): Name of the tool to invoke
58
+ - `params` (Hash): Parameters to pass to the tool
59
+
60
+ ### Prompt/LLM Steps
61
+
62
+ Execute LLM prompts for analysis, generation, or decision-making:
63
+
64
+ ```ruby
65
+ workflow do
66
+ step :analyze do
67
+ prompt "Analyze this data and identify trends: {previous_step.output}"
68
+ end
69
+ end
70
+ ```
71
+
72
+ **Components:**
73
+ - `prompt` (String): The prompt to send to the LLM
74
+ - Supports parameter interpolation from previous steps
75
+
76
+ ### Custom Execution Steps
77
+
78
+ Run custom Ruby code:
79
+
80
+ ```ruby
81
+ workflow do
82
+ step :process do
83
+ execute do |context|
84
+ # Custom logic
85
+ data = context[:previous_step_output]
86
+ result = data.map { |item| item['value'] * 2 }
87
+ { processed_data: result }
88
+ end
89
+ end
90
+ end
91
+ ```
92
+
93
+ **Components:**
94
+ - `execute` (Block): Custom Ruby code to execute
95
+ - Block receives `context` hash with previous step outputs
96
+ - Return value becomes this step's output
97
+
98
+ ### Conditional Steps
99
+
100
+ Execute steps based on conditions:
101
+
102
+ ```ruby
103
+ workflow do
104
+ step :check_status do
105
+ tool 'health_check'
106
+ end
107
+
108
+ step :alert_if_down do
109
+ depends_on :check_status
110
+ condition do |context|
111
+ context[:check_status][:status] != 'healthy'
112
+ end
113
+
114
+ tool 'send_alert'
115
+ params(
116
+ message: 'System is down!',
117
+ severity: 'critical'
118
+ )
119
+ end
120
+ end
121
+ ```
122
+
123
+ ## Step Dependencies
124
+
125
+ ### Simple Dependencies
126
+
127
+ Steps can depend on previous steps:
128
+
129
+ ```ruby
130
+ workflow do
131
+ step :first do
132
+ tool 'fetch_data'
133
+ end
134
+
135
+ step :second do
136
+ depends_on :first
137
+ prompt "Process: {first.output}"
138
+ end
139
+ end
140
+ ```
141
+
142
+ **Execution order:**
143
+ 1. `:first` executes
144
+ 2. `:second` waits for `:first` to complete
145
+ 3. `:second` accesses `:first` output via interpolation
146
+
147
+ ### Multiple Dependencies
148
+
149
+ Steps can depend on multiple previous steps:
150
+
151
+ ```ruby
152
+ workflow do
153
+ step :fetch_users do
154
+ tool 'database_query'
155
+ params query: 'SELECT * FROM users'
156
+ end
157
+
158
+ step :fetch_orders do
159
+ tool 'database_query'
160
+ params query: 'SELECT * FROM orders'
161
+ end
162
+
163
+ step :merge_data do
164
+ depends_on [:fetch_users, :fetch_orders]
165
+ execute do |context|
166
+ users = context[:fetch_users][:output]
167
+ orders = context[:fetch_orders][:output]
168
+ # Merge logic...
169
+ end
170
+ end
171
+ end
172
+ ```
173
+
174
+ **Parallel Execution:**
175
+ - `:fetch_users` and `:fetch_orders` execute in parallel
176
+ - `:merge_data` waits for both to complete
177
+
178
+ ### Dependency Chains
179
+
180
+ Build complex workflows with chains of dependencies:
181
+
182
+ ```ruby
183
+ workflow do
184
+ step :extract do
185
+ tool 'web_scraper'
186
+ params url: 'https://api.example.com/data'
187
+ end
188
+
189
+ step :transform do
190
+ depends_on :extract
191
+ execute do |context|
192
+ # Transform data
193
+ end
194
+ end
195
+
196
+ step :load do
197
+ depends_on :transform
198
+ tool 'database_insert'
199
+ params(
200
+ table: 'processed_data',
201
+ data: '{transform.output}'
202
+ )
203
+ end
204
+
205
+ step :notify do
206
+ depends_on :load
207
+ tool 'send_email'
208
+ params(
209
+ to: 'team@company.com',
210
+ subject: 'ETL Complete',
211
+ body: 'Processed {extract.count} records'
212
+ )
213
+ end
214
+ end
215
+ ```
216
+
217
+ ## Parameter Passing
218
+
219
+ ### Output Interpolation
220
+
221
+ Access previous step outputs using `{step_name.field}` syntax:
222
+
223
+ ```ruby
224
+ workflow do
225
+ step :get_user do
226
+ tool 'database_query'
227
+ params query: 'SELECT * FROM users WHERE id = 123'
228
+ end
229
+
230
+ step :send_email do
231
+ depends_on :get_user
232
+ tool 'email_send'
233
+ params(
234
+ to: '{get_user.email}', # Access nested field
235
+ subject: 'Hello {get_user.name}',
236
+ body: 'Your account is active'
237
+ )
238
+ end
239
+ end
240
+ ```
241
+
242
+ ### Entire Output Passing
243
+
244
+ Pass the entire output of a previous step:
245
+
246
+ ```ruby
247
+ workflow do
248
+ step :fetch_data do
249
+ tool 'api_call'
250
+ end
251
+
252
+ step :analyze do
253
+ depends_on :fetch_data
254
+ prompt "Analyze this complete dataset: {fetch_data.output}"
255
+ end
256
+ end
257
+ ```
258
+
259
+ ### Context Access in Custom Steps
260
+
261
+ Access all previous outputs in custom execution blocks:
262
+
263
+ ```ruby
264
+ workflow do
265
+ step :step1 do
266
+ tool 'fetch_data'
267
+ end
268
+
269
+ step :step2 do
270
+ tool 'fetch_more_data'
271
+ end
272
+
273
+ step :combine do
274
+ depends_on [:step1, :step2]
275
+ execute do |context|
276
+ data1 = context[:step1][:output]
277
+ data2 = context[:step2][:output]
278
+
279
+ combined = {
280
+ total_records: data1.length + data2.length,
281
+ merged: data1 + data2
282
+ }
283
+
284
+ combined
285
+ end
286
+ end
287
+ end
288
+ ```
289
+
290
+ ### Default Values
291
+
292
+ Provide defaults for missing data:
293
+
294
+ ```ruby
295
+ workflow do
296
+ step :get_config do
297
+ tool 'read_config'
298
+ end
299
+
300
+ step :process do
301
+ depends_on :get_config
302
+ execute do |context|
303
+ timeout = context.dig(:get_config, :timeout) || 30
304
+ max_retries = context.dig(:get_config, :retries) || 3
305
+
306
+ # Use config values with defaults
307
+ end
308
+ end
309
+ end
310
+ ```
311
+
312
+ ## Error Handling
313
+
314
+ ### Retry on Failure
315
+
316
+ Configure automatic retries for steps:
317
+
318
+ ```ruby
319
+ workflow do
320
+ step :unreliable_api_call do
321
+ tool 'external_api'
322
+ params endpoint: '/data'
323
+
324
+ retry_on_failure max_attempts: 3, backoff: :exponential
325
+ end
326
+ end
327
+ ```
328
+
329
+ ### Error Handling Blocks
330
+
331
+ Define custom error handling:
332
+
333
+ ```ruby
334
+ workflow do
335
+ step :risky_operation do
336
+ tool 'flaky_service'
337
+ params action: 'process'
338
+
339
+ on_error do |error, context|
340
+ # Log error
341
+ puts "Step failed: #{error.message}"
342
+
343
+ # Return fallback value
344
+ { status: 'failed', fallback_data: [] }
345
+ end
346
+ end
347
+ end
348
+ ```
349
+
350
+ ### Continue on Failure
351
+
352
+ Allow workflow to continue even if a step fails:
353
+
354
+ ```ruby
355
+ workflow do
356
+ step :optional_enrichment do
357
+ tool 'enrichment_service'
358
+ params data: '{previous.output}'
359
+
360
+ continue_on_failure true
361
+ end
362
+
363
+ step :main_process do
364
+ depends_on :optional_enrichment
365
+ execute do |context|
366
+ # Check if enrichment succeeded
367
+ if context[:optional_enrichment][:error]
368
+ # Process without enrichment
369
+ else
370
+ # Process with enrichment
371
+ end
372
+ end
373
+ end
374
+ end
375
+ ```
376
+
377
+ ### Timeout Handling
378
+
379
+ Set timeouts for individual steps:
380
+
381
+ ```ruby
382
+ workflow do
383
+ step :slow_operation do
384
+ tool 'long_running_task'
385
+ timeout '5m' # 5 minutes
386
+
387
+ on_timeout do
388
+ { status: 'timeout', partial_results: [] }
389
+ end
390
+ end
391
+ end
392
+ ```
393
+
394
+ ## Complete Examples
395
+
396
+ ### ETL Pipeline
397
+
398
+ ```ruby
399
+ agent "data-etl-pipeline" do
400
+ description "Extract, transform, and load data daily"
401
+
402
+ mode :scheduled
403
+ schedule "0 2 * * *" # 2 AM daily
404
+
405
+ workflow do
406
+ # Extract
407
+ step :extract_source1 do
408
+ tool 'database_query'
409
+ params(
410
+ connection: 'source_db_1',
411
+ query: 'SELECT * FROM orders WHERE updated_at >= CURRENT_DATE - INTERVAL \'1 day\''
412
+ )
413
+ end
414
+
415
+ step :extract_source2 do
416
+ tool 'api_call'
417
+ params(
418
+ url: 'https://api.partner.com/orders',
419
+ params: { since: '24h' }
420
+ )
421
+ end
422
+
423
+ # Transform
424
+ step :transform_and_merge do
425
+ depends_on [:extract_source1, :extract_source2]
426
+
427
+ execute do |context|
428
+ source1_data = context[:extract_source1][:output]
429
+ source2_data = context[:extract_source2][:output]
430
+
431
+ # Normalize and merge
432
+ merged = []
433
+ source1_data.each do |record|
434
+ merged << {
435
+ id: record['order_id'],
436
+ amount: record['total_amount'],
437
+ source: 'db1'
438
+ }
439
+ end
440
+
441
+ source2_data.each do |record|
442
+ merged << {
443
+ id: record['id'],
444
+ amount: record['amount'],
445
+ source: 'api'
446
+ }
447
+ end
448
+
449
+ { records: merged, count: merged.length }
450
+ end
451
+ end
452
+
453
+ # Load
454
+ step :load_warehouse do
455
+ depends_on :transform_and_merge
456
+
457
+ tool 'database_bulk_insert'
458
+ params(
459
+ connection: 'warehouse',
460
+ table: 'orders_unified',
461
+ data: '{transform_and_merge.records}'
462
+ )
463
+
464
+ retry_on_failure max_attempts: 3
465
+ end
466
+
467
+ # Verify
468
+ step :verify_load do
469
+ depends_on :load_warehouse
470
+
471
+ tool 'database_query'
472
+ params(
473
+ connection: 'warehouse',
474
+ query: 'SELECT COUNT(*) as loaded_count FROM orders_unified WHERE loaded_at >= CURRENT_DATE'
475
+ )
476
+ end
477
+
478
+ # Notify
479
+ step :send_completion_email do
480
+ depends_on [:transform_and_merge, :verify_load]
481
+
482
+ tool 'send_email'
483
+ params(
484
+ to: 'data-team@company.com',
485
+ subject: 'ETL Pipeline Complete',
486
+ body: 'Processed {transform_and_merge.count} records. Warehouse now has {verify_load.loaded_count} records for today.'
487
+ )
488
+ end
489
+ end
490
+
491
+ constraints do
492
+ timeout '30m'
493
+ daily_budget 1000 # $10
494
+ end
495
+ end
496
+ ```
497
+
498
+ ### Multi-Step Analysis Workflow
499
+
500
+ ```ruby
501
+ agent "market-analyzer" do
502
+ description "Analyze market trends and generate insights"
503
+
504
+ mode :scheduled
505
+ schedule "0 16 * * 1-5" # 4 PM on weekdays
506
+
507
+ workflow do
508
+ # Gather data
509
+ step :fetch_stock_prices do
510
+ tool 'financial_api'
511
+ params(
512
+ action: 'get_prices',
513
+ symbols: ['AAPL', 'GOOGL', 'MSFT', 'AMZN'],
514
+ period: '1d'
515
+ )
516
+ end
517
+
518
+ step :fetch_news do
519
+ tool 'news_api'
520
+ params(
521
+ query: 'tech stocks',
522
+ from: 'today'
523
+ )
524
+ end
525
+
526
+ step :fetch_sentiment do
527
+ tool 'twitter_api'
528
+ params(
529
+ topics: ['#tech', '#stocks'],
530
+ limit: 100
531
+ )
532
+ end
533
+
534
+ # Analysis
535
+ step :analyze_price_trends do
536
+ depends_on :fetch_stock_prices
537
+
538
+ prompt <<~PROMPT
539
+ Analyze these stock price movements and identify key trends:
540
+ {fetch_stock_prices.output}
541
+
542
+ Provide:
543
+ 1. Overall market direction
544
+ 2. Top performers
545
+ 3. Stocks showing unusual activity
546
+ PROMPT
547
+ end
548
+
549
+ step :analyze_news_sentiment do
550
+ depends_on :fetch_news
551
+
552
+ prompt <<~PROMPT
553
+ Analyze the sentiment of these news articles:
554
+ {fetch_news.output}
555
+
556
+ Categorize as: positive, negative, or neutral
557
+ Identify key themes and concerns
558
+ PROMPT
559
+ end
560
+
561
+ step :analyze_social_sentiment do
562
+ depends_on :fetch_sentiment
563
+
564
+ prompt <<~PROMPT
565
+ Analyze social media sentiment:
566
+ {fetch_sentiment.output}
567
+
568
+ Summarize public perception of tech stocks
569
+ PROMPT
570
+ end
571
+
572
+ # Synthesis
573
+ step :generate_comprehensive_report do
574
+ depends_on [:analyze_price_trends, :analyze_news_sentiment, :analyze_social_sentiment]
575
+
576
+ prompt <<~PROMPT
577
+ Create a comprehensive market analysis report combining:
578
+
579
+ Price Analysis: {analyze_price_trends.output}
580
+ News Sentiment: {analyze_news_sentiment.output}
581
+ Social Sentiment: {analyze_social_sentiment.output}
582
+
583
+ Generate an executive summary with:
584
+ - Key market movements
585
+ - Notable sentiment shifts
586
+ - Potential opportunities or risks
587
+ - Recommendation for tomorrow's trading strategy
588
+ PROMPT
589
+ end
590
+
591
+ # Delivery
592
+ step :send_report do
593
+ depends_on :generate_comprehensive_report
594
+
595
+ tool 'send_email'
596
+ params(
597
+ to: 'traders@company.com',
598
+ subject: 'Daily Market Analysis - {today}',
599
+ body: '{generate_comprehensive_report.output}',
600
+ format: 'html'
601
+ )
602
+ end
603
+
604
+ step :save_to_archive do
605
+ depends_on :generate_comprehensive_report
606
+
607
+ tool 'file_write'
608
+ params(
609
+ path: '/reports/market-analysis-{date}.md',
610
+ content: '{generate_comprehensive_report.output}'
611
+ )
612
+ end
613
+ end
614
+
615
+ constraints do
616
+ timeout '20m'
617
+ max_iterations 30
618
+ daily_budget 2000 # $20
619
+ end
620
+ end
621
+ ```
622
+
623
+ ### Conditional Workflow
624
+
625
+ ```ruby
626
+ agent "smart-responder" do
627
+ description "Respond to customer inquiries with appropriate escalation"
628
+
629
+ mode :reactive
630
+
631
+ workflow do
632
+ step :classify_inquiry do
633
+ prompt <<~PROMPT
634
+ Classify this customer inquiry:
635
+ {event.inquiry_text}
636
+
637
+ Categories:
638
+ - simple: Can be answered with FAQ
639
+ - technical: Requires technical expertise
640
+ - billing: Related to billing/payments
641
+ - urgent: Critical issue requiring immediate attention
642
+
643
+ Respond with just the category name.
644
+ PROMPT
645
+ end
646
+
647
+ step :check_if_urgent do
648
+ depends_on :classify_inquiry
649
+
650
+ execute do |context|
651
+ category = context[:classify_inquiry][:output].strip.downcase
652
+ { is_urgent: category == 'urgent' }
653
+ end
654
+ end
655
+
656
+ step :send_urgent_alert do
657
+ depends_on :check_if_urgent
658
+
659
+ condition do |context|
660
+ context[:check_if_urgent][:is_urgent]
661
+ end
662
+
663
+ tool 'send_sms'
664
+ params(
665
+ to: '+1-555-ONCALL',
666
+ message: 'URGENT: Customer inquiry requires immediate attention - {event.ticket_id}'
667
+ )
668
+ end
669
+
670
+ step :generate_response do
671
+ depends_on :classify_inquiry
672
+
673
+ prompt <<~PROMPT
674
+ Generate an appropriate response for this {classify_inquiry.output} inquiry:
675
+ {event.inquiry_text}
676
+
677
+ Be helpful, professional, and concise.
678
+ PROMPT
679
+ end
680
+
681
+ step :send_response do
682
+ depends_on :generate_response
683
+
684
+ tool 'email_send'
685
+ params(
686
+ to: '{event.customer_email}',
687
+ subject: 'Re: {event.subject}',
688
+ body: '{generate_response.output}'
689
+ )
690
+ end
691
+
692
+ step :update_ticket do
693
+ depends_on [:send_response, :check_if_urgent]
694
+
695
+ tool 'crm_update'
696
+ params(
697
+ ticket_id: '{event.ticket_id}',
698
+ status: 'responded',
699
+ priority: '{check_if_urgent.is_urgent ? "high" : "normal"}',
700
+ response: '{generate_response.output}'
701
+ )
702
+ end
703
+ end
704
+ end
705
+ ```
706
+
707
+ ## Best Practices
708
+
709
+ ### Workflow Design
710
+
711
+ 1. **Keep steps focused** - Each step should do one thing well
712
+ 2. **Name steps clearly** - Use descriptive names (`:fetch_user_data` not `:step1`)
713
+ 3. **Handle errors explicitly** - Don't assume steps will succeed
714
+ 4. **Use parallel execution** - Steps without dependencies run in parallel
715
+ 5. **Minimize step count** - Combine related operations when sensible
716
+
717
+ ### Error Handling
718
+
719
+ 1. **Always handle critical failures** - Don't let workflows silently fail
720
+ 2. **Provide fallback values** - Return sensible defaults on error
721
+ 3. **Log failures** - Capture error details for debugging
722
+ 4. **Use retries judiciously** - Retry transient failures, not logic errors
723
+ 5. **Set appropriate timeouts** - Prevent indefinite hangs
724
+
725
+ ### Performance
726
+
727
+ 1. **Parallelize when possible** - Avoid unnecessary sequential dependencies
728
+ 2. **Cache expensive operations** - Reuse results within workflow execution
729
+ 3. **Set realistic timeouts** - Balance responsiveness with completion
730
+ 4. **Monitor execution time** - Track and optimize slow steps
731
+
732
+ ### Maintainability
733
+
734
+ 1. **Document complex workflows** - Add comments explaining business logic
735
+ 2. **Use consistent naming** - Follow conventions across all agents
736
+ 3. **Test workflows** - Validate with dry-run mode before production
737
+ 4. **Version control** - Track changes to workflow definitions
738
+
739
+ ## See Also
740
+
741
+ - [Agent Reference](agent-reference.md) - Complete agent DSL reference
742
+ - [Constraints](constraints.md) - Resource and behavior limits
743
+ - [MCP Integration](mcp-integration.md) - External tool integration
744
+ - [Best Practices](best-practices.md) - Production deployment patterns