agentic 0.1.0 → 0.2.0
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/.agentic.yml +2 -0
- data/.architecture/decisions/ArchitecturalFeatureBuilder.md +136 -0
- data/.architecture/decisions/ArchitectureConsiderations.md +200 -0
- data/.architecture/decisions/adr_001_observer_pattern_implementation.md +196 -0
- data/.architecture/decisions/adr_002_plan_orchestrator.md +320 -0
- data/.architecture/decisions/adr_003_plan_orchestrator_interface.md +179 -0
- data/.architecture/decisions/adrs/ADR-001-dependency-management.md +147 -0
- data/.architecture/decisions/adrs/ADR-002-system-boundaries.md +162 -0
- data/.architecture/decisions/adrs/ADR-003-content-safety.md +158 -0
- data/.architecture/decisions/adrs/ADR-004-agent-permissions.md +161 -0
- data/.architecture/decisions/adrs/ADR-005-adaptation-engine.md +127 -0
- data/.architecture/decisions/adrs/ADR-006-extension-system.md +273 -0
- data/.architecture/decisions/adrs/ADR-007-learning-system.md +156 -0
- data/.architecture/decisions/adrs/ADR-008-prompt-generation.md +325 -0
- data/.architecture/decisions/adrs/ADR-009-task-failure-handling.md +353 -0
- data/.architecture/decisions/adrs/ADR-010-task-input-handling.md +251 -0
- data/.architecture/decisions/adrs/ADR-011-task-observable-pattern.md +391 -0
- data/.architecture/decisions/adrs/ADR-012-task-output-handling.md +205 -0
- data/.architecture/decisions/adrs/ADR-013-architecture-alignment.md +211 -0
- data/.architecture/decisions/adrs/ADR-014-agent-capability-registry.md +80 -0
- data/.architecture/decisions/adrs/ADR-015-persistent-agent-store.md +100 -0
- data/.architecture/decisions/adrs/ADR-016-agent-assembly-engine.md +117 -0
- data/.architecture/decisions/adrs/ADR-017-streaming-observability.md +171 -0
- data/.architecture/decisions/capability_tools_distinction.md +150 -0
- data/.architecture/decisions/cli_command_structure.md +61 -0
- data/.architecture/implementation/agent_self_assembly_implementation.md +267 -0
- data/.architecture/implementation/agent_self_assembly_summary.md +138 -0
- data/.architecture/members.yml +187 -0
- data/.architecture/planning/self_implementation_exercise.md +295 -0
- data/.architecture/planning/session_compaction_rule.md +43 -0
- data/.architecture/planning/streaming_observability_feature.md +223 -0
- data/.architecture/principles.md +151 -0
- data/.architecture/recalibration/0-2-0.md +92 -0
- data/.architecture/recalibration/agent_self_assembly.md +238 -0
- data/.architecture/recalibration/cli_command_structure.md +91 -0
- data/.architecture/recalibration/implementation_roadmap_0-2-0.md +301 -0
- data/.architecture/recalibration/progress_tracking_0-2-0.md +114 -0
- data/.architecture/recalibration_process.md +127 -0
- data/.architecture/reviews/0-2-0.md +181 -0
- data/.architecture/reviews/cli_command_duplication.md +98 -0
- data/.architecture/templates/adr.md +105 -0
- data/.architecture/templates/implementation_roadmap.md +125 -0
- data/.architecture/templates/progress_tracking.md +89 -0
- data/.architecture/templates/recalibration_plan.md +70 -0
- data/.architecture/templates/version_comparison.md +124 -0
- data/.claude/settings.local.json +13 -0
- data/.claude-sessions/001-task-class-architecture-implementation.md +129 -0
- data/.claude-sessions/002-plan-orchestrator-interface-review.md +105 -0
- data/.claude-sessions/architecture-governance-implementation.md +37 -0
- data/.claude-sessions/architecture-review-session.md +27 -0
- data/ArchitecturalFeatureBuilder.md +136 -0
- data/ArchitectureConsiderations.md +229 -0
- data/CHANGELOG.md +57 -2
- data/CLAUDE.md +111 -0
- data/CONTRIBUTING.md +286 -0
- data/MAINTAINING.md +301 -0
- data/README.md +582 -28
- data/docs/agent_capabilities_api.md +259 -0
- data/docs/artifact_extension_points.md +757 -0
- data/docs/artifact_generation_architecture.md +323 -0
- data/docs/artifact_implementation_plan.md +596 -0
- data/docs/artifact_integration_points.md +345 -0
- data/docs/artifact_verification_strategies.md +581 -0
- data/docs/streaming_observability_architecture.md +510 -0
- data/exe/agentic +6 -1
- data/lefthook.yml +5 -0
- data/lib/agentic/adaptation_engine.rb +124 -0
- data/lib/agentic/agent.rb +181 -4
- data/lib/agentic/agent_assembly_engine.rb +442 -0
- data/lib/agentic/agent_capability_registry.rb +260 -0
- data/lib/agentic/agent_config.rb +63 -0
- data/lib/agentic/agent_specification.rb +46 -0
- data/lib/agentic/capabilities/examples.rb +530 -0
- data/lib/agentic/capabilities.rb +14 -0
- data/lib/agentic/capability_provider.rb +146 -0
- data/lib/agentic/capability_specification.rb +118 -0
- data/lib/agentic/cli/agent.rb +31 -0
- data/lib/agentic/cli/capabilities.rb +191 -0
- data/lib/agentic/cli/config.rb +134 -0
- data/lib/agentic/cli/execution_observer.rb +796 -0
- data/lib/agentic/cli.rb +1068 -0
- data/lib/agentic/default_agent_provider.rb +35 -0
- data/lib/agentic/errors/llm_error.rb +184 -0
- data/lib/agentic/execution_plan.rb +53 -0
- data/lib/agentic/execution_result.rb +91 -0
- data/lib/agentic/expected_answer_format.rb +46 -0
- data/lib/agentic/extension/domain_adapter.rb +109 -0
- data/lib/agentic/extension/plugin_manager.rb +163 -0
- data/lib/agentic/extension/protocol_handler.rb +116 -0
- data/lib/agentic/extension.rb +45 -0
- data/lib/agentic/factory_methods.rb +9 -1
- data/lib/agentic/generation_stats.rb +61 -0
- data/lib/agentic/learning/README.md +84 -0
- data/lib/agentic/learning/capability_optimizer.rb +613 -0
- data/lib/agentic/learning/execution_history_store.rb +251 -0
- data/lib/agentic/learning/pattern_recognizer.rb +500 -0
- data/lib/agentic/learning/strategy_optimizer.rb +706 -0
- data/lib/agentic/learning.rb +131 -0
- data/lib/agentic/llm_assisted_composition_strategy.rb +188 -0
- data/lib/agentic/llm_client.rb +215 -15
- data/lib/agentic/llm_config.rb +65 -1
- data/lib/agentic/llm_response.rb +163 -0
- data/lib/agentic/logger.rb +1 -1
- data/lib/agentic/observable.rb +51 -0
- data/lib/agentic/persistent_agent_store.rb +385 -0
- data/lib/agentic/plan_execution_result.rb +129 -0
- data/lib/agentic/plan_orchestrator.rb +464 -0
- data/lib/agentic/plan_orchestrator_config.rb +57 -0
- data/lib/agentic/retry_config.rb +63 -0
- data/lib/agentic/retry_handler.rb +125 -0
- data/lib/agentic/structured_outputs.rb +1 -1
- data/lib/agentic/task.rb +193 -0
- data/lib/agentic/task_definition.rb +39 -0
- data/lib/agentic/task_execution_result.rb +92 -0
- data/lib/agentic/task_failure.rb +66 -0
- data/lib/agentic/task_output_schemas.rb +112 -0
- data/lib/agentic/task_planner.rb +54 -19
- data/lib/agentic/task_result.rb +48 -0
- data/lib/agentic/ui.rb +244 -0
- data/lib/agentic/verification/critic_framework.rb +116 -0
- data/lib/agentic/verification/llm_verification_strategy.rb +60 -0
- data/lib/agentic/verification/schema_verification_strategy.rb +47 -0
- data/lib/agentic/verification/verification_hub.rb +62 -0
- data/lib/agentic/verification/verification_result.rb +50 -0
- data/lib/agentic/verification/verification_strategy.rb +26 -0
- data/lib/agentic/version.rb +1 -1
- data/lib/agentic.rb +74 -2
- data/plugins/README.md +41 -0
- metadata +245 -6
@@ -0,0 +1,510 @@
|
|
1
|
+
# Streaming Observability Architecture for Agentic
|
2
|
+
|
3
|
+
## Overview
|
4
|
+
|
5
|
+
This document outlines the design for adding real-time streaming observability to the Agentic framework, enabling live insights into task execution, agent assembly, plan building, and orchestration.
|
6
|
+
|
7
|
+
## Current State Assessment
|
8
|
+
|
9
|
+
### Existing Observability Infrastructure
|
10
|
+
- **Observable Pattern**: Thread-safe event notification system
|
11
|
+
- **ExecutionObserver**: CLI real-time feedback with progress tracking
|
12
|
+
- **Lifecycle Hooks**: Callback system for plan orchestrator events
|
13
|
+
- **Task State Transitions**: Observable state changes in task execution
|
14
|
+
- **Structured Logging**: Comprehensive logging throughout the system
|
15
|
+
|
16
|
+
### Gaps Identified
|
17
|
+
1. **No streaming intermediary steps** during task execution
|
18
|
+
2. **Limited visibility** into agent assembly process
|
19
|
+
3. **No real-time insights** into LLM interactions
|
20
|
+
4. **Missing observability** for plan construction phases
|
21
|
+
5. **No aggregated metrics** streaming capability
|
22
|
+
|
23
|
+
## Streaming Architecture Design
|
24
|
+
|
25
|
+
### Core Components
|
26
|
+
|
27
|
+
#### 1. StreamingObservabilityHub
|
28
|
+
Central coordinator for all streaming observability events.
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
class StreamingObservabilityHub
|
32
|
+
include Singleton
|
33
|
+
|
34
|
+
# Event streams for different types of observability data
|
35
|
+
attr_reader :task_stream, :agent_stream, :plan_stream, :metrics_stream
|
36
|
+
|
37
|
+
# Stream processors for different output formats
|
38
|
+
attr_reader :processors
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
#### 2. ObservabilityStream
|
43
|
+
Generic streaming interface supporting multiple backends.
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
class ObservabilityStream
|
47
|
+
# Stream types: :sse, :websocket, :file, :memory, :stdout
|
48
|
+
def initialize(type:, config: {})
|
49
|
+
|
50
|
+
# Emit structured events with metadata
|
51
|
+
def emit(event_type, payload, metadata: {})
|
52
|
+
|
53
|
+
# Support for event filtering and transformation
|
54
|
+
def filter(&block)
|
55
|
+
def transform(&block)
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
#### 3. Enhanced Observable Pattern
|
60
|
+
Extend existing Observable to support streaming and buffering.
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
module StreamingObservable
|
64
|
+
include Observable
|
65
|
+
|
66
|
+
# Stream-aware notification with buffering
|
67
|
+
def notify_streaming_observers(event_type, payload, stream_config: {})
|
68
|
+
|
69
|
+
# Support for progress events with percentages
|
70
|
+
def notify_progress(percentage, description, metadata: {})
|
71
|
+
|
72
|
+
# Batch event support for performance
|
73
|
+
def notify_batch(events)
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
### Integration Points
|
78
|
+
|
79
|
+
#### 1. Task Execution Streaming
|
80
|
+
|
81
|
+
**Enhanced Task Class:**
|
82
|
+
```ruby
|
83
|
+
class Task
|
84
|
+
include StreamingObservable
|
85
|
+
|
86
|
+
# Stream task lifecycle events
|
87
|
+
def perform(agent)
|
88
|
+
stream_event(:task_started, {
|
89
|
+
task_id: @id,
|
90
|
+
description: @description,
|
91
|
+
agent_spec: @agent_spec.to_h
|
92
|
+
})
|
93
|
+
|
94
|
+
# Stream LLM request details
|
95
|
+
stream_event(:llm_request_started, {
|
96
|
+
prompt_length: build_prompt.length,
|
97
|
+
estimated_tokens: estimate_tokens(build_prompt)
|
98
|
+
})
|
99
|
+
|
100
|
+
# Stream intermediate steps during agent execution
|
101
|
+
@output = agent.execute(build_prompt) do |step|
|
102
|
+
stream_event(:execution_step, {
|
103
|
+
step_type: step[:type],
|
104
|
+
content: step[:content],
|
105
|
+
timestamp: Time.now
|
106
|
+
})
|
107
|
+
end
|
108
|
+
|
109
|
+
stream_event(:task_completed, {
|
110
|
+
task_id: @id,
|
111
|
+
output_size: @output&.to_s&.length || 0,
|
112
|
+
execution_time: Time.now - start_time
|
113
|
+
})
|
114
|
+
end
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
#### 2. Agent Assembly Streaming
|
119
|
+
|
120
|
+
**Enhanced AgentAssemblyEngine:**
|
121
|
+
```ruby
|
122
|
+
class AgentAssemblyEngine
|
123
|
+
include StreamingObservable
|
124
|
+
|
125
|
+
def assemble_agent(task, strategy: nil, store: true)
|
126
|
+
stream_event(:assembly_started, {
|
127
|
+
task_id: task.id,
|
128
|
+
strategy_type: strategy&.class&.name
|
129
|
+
})
|
130
|
+
|
131
|
+
# Stream requirement analysis
|
132
|
+
requirements = analyze_requirements(task) do |capability, score|
|
133
|
+
stream_event(:capability_analyzed, {
|
134
|
+
capability: capability,
|
135
|
+
importance_score: score,
|
136
|
+
reasoning: "Inferred from task description"
|
137
|
+
})
|
138
|
+
end
|
139
|
+
|
140
|
+
# Stream capability selection
|
141
|
+
capabilities = select_capabilities(requirements, strategy) do |selected|
|
142
|
+
stream_event(:capability_selected, {
|
143
|
+
capability: selected[:name],
|
144
|
+
version: selected[:version],
|
145
|
+
selection_reason: selected[:reason]
|
146
|
+
})
|
147
|
+
end
|
148
|
+
|
149
|
+
# Stream agent construction
|
150
|
+
agent = build_agent(task, capabilities) do |step|
|
151
|
+
stream_event(:agent_build_step, {
|
152
|
+
step: step[:name],
|
153
|
+
progress: step[:progress],
|
154
|
+
details: step[:details]
|
155
|
+
})
|
156
|
+
end
|
157
|
+
|
158
|
+
stream_event(:assembly_completed, {
|
159
|
+
agent_id: agent.id,
|
160
|
+
capabilities_count: capabilities.length,
|
161
|
+
assembly_time: Time.now - start_time
|
162
|
+
})
|
163
|
+
|
164
|
+
agent
|
165
|
+
end
|
166
|
+
end
|
167
|
+
```
|
168
|
+
|
169
|
+
#### 3. Plan Orchestrator Streaming
|
170
|
+
|
171
|
+
**Enhanced PlanOrchestrator:**
|
172
|
+
```ruby
|
173
|
+
class PlanOrchestrator
|
174
|
+
include StreamingObservable
|
175
|
+
|
176
|
+
def execute_plan(agent_provider)
|
177
|
+
stream_event(:plan_execution_started, {
|
178
|
+
plan_id: @plan_id,
|
179
|
+
total_tasks: @tasks.length,
|
180
|
+
concurrency_limit: @concurrency_limit
|
181
|
+
})
|
182
|
+
|
183
|
+
# Stream dependency analysis
|
184
|
+
dependency_graph = analyze_dependencies do |analysis|
|
185
|
+
stream_event(:dependency_analysis, analysis)
|
186
|
+
end
|
187
|
+
|
188
|
+
# Stream task scheduling decisions
|
189
|
+
eligible_tasks.each do |task_id|
|
190
|
+
stream_event(:task_scheduled, {
|
191
|
+
task_id: task_id,
|
192
|
+
scheduled_at: Time.now,
|
193
|
+
dependencies_met: all_dependencies_met?(task_id)
|
194
|
+
})
|
195
|
+
end
|
196
|
+
|
197
|
+
# Enhanced lifecycle hooks with streaming
|
198
|
+
@lifecycle_hooks = build_streaming_lifecycle_hooks
|
199
|
+
|
200
|
+
# Execute with streaming updates
|
201
|
+
result = super(agent_provider)
|
202
|
+
|
203
|
+
stream_event(:plan_execution_completed, {
|
204
|
+
plan_id: @plan_id,
|
205
|
+
final_status: result.status,
|
206
|
+
total_execution_time: result.execution_time,
|
207
|
+
task_summary: build_task_summary
|
208
|
+
})
|
209
|
+
|
210
|
+
result
|
211
|
+
end
|
212
|
+
end
|
213
|
+
```
|
214
|
+
|
215
|
+
#### 4. TaskPlanner Streaming
|
216
|
+
|
217
|
+
**Enhanced TaskPlanner:**
|
218
|
+
```ruby
|
219
|
+
class TaskPlanner
|
220
|
+
include StreamingObservable
|
221
|
+
|
222
|
+
def analyze_goal
|
223
|
+
stream_event(:goal_analysis_started, {
|
224
|
+
goal: @goal,
|
225
|
+
analysis_type: "llm_breakdown"
|
226
|
+
})
|
227
|
+
|
228
|
+
# Stream LLM planning interaction
|
229
|
+
response = llm_request(system_message, user_message, schema) do |chunk|
|
230
|
+
stream_event(:llm_planning_chunk, {
|
231
|
+
chunk_type: chunk[:type],
|
232
|
+
content: chunk[:content],
|
233
|
+
tokens_processed: chunk[:tokens]
|
234
|
+
})
|
235
|
+
end
|
236
|
+
|
237
|
+
# Stream task creation
|
238
|
+
@tasks = response.content["tasks"].map.with_index do |task_data, index|
|
239
|
+
stream_event(:task_defined, {
|
240
|
+
task_index: index,
|
241
|
+
description: task_data["description"],
|
242
|
+
agent_type: task_data["agent"]["name"],
|
243
|
+
complexity_estimate: estimate_complexity(task_data)
|
244
|
+
})
|
245
|
+
|
246
|
+
TaskDefinition.new(...)
|
247
|
+
end
|
248
|
+
|
249
|
+
stream_event(:goal_analysis_completed, {
|
250
|
+
tasks_generated: @tasks.length,
|
251
|
+
analysis_time: Time.now - start_time
|
252
|
+
})
|
253
|
+
end
|
254
|
+
end
|
255
|
+
```
|
256
|
+
|
257
|
+
### Stream Processing Architecture
|
258
|
+
|
259
|
+
#### 1. Event Formatting and Filtering
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
class StreamProcessor
|
263
|
+
def initialize(stream, filters: [], formatters: [])
|
264
|
+
@stream = stream
|
265
|
+
@filters = filters
|
266
|
+
@formatters = formatters
|
267
|
+
end
|
268
|
+
|
269
|
+
def process(event)
|
270
|
+
# Apply filters
|
271
|
+
return unless @filters.all? { |filter| filter.call(event) }
|
272
|
+
|
273
|
+
# Apply formatters
|
274
|
+
formatted_event = @formatters.reduce(event) { |evt, formatter| formatter.call(evt) }
|
275
|
+
|
276
|
+
# Emit to stream
|
277
|
+
@stream.emit(formatted_event)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
```
|
281
|
+
|
282
|
+
#### 2. Stream Aggregation and Metrics
|
283
|
+
|
284
|
+
```ruby
|
285
|
+
class MetricsAggregator
|
286
|
+
def initialize(window_size: 60)
|
287
|
+
@window_size = window_size
|
288
|
+
@metrics = {}
|
289
|
+
end
|
290
|
+
|
291
|
+
def process_event(event)
|
292
|
+
case event[:type]
|
293
|
+
when :task_completed
|
294
|
+
track_task_completion(event)
|
295
|
+
when :agent_assembly_completed
|
296
|
+
track_assembly_time(event)
|
297
|
+
when :llm_request_completed
|
298
|
+
track_llm_usage(event)
|
299
|
+
end
|
300
|
+
|
301
|
+
emit_aggregated_metrics if should_emit_metrics?
|
302
|
+
end
|
303
|
+
|
304
|
+
private
|
305
|
+
|
306
|
+
def emit_aggregated_metrics
|
307
|
+
StreamingObservabilityHub.instance.metrics_stream.emit(:metrics_update, {
|
308
|
+
timestamp: Time.now,
|
309
|
+
window_size: @window_size,
|
310
|
+
metrics: calculate_current_metrics
|
311
|
+
})
|
312
|
+
end
|
313
|
+
end
|
314
|
+
```
|
315
|
+
|
316
|
+
#### 3. Multi-Output Support
|
317
|
+
|
318
|
+
```ruby
|
319
|
+
class MultiStreamOutput
|
320
|
+
def initialize
|
321
|
+
@outputs = {}
|
322
|
+
end
|
323
|
+
|
324
|
+
def add_output(name, stream)
|
325
|
+
@outputs[name] = stream
|
326
|
+
end
|
327
|
+
|
328
|
+
def emit(event)
|
329
|
+
@outputs.each do |name, stream|
|
330
|
+
begin
|
331
|
+
stream.emit(event)
|
332
|
+
rescue => e
|
333
|
+
Agentic.logger.warn("Failed to emit to stream #{name}: #{e.message}")
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
```
|
339
|
+
|
340
|
+
## Implementation Strategy
|
341
|
+
|
342
|
+
### Phase 1: Core Streaming Infrastructure
|
343
|
+
1. **StreamingObservabilityHub** - Central coordination
|
344
|
+
2. **ObservabilityStream** - Generic streaming interface
|
345
|
+
3. **Enhanced Observable** - Stream-aware event emission
|
346
|
+
4. **Basic CLI streaming** - Real-time console output
|
347
|
+
|
348
|
+
### Phase 2: Task and Agent Streaming
|
349
|
+
1. **Task execution streaming** - Intermediate steps and progress
|
350
|
+
2. **Agent assembly streaming** - Capability analysis and selection
|
351
|
+
3. **LLM interaction streaming** - Request/response details
|
352
|
+
4. **Enhanced ExecutionObserver** - Richer real-time feedback
|
353
|
+
|
354
|
+
### Phase 3: Plan and Orchestration Streaming
|
355
|
+
1. **Plan building streaming** - Goal analysis and task generation
|
356
|
+
2. **Orchestration streaming** - Scheduling and dependency resolution
|
357
|
+
3. **Metrics aggregation** - Real-time performance insights
|
358
|
+
4. **Advanced filtering** - Configurable event streams
|
359
|
+
|
360
|
+
### Phase 4: Advanced Features
|
361
|
+
1. **WebSocket support** - Browser-based real-time dashboards
|
362
|
+
2. **Stream persistence** - Event replay and analysis
|
363
|
+
3. **Custom processors** - Pluggable stream processing
|
364
|
+
4. **Integration APIs** - External monitoring system support
|
365
|
+
|
366
|
+
## Usage Examples
|
367
|
+
|
368
|
+
### 1. CLI with Streaming Output
|
369
|
+
```bash
|
370
|
+
# Stream all events to console
|
371
|
+
agentic plan "Build a Ruby gem" --stream=console
|
372
|
+
|
373
|
+
# Stream specific event types
|
374
|
+
agentic plan "Analyze codebase" --stream=console --filter=task,agent
|
375
|
+
|
376
|
+
# Stream to file for later analysis
|
377
|
+
agentic plan "Generate tests" --stream=file:/tmp/execution.jsonl
|
378
|
+
```
|
379
|
+
|
380
|
+
### 2. Programmatic Streaming
|
381
|
+
```ruby
|
382
|
+
# Create custom stream processor
|
383
|
+
processor = StreamProcessor.new(
|
384
|
+
ConsoleStream.new,
|
385
|
+
filters: [
|
386
|
+
->(event) { event[:type].to_s.include?('task') },
|
387
|
+
->(event) { event[:metadata][:importance] == :high }
|
388
|
+
],
|
389
|
+
formatters: [
|
390
|
+
JSONFormatter.new,
|
391
|
+
TimestampFormatter.new
|
392
|
+
]
|
393
|
+
)
|
394
|
+
|
395
|
+
# Register with hub
|
396
|
+
StreamingObservabilityHub.instance.add_processor(:custom, processor)
|
397
|
+
|
398
|
+
# Execute with streaming
|
399
|
+
orchestrator = PlanOrchestrator.new(lifecycle_hooks: streaming_hooks)
|
400
|
+
result = orchestrator.execute_plan(agent_provider)
|
401
|
+
```
|
402
|
+
|
403
|
+
### 3. Web Dashboard Integration
|
404
|
+
```ruby
|
405
|
+
# WebSocket stream for browser dashboard
|
406
|
+
ws_stream = WebSocketStream.new(port: 8080, path: '/events')
|
407
|
+
StreamingObservabilityHub.instance.add_stream(:dashboard, ws_stream)
|
408
|
+
|
409
|
+
# Filtered stream for performance metrics only
|
410
|
+
metrics_stream = FilteredStream.new(
|
411
|
+
ws_stream,
|
412
|
+
filter: ->(event) { event[:type].to_s.include?('metrics') }
|
413
|
+
)
|
414
|
+
```
|
415
|
+
|
416
|
+
## Configuration
|
417
|
+
|
418
|
+
### Stream Configuration
|
419
|
+
```yaml
|
420
|
+
streaming:
|
421
|
+
enabled: true
|
422
|
+
default_streams:
|
423
|
+
- type: console
|
424
|
+
level: info
|
425
|
+
- type: file
|
426
|
+
path: logs/execution_stream.jsonl
|
427
|
+
level: debug
|
428
|
+
|
429
|
+
filters:
|
430
|
+
console:
|
431
|
+
include: [task_started, task_completed, plan_completed]
|
432
|
+
exclude: [llm_chunk, debug_info]
|
433
|
+
|
434
|
+
file:
|
435
|
+
include: "*"
|
436
|
+
|
437
|
+
metrics:
|
438
|
+
aggregation_window: 60
|
439
|
+
emit_interval: 10
|
440
|
+
track_performance: true
|
441
|
+
```
|
442
|
+
|
443
|
+
### Event Schema
|
444
|
+
```json
|
445
|
+
{
|
446
|
+
"timestamp": "2025-06-03T10:30:00Z",
|
447
|
+
"event_type": "task_started",
|
448
|
+
"source": {
|
449
|
+
"component": "Task",
|
450
|
+
"id": "task-123",
|
451
|
+
"version": "0.2.0"
|
452
|
+
},
|
453
|
+
"payload": {
|
454
|
+
"task_id": "task-123",
|
455
|
+
"description": "Analyze Ruby codebase",
|
456
|
+
"agent_spec": {...}
|
457
|
+
},
|
458
|
+
"metadata": {
|
459
|
+
"session_id": "session-456",
|
460
|
+
"plan_id": "plan-789",
|
461
|
+
"importance": "high",
|
462
|
+
"estimated_duration": 30
|
463
|
+
}
|
464
|
+
}
|
465
|
+
```
|
466
|
+
|
467
|
+
## Performance Considerations
|
468
|
+
|
469
|
+
### Stream Buffering
|
470
|
+
- Configurable buffer sizes for high-throughput scenarios
|
471
|
+
- Automatic flushing based on time or size thresholds
|
472
|
+
- Memory-conscious buffering with overflow handling
|
473
|
+
|
474
|
+
### Asynchronous Processing
|
475
|
+
- Non-blocking event emission to prevent execution delays
|
476
|
+
- Background thread pools for stream processing
|
477
|
+
- Circuit breaker pattern for failing streams
|
478
|
+
|
479
|
+
### Resource Management
|
480
|
+
- Automatic stream cleanup and resource deallocation
|
481
|
+
- Configurable retention policies for persistent streams
|
482
|
+
- Memory usage monitoring and alerts
|
483
|
+
|
484
|
+
## Security and Privacy
|
485
|
+
|
486
|
+
### Event Filtering
|
487
|
+
- Automatic PII detection and redaction
|
488
|
+
- Configurable content filters for sensitive data
|
489
|
+
- Role-based access control for different stream types
|
490
|
+
|
491
|
+
### Data Protection
|
492
|
+
- Encryption for network streams (WSS, HTTPS)
|
493
|
+
- Secure credential handling for external integrations
|
494
|
+
- Audit logging for stream access and configuration changes
|
495
|
+
|
496
|
+
## Monitoring and Alerting
|
497
|
+
|
498
|
+
### Stream Health
|
499
|
+
- Automatic detection of failing streams
|
500
|
+
- Performance metrics for stream processing
|
501
|
+
- Alerting for abnormal event patterns
|
502
|
+
|
503
|
+
### System Integration
|
504
|
+
- OpenTelemetry compatibility for observability platforms
|
505
|
+
- Prometheus metrics export capability
|
506
|
+
- Custom webhook integrations for external alerting
|
507
|
+
|
508
|
+
## Conclusion
|
509
|
+
|
510
|
+
This streaming observability architecture provides comprehensive real-time insights into all aspects of the Agentic framework while maintaining performance and extensibility. The phased implementation approach ensures gradual adoption with immediate value at each stage.
|
data/exe/agentic
CHANGED
data/lefthook.yml
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Agentic
|
4
|
+
# The AdaptationEngine enables feedback-driven adjustments to agents and tasks.
|
5
|
+
# It is part of the Verification Layer and focuses on applying learned improvements
|
6
|
+
# based on feedback, outcomes, and performance metrics.
|
7
|
+
class AdaptationEngine
|
8
|
+
# Initialize a new AdaptationEngine.
|
9
|
+
#
|
10
|
+
# @param [Hash] options Configuration options for the adaptation engine
|
11
|
+
# @option options [Logger] :logger Custom logger instance
|
12
|
+
# @option options [Integer] :adaptation_threshold Minimum confidence score to trigger adaptation (0-100)
|
13
|
+
# @option options [Boolean] :auto_adapt Whether to automatically apply adaptations
|
14
|
+
def initialize(options = {})
|
15
|
+
@logger = options[:logger] || Agentic.logger
|
16
|
+
@adaptation_threshold = options[:adaptation_threshold] || 75
|
17
|
+
@auto_adapt = options.fetch(:auto_adapt, false)
|
18
|
+
@adaptation_registry = {}
|
19
|
+
@feedback_history = []
|
20
|
+
end
|
21
|
+
|
22
|
+
# Register an adaptation strategy for a specific component/context
|
23
|
+
#
|
24
|
+
# @param [Symbol] component The component or context to adapt (e.g., :agent, :task, :prompt)
|
25
|
+
# @param [Proc] strategy A callable that implements the adaptation logic
|
26
|
+
# @return [Boolean] True if registration was successful
|
27
|
+
def register_adaptation_strategy(component, strategy)
|
28
|
+
return false unless strategy.respond_to?(:call)
|
29
|
+
|
30
|
+
@adaptation_registry[component] = strategy
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
# Process feedback and determine if adaptation is needed
|
35
|
+
#
|
36
|
+
# @param [Hash] feedback The feedback data to process
|
37
|
+
# @option feedback [Symbol] :component The component receiving feedback
|
38
|
+
# @option feedback [Object] :target The specific instance to adapt
|
39
|
+
# @option feedback [Hash] :metrics Performance metrics
|
40
|
+
# @option feedback [String, Symbol] :outcome Success/failure indicator
|
41
|
+
# @option feedback [String] :suggestion Suggested improvement
|
42
|
+
# @return [Hash] Result of the adaptation process
|
43
|
+
def process_feedback(feedback)
|
44
|
+
record_feedback(feedback)
|
45
|
+
|
46
|
+
adaptation_needed = determine_if_adaptation_needed(feedback)
|
47
|
+
return {adapted: false, reason: "Adaptation threshold not met"} unless adaptation_needed
|
48
|
+
|
49
|
+
if @auto_adapt
|
50
|
+
apply_adaptation(feedback)
|
51
|
+
else
|
52
|
+
{
|
53
|
+
adapted: false,
|
54
|
+
adaptation_suggested: true,
|
55
|
+
suggestion: feedback[:suggestion]
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Apply an adaptation based on feedback
|
61
|
+
#
|
62
|
+
# @param [Hash] feedback The feedback data to use for adaptation
|
63
|
+
# @return [Hash] Result of the adaptation attempt
|
64
|
+
def apply_adaptation(feedback)
|
65
|
+
component = feedback[:component]
|
66
|
+
|
67
|
+
unless @adaptation_registry.key?(component)
|
68
|
+
return {adapted: false, reason: "No adaptation strategy registered for #{component}"}
|
69
|
+
end
|
70
|
+
|
71
|
+
strategy = @adaptation_registry[component]
|
72
|
+
|
73
|
+
begin
|
74
|
+
result = strategy.call(feedback)
|
75
|
+
{
|
76
|
+
adapted: true,
|
77
|
+
component: component,
|
78
|
+
target: feedback[:target],
|
79
|
+
result: result
|
80
|
+
}
|
81
|
+
rescue => e
|
82
|
+
@logger.error("Adaptation failed: #{e.message}")
|
83
|
+
{
|
84
|
+
adapted: false,
|
85
|
+
error: e.message,
|
86
|
+
component: component
|
87
|
+
}
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Retrieve adaptation history for a specific component
|
92
|
+
#
|
93
|
+
# @param [Symbol] component The component to get history for
|
94
|
+
# @return [Array<Hash>] History of adaptations for the component
|
95
|
+
def adaptation_history(component = nil)
|
96
|
+
if component
|
97
|
+
@feedback_history.select { |f| f[:component] == component }
|
98
|
+
else
|
99
|
+
@feedback_history
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
# Record feedback in the history
|
106
|
+
#
|
107
|
+
# @param [Hash] feedback The feedback to record
|
108
|
+
def record_feedback(feedback)
|
109
|
+
@feedback_history << feedback.merge(timestamp: Time.now)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Determine if adaptation is needed based on feedback
|
113
|
+
#
|
114
|
+
# @param [Hash] feedback The feedback to analyze
|
115
|
+
# @return [Boolean] True if adaptation is needed
|
116
|
+
def determine_if_adaptation_needed(feedback)
|
117
|
+
# Simple implementation - can be expanded with more sophisticated logic
|
118
|
+
return false unless feedback[:metrics] && feedback[:metrics][:confidence]
|
119
|
+
|
120
|
+
confidence_score = feedback[:metrics][:confidence]
|
121
|
+
confidence_score < @adaptation_threshold
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|