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,325 @@
|
|
1
|
+
# Prompt Generation Architecture
|
2
|
+
|
3
|
+
## Overview
|
4
|
+
|
5
|
+
This document specifies the architecture for prompt generation within the Agentic framework. Prompts serve as the critical interface between Tasks and Agents, translating structured data and instructions into a format that guides agent execution and shapes output quality.
|
6
|
+
|
7
|
+
## Core Principles
|
8
|
+
|
9
|
+
1. **Separation of Concerns**: Prompt generation logic should be separable from task execution
|
10
|
+
2. **Templating**: Prompt structures should be templateable and versionable
|
11
|
+
3. **Adaptability**: Prompts should adapt to different agent capabilities and domains
|
12
|
+
4. **Context Integration**: Prompts should effectively incorporate relevant context
|
13
|
+
5. **Quality Optimization**: Prompt design should optimize for output quality and consistency
|
14
|
+
|
15
|
+
## Prompt Anatomy
|
16
|
+
|
17
|
+
A well-structured prompt typically includes these elements:
|
18
|
+
|
19
|
+
```
|
20
|
+
[System Instructions]
|
21
|
+
You are an agent with the role of {role} and purpose of {purpose}.
|
22
|
+
{backstory}
|
23
|
+
{constraints}
|
24
|
+
|
25
|
+
[Task Description]
|
26
|
+
Your task is to {description}.
|
27
|
+
|
28
|
+
[Context]
|
29
|
+
Here is the relevant information you need to complete this task:
|
30
|
+
{context}
|
31
|
+
|
32
|
+
[Input Parameters]
|
33
|
+
The following input must be processed:
|
34
|
+
{input_json}
|
35
|
+
|
36
|
+
[Output Requirements]
|
37
|
+
Provide your response in the following format:
|
38
|
+
{output_schema}
|
39
|
+
|
40
|
+
[Special Instructions]
|
41
|
+
{special_instructions}
|
42
|
+
```
|
43
|
+
|
44
|
+
## Architectural Components
|
45
|
+
|
46
|
+
### 1. PromptBuilder
|
47
|
+
|
48
|
+
Central service responsible for constructing prompts from templates and data:
|
49
|
+
|
50
|
+
```
|
51
|
+
Task + PromptBuilder → Formatted Prompt
|
52
|
+
```
|
53
|
+
|
54
|
+
Responsibilities:
|
55
|
+
- Apply prompt templates
|
56
|
+
- Insert task-specific data
|
57
|
+
- Format according to agent requirements
|
58
|
+
- Optimize prompt structure
|
59
|
+
|
60
|
+
### 2. PromptTemplate
|
61
|
+
|
62
|
+
Defines the structure and content patterns for different prompt types:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
class PromptTemplate
|
66
|
+
attr_reader :id, :name, :template, :version
|
67
|
+
|
68
|
+
def initialize(id:, name:, template:, version: "1.0")
|
69
|
+
@id = id
|
70
|
+
@name = name
|
71
|
+
@template = template
|
72
|
+
@version = version
|
73
|
+
end
|
74
|
+
|
75
|
+
def render(data)
|
76
|
+
# Apply data to template
|
77
|
+
end
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
Responsibilities:
|
82
|
+
- Store prompt structure
|
83
|
+
- Support variable interpolation
|
84
|
+
- Enable versioning
|
85
|
+
- Allow domain customization
|
86
|
+
|
87
|
+
### 3. PromptRegistry
|
88
|
+
|
89
|
+
Manages the collection of available prompt templates:
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
class PromptRegistry
|
93
|
+
include Singleton
|
94
|
+
|
95
|
+
def initialize
|
96
|
+
@templates = {}
|
97
|
+
end
|
98
|
+
|
99
|
+
def register(template)
|
100
|
+
@templates[template.id] = template
|
101
|
+
end
|
102
|
+
|
103
|
+
def get(id)
|
104
|
+
@templates[id]
|
105
|
+
end
|
106
|
+
|
107
|
+
def find_by_task_type(task_type)
|
108
|
+
# Return appropriate template for task type
|
109
|
+
end
|
110
|
+
end
|
111
|
+
```
|
112
|
+
|
113
|
+
Responsibilities:
|
114
|
+
- Store available templates
|
115
|
+
- Provide template lookup by ID
|
116
|
+
- Support template discovery
|
117
|
+
- Manage template versioning
|
118
|
+
|
119
|
+
### 4. PromptOptimizer
|
120
|
+
|
121
|
+
Improves prompt effectiveness based on historical performance:
|
122
|
+
|
123
|
+
```
|
124
|
+
Historical Prompts + Outcomes → PromptOptimizer → Improved Template
|
125
|
+
```
|
126
|
+
|
127
|
+
Responsibilities:
|
128
|
+
- Analyze prompt effectiveness
|
129
|
+
- Suggest improvements
|
130
|
+
- Implement best practices
|
131
|
+
- Adapt to agent capabilities
|
132
|
+
|
133
|
+
## Prompt Generation Patterns
|
134
|
+
|
135
|
+
### 1. Basic Template Application
|
136
|
+
|
137
|
+
Simplest pattern applying task data to a template:
|
138
|
+
|
139
|
+
```
|
140
|
+
Task Data + Template → PromptBuilder → Formatted Prompt
|
141
|
+
```
|
142
|
+
|
143
|
+
Implementation considerations:
|
144
|
+
- Variable interpolation
|
145
|
+
- Formatting for readability
|
146
|
+
- Handling missing data
|
147
|
+
- Default values
|
148
|
+
|
149
|
+
### 2. Contextual Enhancement
|
150
|
+
|
151
|
+
Enriches prompts with relevant context:
|
152
|
+
|
153
|
+
```
|
154
|
+
Task Data + Context + Template → PromptBuilder → Enhanced Prompt
|
155
|
+
```
|
156
|
+
|
157
|
+
Implementation considerations:
|
158
|
+
- Context prioritization
|
159
|
+
- Relevance determination
|
160
|
+
- Context summarization
|
161
|
+
- Information ordering
|
162
|
+
|
163
|
+
### 3. Agent-Specific Adaptation
|
164
|
+
|
165
|
+
Tailors prompts to specific agent capabilities:
|
166
|
+
|
167
|
+
```
|
168
|
+
Task Data + Template + Agent Capabilities → PromptBuilder → Adapted Prompt
|
169
|
+
```
|
170
|
+
|
171
|
+
Implementation considerations:
|
172
|
+
- Agent capability detection
|
173
|
+
- Feature availability checking
|
174
|
+
- Prompt complexity adjustment
|
175
|
+
- Instruction specificity
|
176
|
+
|
177
|
+
### 4. Dynamic Optimization
|
178
|
+
|
179
|
+
Adjusts prompts based on real-time feedback:
|
180
|
+
|
181
|
+
```
|
182
|
+
Initial Prompt + Feedback → PromptOptimizer → Refined Prompt
|
183
|
+
```
|
184
|
+
|
185
|
+
Implementation considerations:
|
186
|
+
- Incremental refinement
|
187
|
+
- Feedback loop integration
|
188
|
+
- Performance metrics evaluation
|
189
|
+
- A/B testing
|
190
|
+
|
191
|
+
## Responsibility Distribution
|
192
|
+
|
193
|
+
### Task Class
|
194
|
+
|
195
|
+
- Provide task data for prompt creation
|
196
|
+
- Request prompt generation when needed
|
197
|
+
- Pass prompt to agent during execution
|
198
|
+
- Store prompt with execution record
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
# In Task class
|
202
|
+
def build_prompt
|
203
|
+
PromptBuilder.instance.build_for_task(self)
|
204
|
+
end
|
205
|
+
```
|
206
|
+
|
207
|
+
### Agent Class
|
208
|
+
|
209
|
+
- Consume formatted prompts
|
210
|
+
- Provide capability information to prompt builder
|
211
|
+
- Report prompt effectiveness
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
# In Agent class
|
215
|
+
def execute(prompt)
|
216
|
+
# Use prompt to guide execution
|
217
|
+
end
|
218
|
+
```
|
219
|
+
|
220
|
+
### PromptBuilder
|
221
|
+
|
222
|
+
- Central service for prompt construction
|
223
|
+
- Apply templates to task data
|
224
|
+
- Format prompts for specific agents
|
225
|
+
- Implement optimization strategies
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
# PromptBuilder implementation
|
229
|
+
def build_for_task(task, agent_capabilities = {})
|
230
|
+
template = PromptRegistry.instance.find_by_task_type(task.type)
|
231
|
+
context = ContextManager.instance.get_context_for_task(task)
|
232
|
+
|
233
|
+
template.render({
|
234
|
+
role: task.agent_spec["role"],
|
235
|
+
purpose: task.agent_spec["purpose"],
|
236
|
+
description: task.description,
|
237
|
+
context: format_context(context),
|
238
|
+
input_json: JSON.pretty_generate(task.input),
|
239
|
+
output_schema: task.output_schema&.to_json,
|
240
|
+
special_instructions: task.special_instructions
|
241
|
+
})
|
242
|
+
end
|
243
|
+
```
|
244
|
+
|
245
|
+
## Template Management
|
246
|
+
|
247
|
+
### 1. Template Storage
|
248
|
+
|
249
|
+
Templates can be stored in:
|
250
|
+
- Database records
|
251
|
+
- YAML/JSON files
|
252
|
+
- Code-based definitions
|
253
|
+
|
254
|
+
Implementation considerations:
|
255
|
+
- Searchability
|
256
|
+
- Version control
|
257
|
+
- Hot reloading
|
258
|
+
- Environment-specific templates
|
259
|
+
|
260
|
+
### 2. Template Authoring
|
261
|
+
|
262
|
+
Templates can be authored by:
|
263
|
+
- System developers
|
264
|
+
- Domain experts
|
265
|
+
- Automated systems
|
266
|
+
|
267
|
+
Implementation considerations:
|
268
|
+
- Authoring interface
|
269
|
+
- Template validation
|
270
|
+
- Best practice enforcement
|
271
|
+
- Template testing
|
272
|
+
|
273
|
+
### 3. Template Versioning
|
274
|
+
|
275
|
+
Templates should support versioning:
|
276
|
+
- Semantic versioning (Major.Minor.Patch)
|
277
|
+
- Change tracking
|
278
|
+
- Backward compatibility
|
279
|
+
- Gradual rollout
|
280
|
+
|
281
|
+
## Implementation Approach
|
282
|
+
|
283
|
+
1. **Start Simple**: Begin with basic string templates
|
284
|
+
2. **Add Structure**: Implement formal template objects
|
285
|
+
3. **Create Registry**: Develop central template management
|
286
|
+
4. **Enable Customization**: Support domain-specific templates
|
287
|
+
5. **Implement Optimization**: Add performance-based improvements
|
288
|
+
|
289
|
+
## Development Priorities
|
290
|
+
|
291
|
+
1. Define PromptTemplate class
|
292
|
+
2. Implement basic PromptBuilder
|
293
|
+
3. Create PromptRegistry
|
294
|
+
4. Integrate with Task class
|
295
|
+
5. Develop optimization strategies
|
296
|
+
6. Add template management tools
|
297
|
+
|
298
|
+
## Integration with Other Components
|
299
|
+
|
300
|
+
### Input Handling
|
301
|
+
|
302
|
+
- Input data format affects prompt structure
|
303
|
+
- Schema information guides input presentation
|
304
|
+
|
305
|
+
### Output Handling
|
306
|
+
|
307
|
+
- Output schema requirements must be clearly communicated in prompts
|
308
|
+
- Output format instructions affect result quality
|
309
|
+
|
310
|
+
### Verification
|
311
|
+
|
312
|
+
- Prompt quality directly impacts verification success
|
313
|
+
- Verification results can inform prompt improvements
|
314
|
+
|
315
|
+
## Considerations for Future Extensions
|
316
|
+
|
317
|
+
1. **Multi-modal Prompts**: Support for image, audio, or other media in prompts
|
318
|
+
2. **Chain-of-Thought**: Structured prompting for complex reasoning
|
319
|
+
3. **Few-Shot Learning**: Including examples in prompts
|
320
|
+
4. **Interactive Prompts**: Prompts that evolve through agent interaction
|
321
|
+
5. **Meta-Prompting**: Prompts that help agents create better prompts
|
322
|
+
|
323
|
+
## Conclusion
|
324
|
+
|
325
|
+
A well-designed prompt generation system is essential for effective agent execution. By separating prompt generation from task execution, implementing templating and optimization, and ensuring adaptability across domains and agent types, the Agentic framework can maximize agent effectiveness while maintaining consistency and quality.
|
@@ -0,0 +1,353 @@
|
|
1
|
+
# Task Failure Handling Architecture
|
2
|
+
|
3
|
+
## Overview
|
4
|
+
|
5
|
+
This document outlines the architectural design decision for handling task failures within the Agentic framework. It addresses limitations of exception-based failure handling and proposes a more robust approach compatible with complex execution scenarios.
|
6
|
+
|
7
|
+
## Context
|
8
|
+
|
9
|
+
Tasks in Agentic represent discrete units of work executed by agents. The initial design considered raising exceptions when task execution fails, which presents several challenges:
|
10
|
+
|
11
|
+
- **Orchestration Complexity**: In multi-step or parallel execution scenarios, exceptions disrupt the entire orchestration flow
|
12
|
+
- **Recovery Difficulty**: Exception-based approaches complicate retry mechanisms and graceful degradation
|
13
|
+
- **Workflow Continuity**: Dependent tasks may be able to proceed with partial results or alternative paths
|
14
|
+
- **Failure Analysis**: Immediate exception propagation may limit comprehensive failure tracking and analysis
|
15
|
+
|
16
|
+
## Design Decision
|
17
|
+
|
18
|
+
### Result-Oriented Failure Handling
|
19
|
+
|
20
|
+
Rather than raising exceptions, task execution will use a result-oriented approach:
|
21
|
+
|
22
|
+
1. **Task Result Object**: Introduce a TaskResult class to encapsulate execution outcomes
|
23
|
+
2. **Status-Based Flow Control**: Use task status to indicate completion state
|
24
|
+
3. **Error Preservation**: Store error details in the task object itself
|
25
|
+
4. **Observable Failure**: Implement event-based notification for status changes
|
26
|
+
|
27
|
+
### TaskResult Structure
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class TaskResult
|
31
|
+
attr_reader :success, :output, :error, :task_id
|
32
|
+
|
33
|
+
def initialize(task_id:, success:, output: nil, error: nil)
|
34
|
+
@task_id = task_id
|
35
|
+
@success = success
|
36
|
+
@output = output
|
37
|
+
@error = error
|
38
|
+
end
|
39
|
+
|
40
|
+
def successful?
|
41
|
+
@success
|
42
|
+
end
|
43
|
+
|
44
|
+
def failed?
|
45
|
+
!@success
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
### Task Status Lifecycle
|
51
|
+
|
52
|
+
```
|
53
|
+
┌─────────┐ ┌─────────────┐ ┌───────────┐
|
54
|
+
│ pending ├────►│ in_progress ├────►│ completed │
|
55
|
+
└─────────┘ └──────┬──────┘ └───────────┘
|
56
|
+
│
|
57
|
+
▼
|
58
|
+
┌─────────┐ ┌──────────┐
|
59
|
+
│ failed ├─────►│ retrying │
|
60
|
+
└─────┬───┘ └───┬──────┘
|
61
|
+
│ │
|
62
|
+
└──────────────┘
|
63
|
+
```
|
64
|
+
|
65
|
+
### Task Error Representation
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
class TaskError
|
69
|
+
attr_reader :message, :type, :timestamp, :context
|
70
|
+
|
71
|
+
def initialize(message:, type:, context: {})
|
72
|
+
@message = message
|
73
|
+
@type = type
|
74
|
+
@timestamp = Time.now
|
75
|
+
@context = context
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_h
|
79
|
+
{
|
80
|
+
message: @message,
|
81
|
+
type: @type,
|
82
|
+
timestamp: @timestamp.iso8601,
|
83
|
+
context: @context
|
84
|
+
}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
```
|
88
|
+
|
89
|
+
### Observable Failure Pattern
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
module TaskObservable
|
93
|
+
def add_observer(observer)
|
94
|
+
@observers ||= []
|
95
|
+
@observers << observer
|
96
|
+
end
|
97
|
+
|
98
|
+
def notify_status_change(old_status, new_status)
|
99
|
+
return unless @observers
|
100
|
+
|
101
|
+
@observers.each do |observer|
|
102
|
+
observer.on_task_status_change(self, old_status, new_status)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
## Implementation Details
|
109
|
+
|
110
|
+
### Task Class Modifications
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
class Task
|
114
|
+
include TaskObservable
|
115
|
+
|
116
|
+
attr_reader :id, :description, :agent_spec, :input, :output, :status, :error
|
117
|
+
|
118
|
+
# ... existing initialization ...
|
119
|
+
|
120
|
+
def perform(agent)
|
121
|
+
old_status = @status
|
122
|
+
@status = :in_progress
|
123
|
+
notify_status_change(old_status, @status)
|
124
|
+
|
125
|
+
begin
|
126
|
+
@output = agent.execute(build_prompt)
|
127
|
+
old_status = @status
|
128
|
+
@status = :completed
|
129
|
+
notify_status_change(old_status, @status)
|
130
|
+
|
131
|
+
TaskResult.new(
|
132
|
+
task_id: @id,
|
133
|
+
success: true,
|
134
|
+
output: @output
|
135
|
+
)
|
136
|
+
rescue StandardError => e
|
137
|
+
@error = TaskError.new(
|
138
|
+
message: e.message,
|
139
|
+
type: e.class.name,
|
140
|
+
context: {
|
141
|
+
backtrace: e.backtrace&.first(10),
|
142
|
+
agent_id: agent.id
|
143
|
+
}
|
144
|
+
)
|
145
|
+
|
146
|
+
old_status = @status
|
147
|
+
@status = :failed
|
148
|
+
notify_status_change(old_status, @status)
|
149
|
+
|
150
|
+
Agentic.logger.error("Task execution failed: #{e.message}")
|
151
|
+
|
152
|
+
TaskResult.new(
|
153
|
+
task_id: @id,
|
154
|
+
success: false,
|
155
|
+
error: @error
|
156
|
+
)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def retry(agent)
|
161
|
+
return unless @status == :failed
|
162
|
+
|
163
|
+
old_status = @status
|
164
|
+
@status = :retrying
|
165
|
+
notify_status_change(old_status, @status)
|
166
|
+
|
167
|
+
perform(agent)
|
168
|
+
end
|
169
|
+
|
170
|
+
# ... other methods ...
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
174
|
+
### PlanOrchestrator Usage
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
class PlanOrchestrator
|
178
|
+
def execute_task(task, agent)
|
179
|
+
result = task.perform(agent)
|
180
|
+
|
181
|
+
if result.successful?
|
182
|
+
# Process successful outcome
|
183
|
+
process_output(task, result.output)
|
184
|
+
else
|
185
|
+
# Handle failure based on policy
|
186
|
+
handle_task_failure(task, result.error)
|
187
|
+
end
|
188
|
+
|
189
|
+
result
|
190
|
+
end
|
191
|
+
|
192
|
+
def handle_task_failure(task, error)
|
193
|
+
case error.type
|
194
|
+
when "TimeoutError"
|
195
|
+
# Maybe retry with longer timeout
|
196
|
+
retry_with_extended_timeout(task)
|
197
|
+
when "AuthenticationError"
|
198
|
+
# Maybe request new credentials
|
199
|
+
request_authentication_update(task)
|
200
|
+
else
|
201
|
+
# Apply general failure policy
|
202
|
+
apply_failure_policy(task)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# ... other methods ...
|
207
|
+
end
|
208
|
+
```
|
209
|
+
|
210
|
+
## Failure Handling Strategies
|
211
|
+
|
212
|
+
### Retry with Backoff
|
213
|
+
|
214
|
+
For transient failures, implement exponential backoff:
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
def retry_with_backoff(task, agent, max_attempts = 3)
|
218
|
+
attempts = 0
|
219
|
+
|
220
|
+
while attempts < max_attempts
|
221
|
+
sleep_duration = 2 ** attempts
|
222
|
+
sleep(sleep_duration)
|
223
|
+
|
224
|
+
attempts += 1
|
225
|
+
result = task.retry(agent)
|
226
|
+
|
227
|
+
return result if result.successful?
|
228
|
+
end
|
229
|
+
|
230
|
+
# Max retries exceeded
|
231
|
+
TaskResult.new(
|
232
|
+
task_id: task.id,
|
233
|
+
success: false,
|
234
|
+
error: TaskError.new(
|
235
|
+
message: "Max retry attempts exceeded",
|
236
|
+
type: "MaxRetriesExceededError",
|
237
|
+
context: { attempts: attempts }
|
238
|
+
)
|
239
|
+
)
|
240
|
+
end
|
241
|
+
```
|
242
|
+
|
243
|
+
### Alternative Task Path
|
244
|
+
|
245
|
+
When a task fails, try an alternative approach:
|
246
|
+
|
247
|
+
```ruby
|
248
|
+
def execute_with_fallback(primary_task, fallback_task, agent)
|
249
|
+
result = primary_task.perform(agent)
|
250
|
+
|
251
|
+
if result.successful?
|
252
|
+
return result
|
253
|
+
end
|
254
|
+
|
255
|
+
# Try fallback task instead
|
256
|
+
fallback_result = fallback_task.perform(agent)
|
257
|
+
|
258
|
+
# Record relationship between tasks
|
259
|
+
primary_task.add_related_task(fallback_task.id, "fallback")
|
260
|
+
|
261
|
+
fallback_result
|
262
|
+
end
|
263
|
+
```
|
264
|
+
|
265
|
+
### Human Intervention
|
266
|
+
|
267
|
+
For critical failures, request human assistance:
|
268
|
+
|
269
|
+
```ruby
|
270
|
+
def request_human_intervention(task, error)
|
271
|
+
intervention_request = HumanInterventionRequest.new(
|
272
|
+
task_id: task.id,
|
273
|
+
error: error,
|
274
|
+
suggested_actions: generate_intervention_suggestions(error),
|
275
|
+
priority: calculate_intervention_priority(task, error)
|
276
|
+
)
|
277
|
+
|
278
|
+
InterventionPortal.instance.submit(intervention_request)
|
279
|
+
|
280
|
+
# Return a pending result while waiting for human input
|
281
|
+
TaskResult.new(
|
282
|
+
task_id: task.id,
|
283
|
+
success: false,
|
284
|
+
error: TaskError.new(
|
285
|
+
message: "Awaiting human intervention",
|
286
|
+
type: "HumanInterventionRequiredError",
|
287
|
+
context: { intervention_id: intervention_request.id }
|
288
|
+
)
|
289
|
+
)
|
290
|
+
end
|
291
|
+
```
|
292
|
+
|
293
|
+
## Benefits of This Approach
|
294
|
+
|
295
|
+
1. **Enhanced Resilience**: System continues functioning despite individual task failures
|
296
|
+
2. **Execution Flexibility**: Supports parallel, sequential, and conditional execution patterns
|
297
|
+
3. **Better Diagnostics**: Comprehensive error context enables more effective debugging
|
298
|
+
4. **Adaptable Recovery**: Multiple recovery strategies can be applied based on failure context
|
299
|
+
5. **Operational Visibility**: Failure patterns can be analyzed across executions
|
300
|
+
6. **Status Observability**: Other components can react to status changes through the observer pattern
|
301
|
+
|
302
|
+
## Drawbacks and Mitigations
|
303
|
+
|
304
|
+
1. **Increased Complexity**: More complex than simple exceptions
|
305
|
+
- Mitigation: Provide helper methods and clear documentation
|
306
|
+
|
307
|
+
2. **Error Propagation**: May mask serious errors that should halt execution
|
308
|
+
- Mitigation: Include critical error classification with different handling
|
309
|
+
|
310
|
+
3. **Memory Usage**: Storing error details consumes more memory
|
311
|
+
- Mitigation: Implement configurable error detail retention policies
|
312
|
+
|
313
|
+
## Integration with Other Components
|
314
|
+
|
315
|
+
### Verification Layer
|
316
|
+
|
317
|
+
Task failure information feeds into verification:
|
318
|
+
|
319
|
+
```ruby
|
320
|
+
def verify_with_failure_awareness(task)
|
321
|
+
# Include failure history in verification context
|
322
|
+
verification_context = {
|
323
|
+
failure_history: task.failure_history,
|
324
|
+
current_error: task.error
|
325
|
+
}
|
326
|
+
|
327
|
+
VerificationHub.instance.verify(task, verification_context)
|
328
|
+
end
|
329
|
+
```
|
330
|
+
|
331
|
+
### Learning System
|
332
|
+
|
333
|
+
Failures contribute to system learning:
|
334
|
+
|
335
|
+
```ruby
|
336
|
+
def record_failure_patterns(task, error)
|
337
|
+
ExecutionHistoryStore.instance.record_failure(
|
338
|
+
task_type: task.type,
|
339
|
+
error_type: error.type,
|
340
|
+
context: error.context,
|
341
|
+
resolution_strategy: task.resolution_strategy
|
342
|
+
)
|
343
|
+
|
344
|
+
# Analyze failure patterns periodically
|
345
|
+
PatternRecognizer.instance.analyze_failures if should_analyze_patterns?
|
346
|
+
end
|
347
|
+
```
|
348
|
+
|
349
|
+
## Conclusion
|
350
|
+
|
351
|
+
This result-oriented approach to task failure handling offers significant advantages over exception-based designs, particularly for complex orchestration scenarios. It enables more resilient execution flows, flexible recovery strategies, and comprehensive failure analysis while maintaining system stability.
|
352
|
+
|
353
|
+
By storing error information within the task and using status-based flow control, the system can better handle parallel execution, support sophisticated retry mechanisms, and provide rich diagnostics for both automated and human-assisted recovery.
|