Skip to main content

ri_agent_graph/
outcome.rs

1//! Node execution outcomes and interrupt types.
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6/// The result of executing a node in the graph.
7#[derive(Debug, Clone)]
8pub enum NodeOutcome {
9    /// Node completed successfully, producing an output value.
10    Continue { output: Value },
11    /// Node requests an interrupt (e.g., needs user input).
12    Interrupt { interrupt: Interrupt },
13    /// Node execution failed.
14    Fail { error: String },
15}
16
17/// An interrupt raised by a node during execution.
18///
19/// Encodes what the node needs and provides a correlation token
20/// so that resume can be matched safely.
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct Interrupt {
23    /// What kind of interrupt this is.
24    pub kind: InterruptKind,
25    /// A JSON value describing what's needed (e.g., a prompt for the user).
26    pub payload: Value,
27    /// Unique correlation token so resume can be validated.
28    pub correlation_id: String,
29}
30
31impl Interrupt {
32    /// Create a new interrupt requesting user input.
33    pub fn await_input(payload: Value) -> Self {
34        Self {
35            kind: InterruptKind::AwaitInput,
36            payload,
37            correlation_id: uuid::Uuid::new_v4().to_string(),
38        }
39    }
40
41    /// Create a new interrupt requesting approval.
42    pub fn await_approval(payload: Value) -> Self {
43        Self {
44            kind: InterruptKind::AwaitApproval,
45            payload,
46            correlation_id: uuid::Uuid::new_v4().to_string(),
47        }
48    }
49
50    /// Create a custom interrupt.
51    pub fn custom(kind: impl Into<String>, payload: Value) -> Self {
52        Self {
53            kind: InterruptKind::Custom(kind.into()),
54            payload,
55            correlation_id: uuid::Uuid::new_v4().to_string(),
56        }
57    }
58}
59
60/// The kind of interrupt.
61#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
62pub enum InterruptKind {
63    /// Node needs user input to continue.
64    AwaitInput,
65    /// Node needs approval to continue.
66    AwaitApproval,
67    /// Custom interrupt kind.
68    Custom(String),
69}
70
71impl std::fmt::Display for InterruptKind {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        match self {
74            InterruptKind::AwaitInput => write!(f, "await_input"),
75            InterruptKind::AwaitApproval => write!(f, "await_approval"),
76            InterruptKind::Custom(s) => write!(f, "custom:{}", s),
77        }
78    }
79}