ironflow_engine/context/steps/agent.rs
1//! Agent step for [`WorkflowContext`].
2
3use ironflow_store::models::StepKind;
4
5use crate::config::{AgentStep, StepConfig};
6use crate::context::WorkflowContext;
7use crate::error::EngineError;
8
9impl WorkflowContext {
10 /// Execute an agent step.
11 ///
12 /// With [`output::<T>()`](crate::config::AgentStepConfig::output) on the
13 /// config, the step returns the `T` the agent answered; otherwise it
14 /// returns the raw [`StepOutput`](crate::executor::StepOutput). See
15 /// [`AgentStep`].
16 ///
17 /// # Errors
18 ///
19 /// Returns [`EngineError`] if the agent invocation fails or the store
20 /// errors, and [`EngineError::Serialization`] if a typed answer does not
21 /// match its type.
22 ///
23 /// # Examples
24 ///
25 /// ```no_run
26 /// use ironflow_engine::context::WorkflowContext;
27 /// use ironflow_engine::config::AgentStepConfig;
28 /// use ironflow_engine::error::EngineError;
29 /// use schemars::JsonSchema;
30 /// use serde::Deserialize;
31 ///
32 /// #[derive(Deserialize, JsonSchema)]
33 /// struct Review {
34 /// approved: bool,
35 /// comments: Vec<String>,
36 /// }
37 ///
38 /// # async fn example(ctx: &mut WorkflowContext) -> Result<(), EngineError> {
39 /// let review = ctx
40 /// .agent(
41 /// "review",
42 /// AgentStepConfig::new("Review the code").max_turns(2).output::<Review>(),
43 /// )
44 /// .await?;
45 /// if !review.approved {
46 /// println!("{} comments", review.comments.len());
47 /// }
48 /// # Ok(())
49 /// # }
50 /// ```
51 pub async fn agent<C: AgentStep>(
52 &mut self,
53 name: &str,
54 config: C,
55 ) -> Result<C::Answer, EngineError> {
56 let output = self
57 .execute_step(
58 name,
59 StepKind::Agent,
60 StepConfig::Agent(config.into_config()),
61 )
62 .await?;
63 C::answer(output)
64 }
65}