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