Skip to main content

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}