systemprompt_models/a2a/agent_card/
extension.rs1use serde::{Deserialize, Serialize};
7
8pub const ARTIFACT_RENDERING_URI: &str = "https://systemprompt.io/extensions/artifact-rendering/v1";
9
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
11#[serde(rename_all = "camelCase")]
12pub struct AgentCapabilities {
13 #[serde(skip_serializing_if = "Option::is_none")]
14 pub streaming: Option<bool>,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 pub push_notifications: Option<bool>,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub state_transition_history: Option<bool>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub extensions: Option<Vec<AgentExtension>>,
21}
22
23impl Default for AgentCapabilities {
24 fn default() -> Self {
25 Self {
26 streaming: Some(true),
27 push_notifications: Some(true),
28 state_transition_history: Some(true),
29 extensions: None,
30 }
31 }
32}
33
34impl AgentCapabilities {
35 #[must_use]
36 pub const fn normalize(mut self) -> Self {
37 if self.streaming.is_none() {
38 self.streaming = Some(true);
39 }
40 if self.push_notifications.is_none() {
41 self.push_notifications = Some(false);
42 }
43 if self.state_transition_history.is_none() {
44 self.state_transition_history = Some(true);
45 }
46 self
47 }
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
51pub struct AgentExtension {
52 pub uri: String,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub description: Option<String>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub required: Option<bool>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub params: Option<serde_json::Value>,
59}
60
61impl AgentExtension {
62 #[must_use]
63 pub fn mcp_tools_extension() -> Self {
64 Self {
65 uri: "systemprompt:mcp-tools".to_owned(),
66 description: Some("MCP tool execution capabilities".to_owned()),
67 required: Some(false),
68 params: Some(serde_json::json!({
69 "supported_protocols": ["mcp-1.0"]
70 })),
71 }
72 }
73
74 #[must_use]
75 pub fn agent_identity(agent_name: &str) -> Self {
76 Self {
77 uri: "systemprompt:agent-identity".to_owned(),
78 description: Some("systemprompt.io platform agent name".to_owned()),
79 required: Some(true),
80 params: Some(serde_json::json!({
81 "name": agent_name
82 })),
83 }
84 }
85
86 #[must_use]
87 pub fn system_instructions(system_prompt: &str) -> Self {
88 Self {
89 uri: "systemprompt:system-instructions".to_owned(),
90 description: Some("Agent system prompt and behavioral guidelines".to_owned()),
91 required: Some(true),
92 params: Some(serde_json::json!({
93 "systemPrompt": system_prompt,
94 "format": "text/plain"
95 })),
96 }
97 }
98
99 #[must_use]
100 pub fn system_instructions_opt(system_prompt: Option<&str>) -> Option<Self> {
101 system_prompt.map(Self::system_instructions)
102 }
103
104 #[must_use]
105 pub fn service_status(
106 status: &str,
107 port: Option<u16>,
108 pid: Option<u32>,
109 default: bool,
110 ) -> Self {
111 let mut params = serde_json::json!({
112 "status": status,
113 "default": default
114 });
115
116 if let Some(p) = port {
117 params["port"] = serde_json::json!(p);
118 }
119 if let Some(p) = pid {
120 params["pid"] = serde_json::json!(p);
121 }
122
123 Self {
124 uri: "systemprompt:service-status".to_owned(),
125 description: Some("Runtime service status from orchestrator".to_owned()),
126 required: Some(true),
127 params: Some(params),
128 }
129 }
130}