Skip to main content

ag_ui/
input.rs

1//! The request body an agent receives to start or resume a run.
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6use crate::context::Context;
7use crate::ids::{RunId, ThreadId};
8use crate::message::Message;
9use crate::outcome::ResumeEntry;
10use crate::tool::Tool;
11
12/// Everything an agent needs for one run.
13///
14/// This is the body of the AG-UI run request, and it is also embedded verbatim
15/// in [`RunStartedEvent::input`](crate::event::RunStartedEvent::input) so a
16/// recorded stream can be replayed without the original request.
17#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
18#[serde(rename_all = "camelCase")]
19#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
20#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
21pub struct RunAgentInput {
22    /// The conversation this run belongs to.
23    pub thread_id: ThreadId,
24    /// This run's id, echoed on every lifecycle event.
25    pub run_id: RunId,
26    /// The run that spawned this one, for nested / delegated agents.
27    #[serde(default, skip_serializing_if = "Option::is_none")]
28    pub parent_run_id: Option<RunId>,
29    /// Shared state, mutated by the agent through `STATE_SNAPSHOT` and
30    /// `STATE_DELTA`. Free-form JSON, opaque to the protocol.
31    #[serde(default)]
32    pub state: Value,
33    /// Conversation history, oldest first.
34    pub messages: Vec<Message>,
35    /// Tools the client is offering for this run.
36    pub tools: Vec<Tool>,
37    /// Ambient context entries.
38    pub context: Vec<Context>,
39    /// Arbitrary passthrough properties, opaque to the protocol.
40    #[serde(default)]
41    pub forwarded_props: Value,
42    /// Answers to the interrupts a previous run paused on. Present only when
43    /// resuming — see [`crate::outcome`].
44    #[serde(default, skip_serializing_if = "Option::is_none")]
45    pub resume: Option<Vec<ResumeEntry>>,
46}
47
48impl RunAgentInput {
49    /// Builds an input with only the two required identifiers set.
50    pub fn new(thread_id: impl Into<ThreadId>, run_id: impl Into<RunId>) -> Self {
51        Self {
52            thread_id: thread_id.into(),
53            run_id: run_id.into(),
54            ..Default::default()
55        }
56    }
57
58    /// Whether this request resumes a paused run.
59    pub fn is_resume(&self) -> bool {
60        self.resume.as_ref().is_some_and(|r| !r.is_empty())
61    }
62}