Skip to main content

starweaver_runtime/agent/run_loop/
entrypoints.rs

1use starweaver_context::AgentContext;
2use starweaver_core::ConversationId;
3use starweaver_model::ModelMessage;
4
5use crate::{
6    agent::{Agent, AgentError, AgentInput, AgentResult},
7    iteration::{AgentIterResult, AgentIterationTrace},
8    stream::{AgentStreamRecord, AgentStreamResult},
9};
10
11impl Agent {
12    /// Run the agent with a user prompt.
13    ///
14    /// # Errors
15    ///
16    /// Returns an error when the model, capabilities, validation, tools, or runtime policy fails.
17    pub async fn run(&self, prompt: impl Into<AgentInput>) -> Result<AgentResult, AgentError> {
18        self.run_with_history(prompt, Vec::new()).await
19    }
20
21    /// Run the agent and collect a compact iteration trace.
22    ///
23    /// # Errors
24    ///
25    /// Returns an error when the model, capabilities, validation, tools, or runtime policy fails.
26    pub async fn run_iter(
27        &self,
28        prompt: impl Into<AgentInput>,
29    ) -> Result<AgentIterResult, AgentError> {
30        let mut events = Vec::new();
31        let result = self.run_with_stream_events(prompt, &mut events).await?;
32        let iterations = AgentIterationTrace::from_stream_records(&events);
33        Ok(AgentIterResult {
34            result,
35            iterations,
36            events,
37        })
38    }
39
40    /// Run the agent and collect typed stream events emitted during execution.
41    ///
42    /// # Errors
43    ///
44    /// Returns an error when the model, capabilities, validation, tools, or runtime policy fails.
45    pub async fn run_stream(
46        &self,
47        prompt: impl Into<AgentInput>,
48    ) -> Result<AgentStreamResult, AgentError> {
49        let mut events = Vec::new();
50        let result = self.run_with_stream_events(prompt, &mut events).await?;
51        Ok(AgentStreamResult { result, events })
52    }
53
54    /// Run the agent with prior history and collect a compact iteration trace.
55    ///
56    /// # Errors
57    ///
58    /// Returns an error when the model, capabilities, validation, tools, or runtime policy fails.
59    pub async fn run_with_history_iter(
60        &self,
61        prompt: impl Into<AgentInput>,
62        message_history: Vec<ModelMessage>,
63    ) -> Result<AgentIterResult, AgentError> {
64        let mut events = Vec::new();
65        let result = self
66            .run_with_history_and_stream_events(prompt, message_history, &mut events)
67            .await?;
68        let iterations = AgentIterationTrace::from_stream_records(&events);
69        Ok(AgentIterResult {
70            result,
71            iterations,
72            events,
73        })
74    }
75
76    /// Run the agent with an explicit typed stream event collector.
77    ///
78    /// # Errors
79    ///
80    /// Returns an error when the model, capabilities, validation, tools, or runtime policy fails.
81    pub async fn run_with_stream_events(
82        &self,
83        prompt: impl Into<AgentInput>,
84        events: &mut Vec<AgentStreamRecord>,
85    ) -> Result<AgentResult, AgentError> {
86        self.run_with_history_and_stream_events(prompt, Vec::new(), events)
87            .await
88    }
89
90    /// Run the agent with prior history and collect typed stream events.
91    ///
92    /// # Errors
93    ///
94    /// Returns an error when the model, capabilities, validation, tools, or runtime policy fails.
95    pub async fn run_with_history_and_stream_events(
96        &self,
97        prompt: impl Into<AgentInput>,
98        message_history: Vec<ModelMessage>,
99        events: &mut Vec<AgentStreamRecord>,
100    ) -> Result<AgentResult, AgentError> {
101        let mut context = self.context_from_history(message_history);
102        self.run_with_context_and_stream_events(prompt, &mut context, events)
103            .await
104    }
105
106    /// Run the agent with prior canonical message history.
107    ///
108    /// # Errors
109    ///
110    /// Returns an error when the model, capabilities, validation, tools, or runtime policy fails.
111    pub async fn run_with_history(
112        &self,
113        prompt: impl Into<AgentInput>,
114        message_history: Vec<ModelMessage>,
115    ) -> Result<AgentResult, AgentError> {
116        let mut context = self.context_from_history(message_history);
117        self.run_with_context(prompt, &mut context).await
118    }
119
120    /// Run the agent using a lifecycle-wide context and collect a compact iteration trace.
121    ///
122    /// # Errors
123    ///
124    /// Returns an error when the model, capabilities, validation, tools, or runtime policy fails.
125    pub async fn run_with_context_iter(
126        &self,
127        prompt: impl Into<AgentInput>,
128        context: &mut AgentContext,
129    ) -> Result<AgentIterResult, AgentError> {
130        let mut events = Vec::new();
131        let result = self
132            .run_with_context_and_stream_events(prompt, context, &mut events)
133            .await?;
134        let iterations = AgentIterationTrace::from_stream_records(&events);
135        Ok(AgentIterResult {
136            result,
137            iterations,
138            events,
139        })
140    }
141
142    /// Run the agent using a lifecycle-wide context and typed stream event collector.
143    ///
144    /// # Errors
145    ///
146    /// Returns an error when the model, capabilities, validation, tools, or runtime policy fails.
147    pub async fn run_with_context_and_stream_events(
148        &self,
149        prompt: impl Into<AgentInput>,
150        context: &mut AgentContext,
151        events: &mut Vec<AgentStreamRecord>,
152    ) -> Result<AgentResult, AgentError> {
153        self.run_with_context_inner(prompt, context, Some(events))
154            .await
155    }
156
157    /// Run the agent using a lifecycle-wide context.
158    ///
159    /// # Errors
160    ///
161    /// Returns an error when the model, capabilities, validation, tools, or runtime policy fails.
162    #[allow(clippy::too_many_lines)]
163    pub async fn run_with_context(
164        &self,
165        prompt: impl Into<AgentInput>,
166        context: &mut AgentContext,
167    ) -> Result<AgentResult, AgentError> {
168        self.run_with_context_inner(prompt, context, None).await
169    }
170    fn context_from_history(&self, message_history: Vec<ModelMessage>) -> AgentContext {
171        let conversation_id = latest_conversation_id(&message_history).unwrap_or_default();
172        let mut context = self.new_context();
173        context.conversation_id = conversation_id;
174        context.message_history = message_history;
175        context
176    }
177}
178
179fn latest_conversation_id(message_history: &[ModelMessage]) -> Option<ConversationId> {
180    message_history
181        .iter()
182        .rev()
183        .find_map(|message| match message {
184            ModelMessage::Request(request) => request.conversation_id.clone(),
185            ModelMessage::Response(response) => response.conversation_id.clone(),
186        })
187}