ralph_workflow/reducer/event/agent.rs
1// NOTE: split from reducer/event.rs to keep the main file under line limits.
2use crate::agents::AgentRole;
3use serde::{Deserialize, Serialize};
4
5/// Agent invocation and chain management events.
6///
7/// Events related to agent execution, fallback chains, model switching,
8/// rate limiting, and retry cycles. The agent chain provides fault tolerance
9/// through multiple fallback levels:
10///
11/// 1. Model level: Try different models for the same agent
12/// 2. Agent level: Switch to a fallback agent
13/// 3. Retry cycle: Start over with exponential backoff
14///
15/// # State Transitions
16///
17/// - `InvocationFailed(retriable=true)`: Advances to next model
18/// - `InvocationFailed(retriable=false)`: Typically switches to next agent (policy may vary by kind)
19/// - `RateLimited`: Typically immediate agent switch with prompt preservation
20/// - `ChainExhausted`: Starts new retry cycle
21/// - `InvocationSucceeded`: Clears continuation prompt
22#[derive(Clone, Serialize, Deserialize, Debug)]
23pub enum AgentEvent {
24 /// Agent invocation started.
25 InvocationStarted {
26 /// The role this agent is fulfilling.
27 role: AgentRole,
28 /// The agent being invoked.
29 agent: String,
30 /// The model being used, if specified.
31 model: Option<String>,
32 },
33 /// Agent invocation succeeded.
34 InvocationSucceeded {
35 /// The role this agent fulfilled.
36 role: AgentRole,
37 /// The agent that succeeded.
38 agent: String,
39 },
40 /// Agent invocation failed.
41 InvocationFailed {
42 /// The role this agent was fulfilling.
43 role: AgentRole,
44 /// The agent that failed.
45 agent: String,
46 /// The exit code from the agent process.
47 exit_code: i32,
48 /// The kind of error that occurred.
49 error_kind: super::AgentErrorKind,
50 /// Whether this error is retriable with the same agent.
51 retriable: bool,
52 },
53 /// Fallback triggered to switch to a different agent.
54 FallbackTriggered {
55 /// The role being fulfilled.
56 role: AgentRole,
57 /// The agent being switched from.
58 from_agent: String,
59 /// The agent being switched to.
60 to_agent: String,
61 },
62 /// Model fallback triggered within the same agent.
63 ModelFallbackTriggered {
64 /// The role being fulfilled.
65 role: AgentRole,
66 /// The agent whose model is changing.
67 agent: String,
68 /// The model being switched from.
69 from_model: String,
70 /// The model being switched to.
71 to_model: String,
72 },
73 /// Retry cycle started (all agents exhausted, starting over).
74 RetryCycleStarted {
75 /// The role being retried.
76 role: AgentRole,
77 /// The cycle number starting.
78 cycle: u32,
79 },
80 /// Agent chain exhausted (no more agents/models to try).
81 ChainExhausted {
82 /// The role whose chain is exhausted.
83 role: AgentRole,
84 },
85 /// Agent chain initialized with available agents.
86 ChainInitialized {
87 /// The role this chain is for.
88 role: AgentRole,
89 /// The agents available in this chain.
90 agents: Vec<String>,
91 /// Maximum number of retry cycles allowed for this chain.
92 max_cycles: u32,
93 /// Base retry-cycle delay in milliseconds.
94 retry_delay_ms: u64,
95 /// Exponential backoff multiplier.
96 backoff_multiplier: f64,
97 /// Maximum backoff delay in milliseconds.
98 max_backoff_ms: u64,
99 },
100 /// Agent hit rate limit (429).
101 ///
102 /// Effects/executors emit this as a *fact* event. The reducer decides
103 /// whether/when to switch agents.
104 RateLimited {
105 /// The role being fulfilled.
106 role: AgentRole,
107 /// The agent that hit the rate limit.
108 agent: String,
109 /// The prompt that was being executed when rate limit was hit.
110 /// This allows the next agent to continue the same work.
111 prompt_context: Option<String>,
112 },
113
114 /// Agent hit authentication failure (401/403).
115 ///
116 /// Effects/executors emit this as a *fact* event. The reducer decides
117 /// whether/when to switch agents.
118 AuthFailed {
119 /// The role being fulfilled.
120 role: AgentRole,
121 /// The agent that failed authentication.
122 agent: String,
123 },
124
125 /// Agent hit an idle timeout.
126 ///
127 /// Effects/executors emit this as a *fact* event. The reducer decides
128 /// whether/when to switch agents. Unlike rate limits, timeouts do not
129 /// preserve prompt context.
130 TimedOut {
131 /// The role being fulfilled.
132 role: AgentRole,
133 /// The agent that timed out.
134 agent: String,
135 },
136
137 /// Session established with agent.
138 ///
139 /// Emitted when an agent response includes a session ID that can be
140 /// used for XSD retry continuation. This enables reusing the same
141 /// session when retrying due to validation failures.
142 SessionEstablished {
143 /// The role this agent is fulfilling.
144 role: AgentRole,
145 /// The agent name.
146 agent: String,
147 /// The session ID returned by the agent.
148 session_id: String,
149 },
150
151 /// XSD validation failed for agent output.
152 ///
153 /// Emitted when agent output cannot be parsed or fails XSD validation.
154 /// Distinct from OutputValidationFailed events in phase-specific enums,
155 /// this is the canonical XSD retry trigger that the reducer uses to
156 /// decide whether to retry with the same agent/session or advance the chain.
157 XsdValidationFailed {
158 /// The role whose output failed validation.
159 role: AgentRole,
160 /// The artifact type that failed validation.
161 artifact: crate::reducer::state::ArtifactType,
162 /// Error message from validation.
163 error: String,
164 /// Current XSD retry count for this artifact.
165 retry_count: u32,
166 },
167
168 /// Template rendering failed due to missing required variables or unresolved placeholders.
169 ///
170 /// Emitted when a prompt template cannot be rendered because required variables
171 /// are missing or unresolved placeholders (e.g., `{{VAR}}`) remain in the output.
172 /// The reducer decides fallback policy, typically switching to the next agent.
173 TemplateVariablesInvalid {
174 /// The role whose template failed to render.
175 role: AgentRole,
176 /// The name of the template that failed.
177 template_name: String,
178 /// Variables that were required but not provided.
179 missing_variables: Vec<String>,
180 /// Placeholder patterns that remain unresolved in the rendered output.
181 unresolved_placeholders: Vec<String>,
182 },
183}