Skip to main content

async_openai/assistants/
runs.rs

1use crate::{
2    assistants::Steps,
3    config::Config,
4    error::OpenAIError,
5    types::assistants::{
6        CreateRunRequest, ListRunsResponse, ModifyRunRequest, RunObject,
7        SubmitToolOutputsRunRequest,
8    },
9    Client, RequestOptions,
10};
11
12#[cfg(not(target_family = "wasm"))]
13use crate::types::assistants::AssistantEventStream;
14
15/// Represents an execution run on a thread.
16///
17/// Related guide: [Assistants](https://platform.openai.com/docs/assistants/overview)
18#[deprecated(
19    note = "Assistants API is deprecated and will be removed in August 2026. Use the Responses API."
20)]
21pub struct Runs<'c, C: Config> {
22    pub thread_id: String,
23    client: &'c Client<C>,
24    pub(crate) request_options: RequestOptions,
25}
26
27impl<'c, C: Config> Runs<'c, C> {
28    pub fn new(client: &'c Client<C>, thread_id: &str) -> Self {
29        Self {
30            client,
31            thread_id: thread_id.into(),
32            request_options: RequestOptions::new(),
33        }
34    }
35
36    ///  [Steps] API group
37    pub fn steps(&self, run_id: &str) -> Steps<'_, C> {
38        Steps::new(self.client, &self.thread_id, run_id)
39    }
40
41    /// Create a run.
42    #[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
43    pub async fn create(&self, request: CreateRunRequest) -> Result<RunObject, OpenAIError> {
44        self.client
45            .post(
46                &format!("/threads/{}/runs", self.thread_id),
47                request,
48                &self.request_options,
49            )
50            .await
51    }
52
53    /// Create a run.
54    ///
55    /// byot: You must ensure "stream: true" in serialized `request`
56    #[cfg(not(target_family = "wasm"))]
57    #[crate::byot(
58        T0 = serde::Serialize,
59        R = serde::de::DeserializeOwned,
60        stream = "true",
61        where_clause = "R: std::marker::Send + 'static + TryFrom<eventsource_stream::Event, Error = OpenAIError>"
62    )]
63    #[allow(unused_mut)]
64    pub async fn create_stream(
65        &self,
66        mut request: CreateRunRequest,
67    ) -> Result<AssistantEventStream, OpenAIError> {
68        #[cfg(not(feature = "byot"))]
69        {
70            if request.stream.is_some() && !request.stream.unwrap() {
71                return Err(OpenAIError::InvalidArgument(
72                    "When stream is false, use Runs::create".into(),
73                ));
74            }
75
76            request.stream = Some(true);
77        }
78
79        Ok(self
80            .client
81            .post_stream_mapped_raw_events(
82                &format!("/threads/{}/runs", self.thread_id),
83                request,
84                &self.request_options,
85                TryFrom::try_from,
86            )
87            .await)
88    }
89
90    /// Retrieves a run.
91    #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
92    pub async fn retrieve(&self, run_id: &str) -> Result<RunObject, OpenAIError> {
93        self.client
94            .get(
95                &format!("/threads/{}/runs/{run_id}", self.thread_id),
96                &self.request_options,
97            )
98            .await
99    }
100
101    /// Modifies a run.
102    #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
103    pub async fn update(
104        &self,
105        run_id: &str,
106        request: ModifyRunRequest,
107    ) -> Result<RunObject, OpenAIError> {
108        self.client
109            .post(
110                &format!("/threads/{}/runs/{run_id}", self.thread_id),
111                request,
112                &self.request_options,
113            )
114            .await
115    }
116
117    /// Returns a list of runs belonging to a thread.
118    #[crate::byot(R = serde::de::DeserializeOwned)]
119    pub async fn list(&self) -> Result<ListRunsResponse, OpenAIError> {
120        self.client
121            .get(
122                &format!("/threads/{}/runs", self.thread_id),
123                &self.request_options,
124            )
125            .await
126    }
127
128    /// When a run has the status: "requires_action" and required_action.type is submit_tool_outputs, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request.
129    #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
130    pub async fn submit_tool_outputs(
131        &self,
132        run_id: &str,
133        request: SubmitToolOutputsRunRequest,
134    ) -> Result<RunObject, OpenAIError> {
135        self.client
136            .post(
137                &format!(
138                    "/threads/{}/runs/{run_id}/submit_tool_outputs",
139                    self.thread_id
140                ),
141                request,
142                &self.request_options,
143            )
144            .await
145    }
146
147    /// byot: You must ensure "stream: true" in serialized `request`
148    #[cfg(not(target_family = "wasm"))]
149    #[crate::byot(
150        T0 = std::fmt::Display,
151        T1 = serde::Serialize,
152        R = serde::de::DeserializeOwned,
153        stream = "true",
154        where_clause = "R: std::marker::Send + 'static + TryFrom<eventsource_stream::Event, Error = OpenAIError>"
155    )]
156    #[allow(unused_mut)]
157    pub async fn submit_tool_outputs_stream(
158        &self,
159        run_id: &str,
160        mut request: SubmitToolOutputsRunRequest,
161    ) -> Result<AssistantEventStream, OpenAIError> {
162        #[cfg(not(feature = "byot"))]
163        {
164            if request.stream.is_some() && !request.stream.unwrap() {
165                return Err(OpenAIError::InvalidArgument(
166                    "When stream is false, use Runs::submit_tool_outputs".into(),
167                ));
168            }
169
170            request.stream = Some(true);
171        }
172
173        Ok(self
174            .client
175            .post_stream_mapped_raw_events(
176                &format!(
177                    "/threads/{}/runs/{run_id}/submit_tool_outputs",
178                    self.thread_id
179                ),
180                request,
181                &self.request_options,
182                TryFrom::try_from,
183            )
184            .await)
185    }
186
187    /// Cancels a run that is `in_progress`
188    #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
189    pub async fn cancel(&self, run_id: &str) -> Result<RunObject, OpenAIError> {
190        self.client
191            .post(
192                &format!("/threads/{}/runs/{run_id}/cancel", self.thread_id),
193                (),
194                &self.request_options,
195            )
196            .await
197    }
198}