Skip to main content

WorkflowRuntime

Struct WorkflowRuntime 

Source
pub struct WorkflowRuntime { /* private fields */ }

Implementations§

Source§

impl WorkflowRuntime

Source

pub fn builder() -> WorkflowRuntimeBuilder

Examples found in repository?
examples/workflow.rs (line 204)
60async fn main() -> Result<(), String> {
61    let reusable_task = TaskDefinition {
62        id: "draft_release_note".to_string(),
63        target: TaskTarget::Capabilities(vec!["writing".to_string()]),
64        prompt: "Draft a concise release note for {{input.topic}}.".to_string(),
65        input_bindings: Default::default(),
66        input_transform: None,
67        output_transform: None,
68        output_key: Some("draft".to_string()),
69        retry_policy: None,
70        failure_policy: None,
71    };
72
73    let workflow = WorkflowDefinition {
74        id: "release-note-review".to_string(),
75        name: "Release Note Review".to_string(),
76        retry_policy: None,
77        failure_policy: Some(WorkflowFailurePolicy::ContinueBestEffort),
78        nodes: vec![
79            WorkflowNodeDefinition {
80                id: "draft".to_string(),
81                kind: WorkflowNodeKind::Task {
82                    task_id: Some("draft_release_note".to_string()),
83                    task: None,
84                },
85                output_key: None,
86                retry_policy: None,
87                failure_policy: None,
88            },
89            WorkflowNodeDefinition {
90                id: "review".to_string(),
91                kind: WorkflowNodeKind::Task {
92                    task_id: None,
93                    task: Some(TaskDefinition {
94                        id: "review_inline".to_string(),
95                        target: TaskTarget::AgentId("reviewer".to_string()),
96                        prompt:
97                            "Review the draft and suggest improvements:\n{{context.draft.content}}"
98                                .to_string(),
99                        input_bindings: Default::default(),
100                        input_transform: None,
101                        output_transform: None,
102                        output_key: Some("review".to_string()),
103                        retry_policy: None,
104                        failure_policy: None,
105                    }),
106                },
107                output_key: None,
108                retry_policy: None,
109                failure_policy: None,
110            },
111            WorkflowNodeDefinition {
112                id: "fact_check".to_string(),
113                kind: WorkflowNodeKind::Task {
114                    task_id: None,
115                    task: Some(TaskDefinition {
116                        id: "fact_check_inline".to_string(),
117                        target: TaskTarget::Capabilities(vec!["analysis".to_string()]),
118                        prompt:
119                            "Fact-check this draft for {{input.topic}}:\n{{context.draft.content}}"
120                                .to_string(),
121                        input_bindings: Default::default(),
122                        input_transform: None,
123                        output_transform: None,
124                        output_key: Some("fact_check".to_string()),
125                        retry_policy: None,
126                        failure_policy: None,
127                    }),
128                },
129                output_key: None,
130                retry_policy: None,
131                failure_policy: None,
132            },
133            WorkflowNodeDefinition {
134                id: "review_text".to_string(),
135                kind: WorkflowNodeKind::Transform {
136                    transform_id: "extract_content".to_string(),
137                    input_key: Some("review".to_string()),
138                },
139                output_key: Some("review_text".to_string()),
140                retry_policy: None,
141                failure_policy: None,
142            },
143            WorkflowNodeDefinition {
144                id: "review_ready".to_string(),
145                kind: WorkflowNodeKind::Decision {
146                    condition: "context.review_text != null".to_string(),
147                },
148                output_key: Some("review_ready".to_string()),
149                retry_policy: None,
150                failure_policy: None,
151            },
152            WorkflowNodeDefinition {
153                id: "merge".to_string(),
154                kind: WorkflowNodeKind::Join,
155                output_key: Some("merged".to_string()),
156                retry_policy: None,
157                failure_policy: None,
158            },
159        ],
160        edges: vec![
161            WorkflowEdgeDefinition {
162                from: "draft".to_string(),
163                to: "review".to_string(),
164                transition: WorkflowEdgeTransition::OnSuccess,
165            },
166            WorkflowEdgeDefinition {
167                from: "draft".to_string(),
168                to: "fact_check".to_string(),
169                transition: WorkflowEdgeTransition::OnSuccess,
170            },
171            WorkflowEdgeDefinition {
172                from: "review".to_string(),
173                to: "review_text".to_string(),
174                transition: WorkflowEdgeTransition::OnSuccess,
175            },
176            WorkflowEdgeDefinition {
177                from: "review_text".to_string(),
178                to: "review_ready".to_string(),
179                transition: WorkflowEdgeTransition::OnSuccess,
180            },
181            WorkflowEdgeDefinition {
182                from: "review_ready".to_string(),
183                to: "merge".to_string(),
184                transition: WorkflowEdgeTransition::Condition(
185                    "context.review_ready.matched == true".to_string(),
186                ),
187            },
188            WorkflowEdgeDefinition {
189                from: "fact_check".to_string(),
190                to: "merge".to_string(),
191                transition: WorkflowEdgeTransition::OnSuccess,
192            },
193        ],
194    };
195
196    let workspace_home = std::env::temp_dir().join(format!(
197        "enki-workflow-example-{}",
198        SystemTime::now()
199            .duration_since(UNIX_EPOCH)
200            .map_err(|err| err.to_string())?
201            .as_nanos()
202    ));
203
204    let runtime = WorkflowRuntime::builder()
205        .with_workspace_home(&workspace_home)
206        .with_task_runner(Arc::new(DemoTaskRunner))
207        .add_task(reusable_task)
208        .add_workflow(workflow)
209        .build()
210        .await?;
211
212    let response = runtime
213        .start(WorkflowRequest::new(
214            "release-note-review",
215            json!({ "topic": "runtime-managed workflows" }),
216        ))
217        .await?;
218
219    println!("Workflow: {}", response.workflow_id);
220    println!("Run: {}", response.run_id);
221    println!("Status: {:?}", response.status);
222    println!("Workspace: {}", workspace_home.display());
223    println!(
224        "Context:\n{}",
225        serde_json::to_string_pretty(&response.context.to_value()).map_err(|err| err.to_string())?
226    );
227
228    Ok(())
229}
Source

pub fn list_workflows(&self) -> Vec<&WorkflowDefinition>

Source

pub async fn list_runs(&self) -> Result<Vec<WorkflowRunState>, String>

Source

pub async fn inspect(&self, run_id: &str) -> Result<WorkflowRunState, String>

Source

pub async fn start( &self, request: WorkflowRequest, ) -> Result<WorkflowResponse, String>

Examples found in repository?
examples/workflow.rs (lines 213-216)
60async fn main() -> Result<(), String> {
61    let reusable_task = TaskDefinition {
62        id: "draft_release_note".to_string(),
63        target: TaskTarget::Capabilities(vec!["writing".to_string()]),
64        prompt: "Draft a concise release note for {{input.topic}}.".to_string(),
65        input_bindings: Default::default(),
66        input_transform: None,
67        output_transform: None,
68        output_key: Some("draft".to_string()),
69        retry_policy: None,
70        failure_policy: None,
71    };
72
73    let workflow = WorkflowDefinition {
74        id: "release-note-review".to_string(),
75        name: "Release Note Review".to_string(),
76        retry_policy: None,
77        failure_policy: Some(WorkflowFailurePolicy::ContinueBestEffort),
78        nodes: vec![
79            WorkflowNodeDefinition {
80                id: "draft".to_string(),
81                kind: WorkflowNodeKind::Task {
82                    task_id: Some("draft_release_note".to_string()),
83                    task: None,
84                },
85                output_key: None,
86                retry_policy: None,
87                failure_policy: None,
88            },
89            WorkflowNodeDefinition {
90                id: "review".to_string(),
91                kind: WorkflowNodeKind::Task {
92                    task_id: None,
93                    task: Some(TaskDefinition {
94                        id: "review_inline".to_string(),
95                        target: TaskTarget::AgentId("reviewer".to_string()),
96                        prompt:
97                            "Review the draft and suggest improvements:\n{{context.draft.content}}"
98                                .to_string(),
99                        input_bindings: Default::default(),
100                        input_transform: None,
101                        output_transform: None,
102                        output_key: Some("review".to_string()),
103                        retry_policy: None,
104                        failure_policy: None,
105                    }),
106                },
107                output_key: None,
108                retry_policy: None,
109                failure_policy: None,
110            },
111            WorkflowNodeDefinition {
112                id: "fact_check".to_string(),
113                kind: WorkflowNodeKind::Task {
114                    task_id: None,
115                    task: Some(TaskDefinition {
116                        id: "fact_check_inline".to_string(),
117                        target: TaskTarget::Capabilities(vec!["analysis".to_string()]),
118                        prompt:
119                            "Fact-check this draft for {{input.topic}}:\n{{context.draft.content}}"
120                                .to_string(),
121                        input_bindings: Default::default(),
122                        input_transform: None,
123                        output_transform: None,
124                        output_key: Some("fact_check".to_string()),
125                        retry_policy: None,
126                        failure_policy: None,
127                    }),
128                },
129                output_key: None,
130                retry_policy: None,
131                failure_policy: None,
132            },
133            WorkflowNodeDefinition {
134                id: "review_text".to_string(),
135                kind: WorkflowNodeKind::Transform {
136                    transform_id: "extract_content".to_string(),
137                    input_key: Some("review".to_string()),
138                },
139                output_key: Some("review_text".to_string()),
140                retry_policy: None,
141                failure_policy: None,
142            },
143            WorkflowNodeDefinition {
144                id: "review_ready".to_string(),
145                kind: WorkflowNodeKind::Decision {
146                    condition: "context.review_text != null".to_string(),
147                },
148                output_key: Some("review_ready".to_string()),
149                retry_policy: None,
150                failure_policy: None,
151            },
152            WorkflowNodeDefinition {
153                id: "merge".to_string(),
154                kind: WorkflowNodeKind::Join,
155                output_key: Some("merged".to_string()),
156                retry_policy: None,
157                failure_policy: None,
158            },
159        ],
160        edges: vec![
161            WorkflowEdgeDefinition {
162                from: "draft".to_string(),
163                to: "review".to_string(),
164                transition: WorkflowEdgeTransition::OnSuccess,
165            },
166            WorkflowEdgeDefinition {
167                from: "draft".to_string(),
168                to: "fact_check".to_string(),
169                transition: WorkflowEdgeTransition::OnSuccess,
170            },
171            WorkflowEdgeDefinition {
172                from: "review".to_string(),
173                to: "review_text".to_string(),
174                transition: WorkflowEdgeTransition::OnSuccess,
175            },
176            WorkflowEdgeDefinition {
177                from: "review_text".to_string(),
178                to: "review_ready".to_string(),
179                transition: WorkflowEdgeTransition::OnSuccess,
180            },
181            WorkflowEdgeDefinition {
182                from: "review_ready".to_string(),
183                to: "merge".to_string(),
184                transition: WorkflowEdgeTransition::Condition(
185                    "context.review_ready.matched == true".to_string(),
186                ),
187            },
188            WorkflowEdgeDefinition {
189                from: "fact_check".to_string(),
190                to: "merge".to_string(),
191                transition: WorkflowEdgeTransition::OnSuccess,
192            },
193        ],
194    };
195
196    let workspace_home = std::env::temp_dir().join(format!(
197        "enki-workflow-example-{}",
198        SystemTime::now()
199            .duration_since(UNIX_EPOCH)
200            .map_err(|err| err.to_string())?
201            .as_nanos()
202    ));
203
204    let runtime = WorkflowRuntime::builder()
205        .with_workspace_home(&workspace_home)
206        .with_task_runner(Arc::new(DemoTaskRunner))
207        .add_task(reusable_task)
208        .add_workflow(workflow)
209        .build()
210        .await?;
211
212    let response = runtime
213        .start(WorkflowRequest::new(
214            "release-note-review",
215            json!({ "topic": "runtime-managed workflows" }),
216        ))
217        .await?;
218
219    println!("Workflow: {}", response.workflow_id);
220    println!("Run: {}", response.run_id);
221    println!("Status: {:?}", response.status);
222    println!("Workspace: {}", workspace_home.display());
223    println!(
224        "Context:\n{}",
225        serde_json::to_string_pretty(&response.context.to_value()).map_err(|err| err.to_string())?
226    );
227
228    Ok(())
229}
Source

pub async fn resume(&self, run_id: &str) -> Result<WorkflowResponse, String>

Source

pub async fn submit_intervention( &self, run_id: &str, intervention_id: &str, response: Option<String>, ) -> Result<WorkflowRunState, String>

Source

pub async fn list_pending_interventions( &self, run_id: &str, ) -> Result<Vec<InterventionRequest>, String>

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more