Skip to main content

systemprompt_models/services/agent_config/
card.rs

1//! Agent capability and skill descriptors plus the container
2//! [`AgentCardConfig`] published as the agent's public face.
3//!
4//! Copyright (c) systemprompt.io — Business Source License 1.1.
5//! See <https://systemprompt.io> for licensing details.
6
7use serde::{Deserialize, Serialize};
8
9use crate::ai::ToolModelOverrides;
10use crate::auth::{JwtAudience, Permission};
11use crate::services::plugin::PluginComponentRef;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
14#[serde(rename_all = "camelCase")]
15pub struct AgentCardConfig {
16    pub protocol_version: String,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub name: Option<String>,
19    pub display_name: String,
20    pub description: String,
21    pub version: String,
22    #[serde(default = "default_transport")]
23    pub preferred_transport: String,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub icon_url: Option<String>,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub documentation_url: Option<String>,
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub provider: Option<AgentProviderInfo>,
30    #[serde(default)]
31    pub capabilities: CapabilitiesConfig,
32    #[serde(default = "default_input_modes")]
33    pub default_input_modes: Vec<String>,
34    #[serde(default = "default_output_modes")]
35    pub default_output_modes: Vec<String>,
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub security_schemes: Option<serde_json::Value>,
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub security: Option<Vec<serde_json::Value>>,
40    #[serde(default)]
41    pub supports_authenticated_extended_card: bool,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct AgentProviderInfo {
46    pub organization: String,
47    pub url: String,
48}
49
50#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
51#[serde(rename_all = "camelCase")]
52pub struct CapabilitiesConfig {
53    #[serde(default = "default_true")]
54    pub streaming: bool,
55    #[serde(default)]
56    pub push_notifications: bool,
57    #[serde(default = "default_true")]
58    pub state_transition_history: bool,
59}
60
61#[derive(Debug, Clone, Default, Serialize, Deserialize)]
62#[serde(rename_all = "camelCase")]
63pub struct AgentMetadataConfig {
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub system_prompt: Option<String>,
66    #[serde(default)]
67    pub mcp_servers: PluginComponentRef,
68    #[serde(default)]
69    pub skills: PluginComponentRef,
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub provider: Option<String>,
72    #[serde(skip_serializing_if = "Option::is_none")]
73    pub model: Option<String>,
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub max_output_tokens: Option<u32>,
76    #[serde(default)]
77    pub tool_model_overrides: ToolModelOverrides,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct OAuthConfig {
82    #[serde(default)]
83    pub required: bool,
84    #[serde(default)]
85    pub scopes: Vec<Permission>,
86    #[serde(default = "default_audience")]
87    pub audience: JwtAudience,
88}
89
90impl Default for CapabilitiesConfig {
91    fn default() -> Self {
92        Self {
93            streaming: true,
94            push_notifications: false,
95            state_transition_history: true,
96        }
97    }
98}
99
100impl Default for OAuthConfig {
101    fn default() -> Self {
102        Self {
103            required: false,
104            scopes: Vec::new(),
105            audience: JwtAudience::A2a,
106        }
107    }
108}
109
110pub(super) fn default_transport() -> String {
111    "JSONRPC".to_owned()
112}
113
114pub(super) fn default_input_modes() -> Vec<String> {
115    vec!["text/plain".to_owned()]
116}
117
118pub(super) fn default_output_modes() -> Vec<String> {
119    vec!["text/plain".to_owned()]
120}
121
122pub(super) const fn default_true() -> bool {
123    true
124}
125
126pub(super) const fn default_audience() -> JwtAudience {
127    JwtAudience::A2a
128}