Skip to main content

async_openai/assistants/
threads.rs

1use crate::{
2    config::Config,
3    error::OpenAIError,
4    types::assistants::{
5        CreateThreadAndRunRequest, CreateThreadRequest, DeleteThreadResponse, ModifyThreadRequest,
6        RunObject, ThreadObject,
7    },
8    Client, Messages, RequestOptions, Runs,
9};
10
11#[cfg(not(target_family = "wasm"))]
12use crate::types::assistants::AssistantEventStream;
13
14/// Create threads that assistants can interact with.
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 Threads<'c, C: Config> {
21    client: &'c Client<C>,
22    pub(crate) request_options: RequestOptions,
23}
24
25impl<'c, C: Config> Threads<'c, C> {
26    pub fn new(client: &'c Client<C>) -> Self {
27        Self {
28            client,
29            request_options: RequestOptions::new(),
30        }
31    }
32
33    /// Call [Messages] group API to manage message in `thread_id` thread.
34    pub fn messages(&self, thread_id: &str) -> Messages<'_, C> {
35        Messages::new(self.client, thread_id)
36    }
37
38    /// Call [Runs] group API to manage runs in `thread_id` thread.
39    pub fn runs(&self, thread_id: &str) -> Runs<'_, C> {
40        Runs::new(self.client, thread_id)
41    }
42
43    /// Create a thread and run it in one request.
44    #[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
45    pub async fn create_and_run(
46        &self,
47        request: CreateThreadAndRunRequest,
48    ) -> Result<RunObject, OpenAIError> {
49        self.client
50            .post("/threads/runs", request, &self.request_options)
51            .await
52    }
53
54    /// Create a thread and run it in one request (streaming).
55    ///
56    /// byot: You must ensure "stream: true" in serialized `request`
57    #[cfg(not(target_family = "wasm"))]
58    #[crate::byot(
59        T0 = serde::Serialize,
60        R = serde::de::DeserializeOwned,
61        stream = "true",
62        where_clause = "R: std::marker::Send + 'static + TryFrom<eventsource_stream::Event, Error = OpenAIError>"
63    )]
64    #[allow(unused_mut)]
65    pub async fn create_and_run_stream(
66        &self,
67        mut request: CreateThreadAndRunRequest,
68    ) -> Result<AssistantEventStream, OpenAIError> {
69        #[cfg(not(feature = "byot"))]
70        {
71            if request.stream.is_some() && !request.stream.unwrap() {
72                return Err(OpenAIError::InvalidArgument(
73                    "When stream is false, use Threads::create_and_run".into(),
74                ));
75            }
76
77            request.stream = Some(true);
78        }
79        Ok(self
80            .client
81            .post_stream_mapped_raw_events(
82                "/threads/runs",
83                request,
84                &self.request_options,
85                TryFrom::try_from,
86            )
87            .await)
88    }
89
90    /// Create a thread.
91    #[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
92    pub async fn create(&self, request: CreateThreadRequest) -> Result<ThreadObject, OpenAIError> {
93        self.client
94            .post("/threads", request, &self.request_options)
95            .await
96    }
97
98    /// Retrieves a thread.
99    #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
100    pub async fn retrieve(&self, thread_id: &str) -> Result<ThreadObject, OpenAIError> {
101        self.client
102            .get(&format!("/threads/{thread_id}"), &self.request_options)
103            .await
104    }
105
106    /// Modifies a thread.
107    #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
108    pub async fn update(
109        &self,
110        thread_id: &str,
111        request: ModifyThreadRequest,
112    ) -> Result<ThreadObject, OpenAIError> {
113        self.client
114            .post(
115                &format!("/threads/{thread_id}"),
116                request,
117                &self.request_options,
118            )
119            .await
120    }
121
122    /// Delete a thread.
123    #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
124    pub async fn delete(&self, thread_id: &str) -> Result<DeleteThreadResponse, OpenAIError> {
125        self.client
126            .delete(&format!("/threads/{thread_id}"), &self.request_options)
127            .await
128    }
129}