Skip to main content

uarp_sdk/generated/api/
agents.rs

1// Code generated by @uarp/codegen from spec/openapi.json. DO NOT EDIT.
2//!
3//! Agent CRUD and versioning
4
5#![allow(unused_imports, clippy::too_many_arguments)]
6
7use reqwest::Method;
8use serde::{Deserialize, Serialize};
9use futures_core::Stream;
10
11use crate::client::{Client, Request, NO_BODY, NO_QUERY};
12use crate::error::Result;
13use crate::generated::models;
14use crate::multipart::{field_text, FilePart};
15use crate::pagination::CursorGuard;
16use crate::util::encode_path;
17
18/// Query and header parameters for `getAgentActivityStats`.
19#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
20pub struct GetAgentActivityStatsParams {
21    #[serde(default, skip_serializing_if = "Option::is_none")]
22    pub days: Option<i64>,
23}
24
25/// Query and header parameters for `getAgentSystemCard`.
26#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
27pub struct GetAgentSystemCardParams {
28    /// Output format (default: json)
29    #[serde(default, skip_serializing_if = "Option::is_none")]
30    pub format: Option<models::GetAgentSystemCardFormat>,
31}
32
33/// Query and header parameters for `getAgentVersionDiff`.
34#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
35pub struct GetAgentVersionDiffParams {
36    /// Version number to compare against (defaults to versionNum-1)
37    #[serde(default, skip_serializing_if = "Option::is_none")]
38    pub compare_to: Option<i64>,
39}
40
41/// Query and header parameters for `listAgents`.
42#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
43pub struct ListAgentsParams {
44    /// Filter by workspace
45    #[serde(default, skip_serializing_if = "Option::is_none")]
46    pub workspace_id: Option<String>,
47    #[serde(default, skip_serializing_if = "Option::is_none")]
48    pub limit: Option<i64>,
49    /// Opaque pagination cursor returned by previous page response. Use `has_more` to detect if
50    /// more pages exist.
51    #[serde(default, skip_serializing_if = "Option::is_none")]
52    pub cursor: Option<String>,
53    /// Include bridge agents whose Snaga CLI is not currently `serve`-ing. By default offline
54    /// ghosts are hidden from main pickers.
55    #[serde(default, skip_serializing_if = "Option::is_none")]
56    pub include_offline: Option<bool>,
57}
58
59/// Query and header parameters for `listAgentMail`.
60#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
61pub struct ListAgentMailParams {
62    /// Restrict to one thread — a cheaper scan than filtering after the fact.
63    #[serde(default, skip_serializing_if = "Option::is_none")]
64    pub thread_id: Option<String>,
65    /// Messages to OR from this agent.
66    #[serde(default, skip_serializing_if = "Option::is_none")]
67    pub agent_id: Option<String>,
68    #[serde(default, skip_serializing_if = "Option::is_none")]
69    pub limit: Option<i64>,
70}
71
72/// Agent CRUD and versioning
73#[derive(Debug, Clone)]
74pub struct AgentsApi {
75    pub(crate) client: Client,
76}
77
78impl Client {
79    /// Agent CRUD and versioning
80    pub fn agents(&self) -> AgentsApi {
81        AgentsApi { client: self.clone() }
82    }
83}
84
85impl AgentsApi {
86    /// Activate agent
87    ///
88    /// `POST /api/v1/agents/{agentId}/activate`
89    ///
90    /// Required scopes: `agents:write`.
91    pub async fn activate_agent(&self, agent_id: &str) -> Result<models::Agent> {
92        self.client
93            .request_json(Request {
94                method: Method::POST,
95                path: format!("/api/v1/agents/{}/activate", encode_path(agent_id)),
96                query: NO_QUERY,
97                body: NO_BODY,
98                headers: Vec::new(),
99                idempotent: true,
100            })
101            .await
102    }
103
104    /// Create an agent
105    ///
106    /// `POST /api/v1/agents`
107    ///
108    /// Required scopes: `agents:write`.
109    pub async fn create(&self, body: &models::CreateAgentRequest) -> Result<models::Agent> {
110        self.client
111            .request_json(Request {
112                method: Method::POST,
113                path: "/api/v1/agents".to_string(),
114                query: NO_QUERY,
115                body: Some(body),
116                headers: Vec::new(),
117                idempotent: true,
118            })
119            .await
120    }
121
122    /// Pin a message
123    ///
124    /// Idempotent on `message_id`: pinning a message already pinned returns the existing record
125    /// with 200 and changes nothing; a new pin is 201. `content` is stored as sent (≤10 000 chars).
126    /// Unknown fields are dropped.
127    ///
128    /// `POST /api/v1/agents/{agentId}/bookmarks`
129    ///
130    /// Required scopes: `agents:write`.
131    pub async fn create_agent_bookmark(&self, agent_id: &str, body: &models::CreateAgentBookmarkRequest) -> Result<models::AgentBookmark> {
132        self.client
133            .request_json(Request {
134                method: Method::POST,
135                path: format!("/api/v1/agents/{}/bookmarks", encode_path(agent_id)),
136                query: NO_QUERY,
137                body: Some(body),
138                headers: Vec::new(),
139                idempotent: true,
140            })
141            .await
142    }
143
144    /// Create or update FRIA report
145    ///
146    /// `POST /api/v1/agents/{agentId}/fria`
147    ///
148    /// Required scopes: `agents:write`.
149    pub async fn create_agent_fria(&self, agent_id: &str, body: &models::CreateAgentFriaRequest) -> Result<models::FriaReport> {
150        self.client
151            .request_json(Request {
152                method: Method::POST,
153                path: format!("/api/v1/agents/{}/fria", encode_path(agent_id)),
154                query: NO_QUERY,
155                body: Some(body),
156                headers: Vec::new(),
157                idempotent: true,
158            })
159            .await
160    }
161
162    /// Create a version snapshot of an agent
163    ///
164    /// `POST /api/v1/agents/{agentId}/versions`
165    ///
166    /// Required scopes: `agents:write`.
167    pub async fn create_agent_version(&self, agent_id: &str, body: &models::CreateAgentVersionRequest) -> Result<models::AgentVersion> {
168        self.client
169            .request_json(Request {
170                method: Method::POST,
171                path: format!("/api/v1/agents/{}/versions", encode_path(agent_id)),
172                query: NO_QUERY,
173                body: Some(body),
174                headers: Vec::new(),
175                idempotent: true,
176            })
177            .await
178    }
179
180    /// Delete an agent
181    ///
182    /// `DELETE /api/v1/agents/{agentId}`
183    ///
184    /// Required scopes: `agents:write`.
185    pub async fn delete(&self, agent_id: &str) -> Result<serde_json::Value> {
186        self.client
187            .request_json(Request {
188                method: Method::DELETE,
189                path: format!("/api/v1/agents/{}", encode_path(agent_id)),
190                query: NO_QUERY,
191                body: NO_BODY,
192                headers: Vec::new(),
193                idempotent: true,
194            })
195            .await
196    }
197
198    /// Unpin one message
199    ///
200    /// `DELETE /api/v1/agents/{agentId}/bookmarks/{messageId}`
201    ///
202    /// Required scopes: `agents:write`.
203    pub async fn delete_agent_bookmark(&self, agent_id: &str, message_id: &str) -> Result<models::DeleteAgentBookmarkResponse> {
204        self.client
205            .request_json(Request {
206                method: Method::DELETE,
207                path: format!("/api/v1/agents/{}/bookmarks/{}", encode_path(agent_id), encode_path(message_id)),
208                query: NO_QUERY,
209                body: NO_BODY,
210                headers: Vec::new(),
211                idempotent: true,
212            })
213            .await
214    }
215
216    /// Delete agent identity
217    ///
218    /// `DELETE /api/v1/agents/{agentId}/identity`
219    ///
220    /// Required scopes: `agents:write`.
221    pub async fn delete_agent_identity(&self, agent_id: &str) -> Result<models::DeleteAgentIdentityResponse> {
222        self.client
223            .request_json(Request {
224                method: Method::DELETE,
225                path: format!("/api/v1/agents/{}/identity", encode_path(agent_id)),
226                query: NO_QUERY,
227                body: NO_BODY,
228                headers: Vec::new(),
229                idempotent: true,
230            })
231            .await
232    }
233
234    /// Unpin every message of an agent
235    ///
236    /// `DELETE /api/v1/agents/{agentId}/bookmarks`
237    ///
238    /// Required scopes: `agents:write`.
239    pub async fn delete_all_agent_bookmarks(&self, agent_id: &str) -> Result<models::DeleteAllAgentBookmarksResponse> {
240        self.client
241            .request_json(Request {
242                method: Method::DELETE,
243                path: format!("/api/v1/agents/{}/bookmarks", encode_path(agent_id)),
244                query: NO_QUERY,
245                body: NO_BODY,
246                headers: Vec::new(),
247                idempotent: true,
248            })
249            .await
250    }
251
252    /// Get an agent
253    ///
254    /// `GET /api/v1/agents/{agentId}`
255    ///
256    /// Required scopes: `agents:read`.
257    pub async fn get(&self, agent_id: &str) -> Result<models::Agent> {
258        self.client
259            .request_json(Request {
260                method: Method::GET,
261                path: format!("/api/v1/agents/{}", encode_path(agent_id)),
262                query: NO_QUERY,
263                body: NO_BODY,
264                headers: Vec::new(),
265                idempotent: false,
266            })
267            .await
268    }
269
270    /// Get agent activity stats
271    ///
272    /// `GET /api/v1/agents/{agentId}/activity-stats`
273    ///
274    /// Required scopes: `agents:read`.
275    pub async fn get_agent_activity_stats(&self, agent_id: &str, params: &GetAgentActivityStatsParams) -> Result<models::GetAgentActivityStatsResponse> {
276        self.client
277            .request_json(Request {
278                method: Method::GET,
279                path: format!("/api/v1/agents/{}/activity-stats", encode_path(agent_id)),
280                query: Some(params),
281                body: NO_BODY,
282                headers: Vec::new(),
283                idempotent: false,
284            })
285            .await
286    }
287
288    /// Get agent capability manifest
289    ///
290    /// `GET /api/v1/agents/{agentId}/capabilities`
291    ///
292    /// Required scopes: `agents:read`.
293    pub async fn get_agent_capabilities(&self, agent_id: &str) -> Result<models::AgentCapabilities> {
294        self.client
295            .request_json(Request {
296                method: Method::GET,
297                path: format!("/api/v1/agents/{}/capabilities", encode_path(agent_id)),
298                query: NO_QUERY,
299                body: NO_BODY,
300                headers: Vec::new(),
301                idempotent: false,
302            })
303            .await
304    }
305
306    /// Get Fundamental Rights Impact Assessment
307    ///
308    /// `GET /api/v1/agents/{agentId}/fria`
309    ///
310    /// Required scopes: `agents:read`.
311    pub async fn get_agent_fria(&self, agent_id: &str) -> Result<models::FriaReport> {
312        self.client
313            .request_json(Request {
314                method: Method::GET,
315                path: format!("/api/v1/agents/{}/fria", encode_path(agent_id)),
316                query: NO_QUERY,
317                body: NO_BODY,
318                headers: Vec::new(),
319                idempotent: false,
320            })
321            .await
322    }
323
324    /// Get agent identity (public key)
325    ///
326    /// `GET /api/v1/agents/{agentId}/identity`
327    ///
328    /// Required scopes: `agents:read`.
329    pub async fn get_agent_identity(&self, agent_id: &str) -> Result<models::GetAgentIdentityResponse> {
330        self.client
331            .request_json(Request {
332                method: Method::GET,
333                path: format!("/api/v1/agents/{}/identity", encode_path(agent_id)),
334                query: NO_QUERY,
335                body: NO_BODY,
336                headers: Vec::new(),
337                idempotent: false,
338            })
339            .await
340    }
341
342    /// Read the EU AI Act risk classification
343    ///
344    /// `GET /api/v1/agents/{agentId}/risk-classification`
345    ///
346    /// Required scopes: `agents:read`.
347    pub async fn get_agent_risk_classification(&self, agent_id: &str) -> Result<models::RiskClassification> {
348        self.client
349            .request_json(Request {
350                method: Method::GET,
351                path: format!("/api/v1/agents/{}/risk-classification", encode_path(agent_id)),
352                query: NO_QUERY,
353                body: NO_BODY,
354                headers: Vec::new(),
355                idempotent: false,
356            })
357            .await
358    }
359
360    /// Tool → output-view catalog
361    ///
362    /// What the builder needs to render a tool result: for each tool the agent can actually call,
363    /// the SPEC that owns it and the view to render its output with.
364    ///
365    /// Only tools the agent is entitled to are listed — the same filter the runtime applies — so
366    /// the UI cannot offer a view for a tool that will never fire. A stored view whose JSON will
367    /// not parse is skipped, not fatal: one broken view must not take the catalog down.
368    ///
369    /// `GET /api/v1/agents/{agentId}/spec-catalog`
370    ///
371    /// Required scopes: `agents:read`.
372    pub async fn get_agent_spec_catalog(&self, agent_id: &str) -> Result<models::SpecToolCatalog> {
373        self.client
374            .request_json(Request {
375                method: Method::GET,
376                path: format!("/api/v1/agents/{}/spec-catalog", encode_path(agent_id)),
377                query: NO_QUERY,
378                body: NO_BODY,
379                headers: Vec::new(),
380                idempotent: false,
381            })
382            .await
383    }
384
385    /// Get EU AI Act Annex IV system card
386    ///
387    /// `GET /api/v1/agents/{agentId}/system-card`
388    ///
389    /// Required scopes: `agents:read`.
390    pub async fn get_agent_system_card(&self, agent_id: &str, params: &GetAgentSystemCardParams) -> Result<models::AiSystemCard> {
391        self.client
392            .request_json(Request {
393                method: Method::GET,
394                path: format!("/api/v1/agents/{}/system-card", encode_path(agent_id)),
395                query: Some(params),
396                body: NO_BODY,
397                headers: Vec::new(),
398                idempotent: false,
399            })
400            .await
401    }
402
403    /// Get traffic split configuration
404    ///
405    /// `GET /api/v1/agents/{agentId}/traffic`
406    ///
407    /// Required scopes: `agents:read`.
408    pub async fn get_agent_traffic(&self, agent_id: &str) -> Result<models::GetAgentTrafficResponse> {
409        self.client
410            .request_json(Request {
411                method: Method::GET,
412                path: format!("/api/v1/agents/{}/traffic", encode_path(agent_id)),
413                query: NO_QUERY,
414                body: NO_BODY,
415                headers: Vec::new(),
416                idempotent: false,
417            })
418            .await
419    }
420
421    /// Diff between two agent versions
422    ///
423    /// `GET /api/v1/agents/{agentId}/versions/{versionNum}/diff`
424    ///
425    /// Required scopes: `agents:read`.
426    pub async fn get_agent_version_diff(&self, agent_id: &str, version_num: i64, params: &GetAgentVersionDiffParams) -> Result<models::GetAgentVersionDiffResponse> {
427        self.client
428            .request_json(Request {
429                method: Method::GET,
430                path: format!("/api/v1/agents/{}/versions/{}/diff", encode_path(agent_id), encode_path(&version_num.to_string())),
431                query: Some(params),
432                body: NO_BODY,
433                headers: Vec::new(),
434                idempotent: false,
435            })
436            .await
437    }
438
439    /// List all agents
440    ///
441    /// `GET /api/v1/agents`
442    ///
443    /// Required scopes: `agents:read`.
444    pub async fn list(&self, params: &ListAgentsParams) -> Result<models::ListAgentsResponse> {
445        self.client
446            .request_json(Request {
447                method: Method::GET,
448                path: "/api/v1/agents".to_string(),
449                query: Some(params),
450                body: NO_BODY,
451                headers: Vec::new(),
452                idempotent: false,
453            })
454            .await
455    }
456
457    /// Stream every item returned by `listAgents`, following the `cursor` cursor until the server
458    /// reports no further pages.
459    pub fn list_all<'a>(&'a self, params: &'a ListAgentsParams) -> impl Stream<Item = Result<models::Agent>> + 'a {
460        async_stream::try_stream! {
461            let mut guard = CursorGuard::new();
462            let mut cursor = params.cursor.clone();
463            loop {
464                let mut page_params = params.clone();
465                page_params.cursor = cursor.clone();
466                let page = self.list(&page_params).await?;
467                let items = page.items;
468                let was_empty = items.is_empty();
469                for item in items {
470                    yield item;
471                }
472                match guard.advance(page.cursor, Some(page.has_more), was_empty) {
473                    Some(next) => cursor = Some(next),
474                    None => break,
475                }
476            }
477        }
478    }
479
480    /// Pinned messages of an agent
481    ///
482    /// Up to 1000, unordered. `{"items":\[\]}` on an agent with none (measured 2026-09-10).
483    ///
484    /// `GET /api/v1/agents/{agentId}/bookmarks`
485    ///
486    /// Required scopes: `agents:read`.
487    pub async fn list_agent_bookmarks(&self, agent_id: &str) -> Result<models::ListAgentBookmarksResponse> {
488        self.client
489            .request_json(Request {
490                method: Method::GET,
491                path: format!("/api/v1/agents/{}/bookmarks", encode_path(agent_id)),
492                query: NO_QUERY,
493                body: NO_BODY,
494                headers: Vec::new(),
495                idempotent: false,
496            })
497            .await
498    }
499
500    /// Messages between agents
501    ///
502    /// Newest first. `agent_id` matches a message in EITHER direction — sent or received — which is
503    /// what an inbox view of one agent means.
504    ///
505    /// `total_scanned` is how many messages the scan looked at before `limit` was applied, so a
506    /// client can tell a short page from an exhausted one.
507    ///
508    /// `GET /api/v1/agent-mail`
509    ///
510    /// Required scopes: `agents:read`.
511    pub async fn list_agent_mail(&self, params: &ListAgentMailParams) -> Result<models::ListAgentMailResponse> {
512        self.client
513            .request_json(Request {
514                method: Method::GET,
515                path: "/api/v1/agent-mail".to_string(),
516                query: Some(params),
517                body: NO_BODY,
518                headers: Vec::new(),
519                idempotent: false,
520            })
521            .await
522    }
523
524    /// List version snapshots for an agent
525    ///
526    /// Returns the ordered version history for an agent. Lazily creates v1 from the current config
527    /// if no versions exist yet.
528    ///
529    /// `GET /api/v1/agents/{agentId}/versions`
530    ///
531    /// Required scopes: `agents:read`.
532    pub async fn list_agent_versions(&self, agent_id: &str) -> Result<models::ListAgentVersionsResponse> {
533        self.client
534            .request_json(Request {
535                method: Method::GET,
536                path: format!("/api/v1/agents/{}/versions", encode_path(agent_id)),
537                query: NO_QUERY,
538                body: NO_BODY,
539                headers: Vec::new(),
540                idempotent: false,
541            })
542            .await
543    }
544
545    /// Partial update agent
546    ///
547    /// `PATCH /api/v1/agents/{agentId}`
548    ///
549    /// Required scopes: `agents:write`.
550    pub async fn patch(&self, agent_id: &str, body: &serde_json::Map<String, serde_json::Value>) -> Result<models::Agent> {
551        self.client
552            .request_json(Request {
553                method: Method::PATCH,
554                path: format!("/api/v1/agents/{}", encode_path(agent_id)),
555                query: NO_QUERY,
556                body: Some(body),
557                headers: Vec::new(),
558                idempotent: true,
559            })
560            .await
561    }
562
563    /// Clear an agent's memory and conversation history
564    ///
565    /// Purges the agent's memory store and every session it owns — with their runs, events and
566    /// todos — plus any session-less runs. The agent RECORD is untouched: prompts, model, tools,
567    /// specs, workspaces and marketplace listings all survive. The same purge the super-agent's
568    /// cross-tenant `manageAgent("reset")` hook calls, deliberately shared rather than copied.
569    ///
570    /// Undeclared until 2026-08-31 while the console shipped a button for it — a route can be
571    /// missing from the contract and still be in people's hands. The two symptoms differ by client:
572    /// a hand-written client BUILDS a workaround (the web calls it with a direct POST, past the
573    /// SDK), while a generated one simply has no method and nobody notices. That makes the SDK side
574    /// the quieter of the two — there is not even a crutch to show someone came looking.
575    ///
576    /// `POST /api/v1/agents/{agentId}/reset`
577    ///
578    /// Required scopes: `agents:write`.
579    pub async fn reset_agent(&self, agent_id: &str) -> Result<models::ResetAgentResponse> {
580        self.client
581            .request_json(Request {
582                method: Method::POST,
583                path: format!("/api/v1/agents/{}/reset", encode_path(agent_id)),
584                query: NO_QUERY,
585                body: NO_BODY,
586                headers: Vec::new(),
587                idempotent: true,
588            })
589            .await
590    }
591
592    /// Rollback an agent to a previous version
593    ///
594    /// `POST /api/v1/agents/{agentId}/rollback`
595    ///
596    /// Required scopes: `agents:write`.
597    pub async fn rollback_agent(&self, agent_id: &str, body: &models::RollbackAgentRequest) -> Result<models::AgentVersion> {
598        self.client
599            .request_json(Request {
600                method: Method::POST,
601                path: format!("/api/v1/agents/{}/rollback", encode_path(agent_id)),
602                query: NO_QUERY,
603                body: Some(body),
604                headers: Vec::new(),
605                idempotent: true,
606            })
607            .await
608    }
609
610    /// Rotate agent identity
611    ///
612    /// `POST /api/v1/agents/{agentId}/identity/rotate`
613    ///
614    /// Required scopes: `agents:write`.
615    pub async fn rotate_agent_identity(&self, agent_id: &str) -> Result<models::RotateAgentIdentityResponse> {
616        self.client
617            .request_json(Request {
618                method: Method::POST,
619                path: format!("/api/v1/agents/{}/identity/rotate", encode_path(agent_id)),
620                query: NO_QUERY,
621                body: NO_BODY,
622                headers: Vec::new(),
623                idempotent: true,
624            })
625            .await
626    }
627
628    /// Set agent capabilities
629    ///
630    /// `PUT /api/v1/agents/{agentId}/capabilities`
631    ///
632    /// Required scopes: `agents:write`.
633    pub async fn set_agent_capabilities(&self, agent_id: &str, body: &serde_json::Map<String, serde_json::Value>) -> Result<models::SetAgentCapabilitiesResponse> {
634        self.client
635            .request_json(Request {
636                method: Method::PUT,
637                path: format!("/api/v1/agents/{}/capabilities", encode_path(agent_id)),
638                query: NO_QUERY,
639                body: Some(body),
640                headers: Vec::new(),
641                idempotent: true,
642            })
643            .await
644    }
645
646    /// Set traffic split configuration
647    ///
648    /// `PUT /api/v1/agents/{agentId}/traffic`
649    ///
650    /// Required scopes: `agents:write`.
651    pub async fn set_agent_traffic(&self, agent_id: &str, body: &models::SetAgentTrafficRequest) -> Result<models::SetAgentTrafficResponse> {
652        self.client
653            .request_json(Request {
654                method: Method::PUT,
655                path: format!("/api/v1/agents/{}/traffic", encode_path(agent_id)),
656                query: NO_QUERY,
657                body: Some(body),
658                headers: Vec::new(),
659                idempotent: true,
660            })
661            .await
662    }
663
664    /// Suspend agent
665    ///
666    /// `POST /api/v1/agents/{agentId}/suspend`
667    ///
668    /// Required scopes: `agents:write`.
669    pub async fn suspend_agent(&self, agent_id: &str, body: &models::SuspendAgentRequest) -> Result<models::Agent> {
670        self.client
671            .request_json(Request {
672                method: Method::POST,
673                path: format!("/api/v1/agents/{}/suspend", encode_path(agent_id)),
674                query: NO_QUERY,
675                body: Some(body),
676                headers: Vec::new(),
677                idempotent: true,
678            })
679            .await
680    }
681
682    /// Terminate/delete agent
683    ///
684    /// `POST /api/v1/agents/{agentId}/terminate`
685    ///
686    /// Required scopes: `agents:write`.
687    pub async fn terminate_agent(&self, agent_id: &str) -> Result<models::TerminateAgentResponse> {
688        self.client
689            .request_json(Request {
690                method: Method::POST,
691                path: format!("/api/v1/agents/{}/terminate", encode_path(agent_id)),
692                query: NO_QUERY,
693                body: NO_BODY,
694                headers: Vec::new(),
695                idempotent: true,
696            })
697            .await
698    }
699
700    /// Update an agent
701    ///
702    /// `PUT /api/v1/agents/{agentId}`
703    ///
704    /// Required scopes: `agents:write`.
705    pub async fn update(&self, agent_id: &str, body: &models::AgentUpdate) -> Result<models::Agent> {
706        self.client
707            .request_json(Request {
708                method: Method::PUT,
709                path: format!("/api/v1/agents/{}", encode_path(agent_id)),
710                query: NO_QUERY,
711                body: Some(body),
712                headers: Vec::new(),
713                idempotent: true,
714            })
715            .await
716    }
717
718    /// Update EU AI Act risk classification (admin only)
719    ///
720    /// `PATCH /api/v1/agents/{agentId}/risk-classification`
721    ///
722    /// Required scopes: `agents:write`.
723    pub async fn update_agent_risk_classification(&self, agent_id: &str, body: &models::RiskClassificationUpdate) -> Result<models::Agent> {
724        self.client
725            .request_json(Request {
726                method: Method::PATCH,
727                path: format!("/api/v1/agents/{}/risk-classification", encode_path(agent_id)),
728                query: NO_QUERY,
729                body: Some(body),
730                headers: Vec::new(),
731                idempotent: true,
732            })
733            .await
734    }
735
736    /// Set one per-tool trust override
737    ///
738    /// Upserts a single entry: sending the same `tool_name` twice replaces its `trust_level` rather
739    /// than adding a second row. The response is the agent's FULL override list after the write, so
740    /// a client can render the table without a second call.
741    ///
742    /// WRITE SEMANTICS: merges. Read from the handler, not from the body shape: it loads the agent,
743    /// drops any existing entry with this `tool_name`, appends the new one and leaves every other
744    /// override untouched. So this call cannot clear the list, and cannot set two entries at once.
745    ///
746    /// The write is a compare-and-set against the agent record, so a concurrent `PUT
747    /// /agents/{agentId}` cannot clobber the override with a stale snapshot — a lost race answers
748    /// 409 and the caller reloads.
749    ///
750    /// `PATCH /api/v1/agents/{agentId}/autonomy/tool-override`
751    ///
752    /// Required scopes: `agents:write`.
753    pub async fn upsert_agent_tool_override(&self, agent_id: &str, body: &models::AgentToolOverrideUpdate) -> Result<models::UpsertAgentToolOverrideResponse> {
754        self.client
755            .request_json(Request {
756                method: Method::PATCH,
757                path: format!("/api/v1/agents/{}/autonomy/tool-override", encode_path(agent_id)),
758                query: NO_QUERY,
759                body: Some(body),
760                headers: Vec::new(),
761                idempotent: true,
762            })
763            .await
764    }
765}