Skip to main content

zai_rs/agent/
mod.rs

1//! # Agent API Module
2//!
3//! Provides support for Zhipu AI's Agent API, enabling advanced AI agent
4//! interactions including creation, multi-turn conversations, tool use,
5//! and persistent state management.
6//!
7//! # Core Types
8//!
9//! - [`AgentClient`] — Main client for all agent operations
10//! - [`AgentCreateRequest`] — Request body for creating an agent
11//! - [`AgentChatRequest`] — Request body for sending a chat message
12//!
13//! # Usage
14//!
15//! ```rust,ignore
16//! use zai_rs::agent::{AgentClient, AgentCreateRequest};
17//!
18//! let client = AgentClient::new(api_key);
19//!
20//! // Create an agent
21//! let agent = client.create_agent(request).await?;
22//!
23//! // Chat with the agent
24//! let response = client.chat(&agent.id, chat_request).await?;
25//!
26//! // Retrieve conversation history
27//! let history = client.get_history(&agent.id, Some(10)).await?;
28//! ```
29
30use serde::{Deserialize, Serialize};
31
32use crate::client::http::{HttpClientConfig, http_client_with_config, parse_api_error_response};
33
34pub mod request;
35pub mod response;
36
37pub use request::*;
38pub use response::*;
39
40/// Agent API endpoint for creating and managing AI agents
41pub const AGENT_API_URL: &str = "https://open.bigmodel.cn/api/paas/v4/agents";
42
43/// Agent client for managing AI agent interactions
44///
45/// # Example
46///
47/// ```rust,ignore
48/// use zai_rs::agent::{AgentClient, AgentCreateRequest};
49///
50/// let client = AgentClient::new(api_key);
51/// let request = AgentCreateRequest::builder()
52///     .name("My Assistant")
53///     .description("A helpful assistant")
54///     .build();
55///
56/// let agent = client.create_agent(request).await?;
57/// ```
58pub struct AgentClient {
59    api_key: String,
60    base_url: String,
61    http_config: HttpClientConfig,
62    client: reqwest::Client,
63}
64
65impl AgentClient {
66    /// Create a new Agent API client
67    pub fn new(api_key: impl Into<String>) -> Self {
68        let config = HttpClientConfig::default();
69        let client = http_client_with_config(&config);
70        Self {
71            api_key: api_key.into(),
72            base_url: AGENT_API_URL.to_string(),
73            http_config: config,
74            client,
75        }
76    }
77
78    /// Create a new agent with custom base URL
79    pub fn with_base_url(mut self, base_url: impl Into<String>) -> Self {
80        self.base_url = base_url.into();
81        self
82    }
83
84    /// Set custom HTTP client configuration (timeout, retries, etc.)
85    pub fn with_http_config(mut self, config: HttpClientConfig) -> Self {
86        self.client = http_client_with_config(&config);
87        self.http_config = config;
88        self
89    }
90
91    /// Create a new AI agent
92    pub async fn create_agent(
93        &self,
94        request: AgentCreateRequest,
95    ) -> crate::ZaiResult<AgentCreateResponse> {
96        self.send_request(&self.base_url, &request).await
97    }
98
99    /// Get agent details by ID
100    pub async fn get_agent(&self, agent_id: &str) -> crate::ZaiResult<AgentDetails> {
101        let url = format!("{}/{}", self.base_url, agent_id);
102        self.send_get_request(&url).await
103    }
104
105    /// Update an existing agent
106    pub async fn update_agent(
107        &self,
108        agent_id: &str,
109        request: AgentUpdateRequest,
110    ) -> crate::ZaiResult<AgentUpdateResponse> {
111        let url = format!("{}/{}", self.base_url, agent_id);
112        self.send_request(&url, &request).await
113    }
114
115    /// Delete an agent
116    pub async fn delete_agent(&self, agent_id: &str) -> crate::ZaiResult<AgentDeleteResponse> {
117        let url = format!("{}/{}", self.base_url, agent_id);
118        let response = self
119            .client
120            .delete(&url)
121            .bearer_auth(&self.api_key)
122            .send()
123            .await?;
124
125        if response.status().is_success() {
126            Ok(response.json().await?)
127        } else {
128            let status = response.status().as_u16();
129            let body = response.text().await.unwrap_or_default();
130            Err(parse_api_error_response(status, body))
131        }
132    }
133
134    /// Send a chat message to an agent
135    pub async fn chat(
136        &self,
137        agent_id: &str,
138        request: AgentChatRequest,
139    ) -> crate::ZaiResult<AgentChatResponse> {
140        let url = format!("{}/{}/chat", self.base_url, agent_id);
141        self.send_request(&url, &request).await
142    }
143
144    /// Get conversation history
145    pub async fn get_history(
146        &self,
147        agent_id: &str,
148        limit: Option<u32>,
149    ) -> crate::ZaiResult<ConversationHistory> {
150        let mut url = format!("{}/{}/history", self.base_url, agent_id);
151        if let Some(l) = limit {
152            url.push_str(&format!("?limit={}", l));
153        }
154        self.send_get_request(&url).await
155    }
156
157    /// Internal method to send POST requests (reuses connection pool)
158    async fn send_request<T: Serialize, R: for<'de> Deserialize<'de>>(
159        &self,
160        url: &str,
161        body: &T,
162    ) -> crate::ZaiResult<R> {
163        let response = self
164            .client
165            .post(url)
166            .bearer_auth(&self.api_key)
167            .header("Content-Type", "application/json")
168            .json(body)
169            .send()
170            .await?;
171
172        if response.status().is_success() {
173            Ok(response.json().await?)
174        } else {
175            let status = response.status().as_u16();
176            let body = response.text().await.unwrap_or_default();
177            Err(parse_api_error_response(status, body))
178        }
179    }
180
181    /// Internal method to send GET requests (reuses connection pool)
182    async fn send_get_request<R: for<'de> Deserialize<'de>>(
183        &self,
184        url: &str,
185    ) -> crate::ZaiResult<R> {
186        let response = self
187            .client
188            .get(url)
189            .bearer_auth(&self.api_key)
190            .send()
191            .await?;
192
193        if response.status().is_success() {
194            Ok(response.json().await?)
195        } else {
196            let status = response.status().as_u16();
197            let body = response.text().await.unwrap_or_default();
198            Err(parse_api_error_response(status, body))
199        }
200    }
201}