pub struct Workflow<S: Clone + 'static> { /* private fields */ }Expand description
A validated workflow of agents. Built via Workflow::builder.
Implementations§
Source§impl<S: Clone + 'static> Workflow<S>
impl<S: Clone + 'static> Workflow<S>
Sourcepub fn builder(name: &'static str) -> WorkflowBuilder<S>
pub fn builder(name: &'static str) -> WorkflowBuilder<S>
Create a new builder with the given workflow name.
Examples found in repository?
examples/workflow.rs (line 34)
32fn main() {
33 let mut ctx = Ctx::new();
34 let wf = Workflow::builder("demo")
35 .register(AddOne)
36 .register(StopAtThree)
37 .start_at("add_one")
38 .then("stop")
39 .build()
40 .unwrap();
41
42 let final_state = Runner::new(wf).run(State { n: 0 }, &mut ctx).unwrap();
43 println!("final n={}", final_state.n);
44}More examples
examples/assistant.rs (line 119)
116fn main() {
117 let mut ctx = Ctx::new();
118
119 let wf = Workflow::builder("daily-briefing")
120 .register(FetchWeather)
121 .register(FetchCalendar)
122 .register(FetchEmail)
123 .register(Summarize)
124 .start_at("fetch_weather")
125 .then("fetch_calendar")
126 .then("fetch_email")
127 .then("summarize")
128 .build()
129 .unwrap();
130
131 let mut runner = Runner::new(wf).with_tracing();
132
133 let mut iteration = 0;
134 loop {
135 iteration += 1;
136 println!("=== Briefing #{iteration} ===\n");
137
138 match runner.run(BriefingState::new(), &mut ctx) {
139 Ok(state) => {
140 println!("{}\n", state.summary);
141 }
142 Err(e) => {
143 eprintln!("Briefing failed: {e}\n");
144 }
145 }
146
147 ctx.clear_logs();
148
149 println!("(sleeping 30s before next briefing...)\n");
150 thread::sleep(Duration::from_secs(30));
151 }
152}examples/edit_loop.rs (line 94)
90fn main() {
91 let mut ctx = Ctx::new();
92
93 let mut runner = Runner::new(
94 Workflow::builder("edit-loop")
95 .register(Writer)
96 .register(Validator)
97 .register(Fixer { retried: false })
98 .start_at("writer")
99 .then("validator")
100 .build()
101 .unwrap(),
102 );
103
104 let mut revision = 0;
105 for round in 1..=3 {
106 println!("=== Round {round} ===");
107
108 let doc = Doc {
109 text: String::new(),
110 revision,
111 };
112
113 match runner.run(doc, &mut ctx) {
114 Ok(doc) => {
115 println!(" Final text: {:?}", doc.text);
116 println!(" Revisions: {}", doc.revision);
117 revision = doc.revision;
118 }
119 Err(e) => println!(" Error: {e}"),
120 }
121
122 println!(" Log:");
123 for entry in ctx.logs() {
124 println!(" {entry}");
125 }
126 ctx.clear_logs();
127 println!();
128 }
129}examples/coder.rs (line 171)
161fn main() {
162 let tmp = std::env::temp_dir().join("agent-line-coder");
163 scaffold_project(&tmp);
164
165 let lib_path = tmp.join("src/lib.rs").display().to_string();
166 let manifest = tmp.join("Cargo.toml").display().to_string();
167
168 let mut ctx = Ctx::new();
169 ctx.set("manifest_path", &manifest);
170
171 let wf = Workflow::builder("coding-agent")
172 .register(Planner)
173 .register(Coder)
174 .register(Tester)
175 .start_at("planner")
176 .then("coder")
177 .then("tester")
178 .build()
179 .unwrap();
180
181 let mut runner = Runner::new(wf);
182
183 let result = runner.run(
184 Task {
185 description: "Add a function called `reverse_string` that reverses a string \
186 and add unit tests"
187 .into(),
188 file_path: lib_path,
189 code: String::new(),
190 test_output: String::new(),
191 attempts: 0,
192 max_attempts: 3,
193 },
194 &mut ctx,
195 );
196
197 println!("=== Result ===");
198 match result {
199 Ok(task) => {
200 println!(" Success after {} fix attempts", task.attempts);
201 println!(" Final code:\n{}", task.code);
202 }
203 Err(e) => println!(" Failed: {e}"),
204 }
205
206 println!("\n=== Log ===");
207 for entry in ctx.logs() {
208 println!(" {entry}");
209 }
210}examples/newsletter.rs (line 161)
155fn main() {
156 let mut ctx = Ctx::new();
157
158 // could populate ctx.store with some writing rules or could read in a markdown skill and pass
159 // that into the agent.
160 // Phase 1: find topics
161 let topic_wf = Workflow::builder("find-topics")
162 .register(TopicSearcher)
163 .register(TopicPicker)
164 .start_at("topic_searcher")
165 .then("topic_picker")
166 .build()
167 .unwrap();
168
169 let mut topic_runner = Runner::new(topic_wf);
170 let topics = topic_runner
171 .run(
172 TopicState {
173 query: "bluecollar engineering newsletter".into(),
174 topics: vec![],
175 selected: vec![],
176 },
177 &mut ctx,
178 )
179 .unwrap();
180
181 println!("=== Topics ===");
182 for entry in ctx.logs() {
183 println!(" {entry}");
184 }
185 ctx.clear_logs();
186 println!();
187
188 // Phase 2: write one article per topic
189 let article_wf = Workflow::builder("write-article")
190 .register(ArticleWriter)
191 .register(ArticleValidator)
192 .register(ArticleFixer)
193 .start_at("article_writer")
194 .then("article_validator")
195 .build()
196 .unwrap();
197
198 let mut article_runner = Runner::new(article_wf);
199 let mut finished_articles: Vec<String> = Vec::new();
200
201 for (i, topic) in topics.selected.iter().enumerate() {
202 println!("=== Article {} ===", i + 1);
203
204 let result = article_runner
205 .run(
206 ArticleState {
207 topic: topic.clone(),
208 draft: String::new(),
209 revision: 0,
210 },
211 &mut ctx,
212 )
213 .unwrap();
214
215 finished_articles.push(result.draft.clone());
216 println!(" Revisions: {}", result.revision);
217
218 for entry in ctx.logs() {
219 println!(" {entry}");
220 }
221 ctx.clear_logs();
222 println!();
223 }
224
225 // Phase 3: "store" the articles
226 println!("=== Stored ===");
227 for (i, article) in finished_articles.iter().enumerate() {
228 let preview: String = article.chars().take(60).collect();
229 println!(" article_{}.md: {preview}...", i + 1);
230 }
231}examples/parallel.rs (line 227)
199fn main() {
200 let topics = vec![
201 "Rust in embedded systems".to_string(),
202 "Why plumbers love side projects".to_string(),
203 "Electricians using Raspberry Pi on the job".to_string(),
204 ];
205
206 // Shared guidelines for all writers -- the author's voice and style rules
207 let guidelines = "\
208 Write in first person. \
209 Do not use emdashes. \
210 Add a touch of humor. \
211 Keep it under 300 words."
212 .to_string();
213
214 println!("=== Fan-out: {} threads ===\n", topics.len());
215
216 // Fan-out: spawn one thread per topic
217 let handles: Vec<_> = topics
218 .into_iter()
219 .enumerate()
220 .map(|(i, topic)| {
221 let guidelines = guidelines.clone();
222
223 thread::spawn(move || {
224 // Each thread gets its own Ctx and Runner -- no shared mutable state
225 let mut ctx = Ctx::new();
226
227 let wf = Workflow::builder("write-article")
228 .register(Researcher)
229 .register(Writer)
230 .register(Editor)
231 .start_at("researcher")
232 .then("writer")
233 .then("editor")
234 .build()
235 .unwrap();
236
237 let mut runner = Runner::new(wf).with_max_retries(5);
238
239 let result = runner.run(ArticleState::new(topic.clone(), guidelines), &mut ctx);
240
241 // Print the log from this thread's pipeline
242 for entry in ctx.logs() {
243 println!(" [thread {}] {}", i, entry);
244 }
245
246 result
247 })
248 })
249 .collect();
250
251 // Fan-in: join all threads, collect results
252 let mut finished = Vec::new();
253 for handle in handles {
254 match handle.join().unwrap() {
255 Ok(state) => finished.push(state),
256 Err(e) => eprintln!("thread failed: {e}"),
257 }
258 }
259
260 // Show results
261 println!("\n=== Fan-in: {} articles ===\n", finished.len());
262 for (i, article) in finished.iter().enumerate() {
263 let preview: String = article.draft.chars().take(72).collect();
264 println!(
265 " {}. {} (rev {})\n {preview}...\n",
266 i + 1,
267 article.topic,
268 article.revision
269 );
270 }
271}Auto Trait Implementations§
impl<S> Freeze for Workflow<S>
impl<S> !RefUnwindSafe for Workflow<S>
impl<S> Send for Workflow<S>
impl<S> !Sync for Workflow<S>
impl<S> Unpin for Workflow<S>
impl<S> UnsafeUnpin for Workflow<S>
impl<S> !UnwindSafe for Workflow<S>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more