From db4c4980e76641da3da9dd6b93bcb2a992846719 Mon Sep 17 00:00:00 2001 From: Shushakov Daniil 84373458 Date: Tue, 9 Jun 2026 18:35:25 +0300 Subject: [PATCH 1/3] Add descriptions to elicitation enum options --- docs/protocol/v1/draft/schema.mdx | 5 ++- docs/protocol/v2/draft/schema.mdx | 5 ++- docs/rfds/elicitation.mdx | 66 +++++++++++++++++++++++++------ schema/v1/schema.unstable.json | 6 ++- schema/v2/schema.unstable.json | 6 ++- src/v1/elicitation.rs | 25 ++++++++++-- src/v2/conversion.rs | 14 ++++++- src/v2/elicitation.rs | 25 ++++++++++-- 8 files changed, 128 insertions(+), 24 deletions(-) diff --git a/docs/protocol/v1/draft/schema.mdx b/docs/protocol/v1/draft/schema.mdx index eb4d43dd7..1656b0ace 100644 --- a/docs/protocol/v1/draft/schema.mdx +++ b/docs/protocol/v1/draft/schema.mdx @@ -4185,7 +4185,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/d ## EnumOption -A titled enum option with a const value and human-readable title. +A titled enum option with a const value, human-readable title, and optional description. **Type:** Object @@ -4194,6 +4194,9 @@ A titled enum option with a const value and human-readable title. The constant value for this option. + + Optional description for this option value. + Human-readable title for this option. diff --git a/docs/protocol/v2/draft/schema.mdx b/docs/protocol/v2/draft/schema.mdx index 3f2db2fdc..79954ed2a 100644 --- a/docs/protocol/v2/draft/schema.mdx +++ b/docs/protocol/v2/draft/schema.mdx @@ -3784,7 +3784,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/d ## EnumOption -A titled enum option with a const value and human-readable title. +A titled enum option with a const value, human-readable title, and optional description. **Type:** Object @@ -3793,6 +3793,9 @@ A titled enum option with a const value and human-readable title. The constant value for this option. + + Optional description for this option value. + Human-readable title for this option. diff --git a/docs/rfds/elicitation.mdx b/docs/rfds/elicitation.mdx index ab69c1082..72f3d6929 100644 --- a/docs/rfds/elicitation.mdx +++ b/docs/rfds/elicitation.mdx @@ -99,12 +99,18 @@ Agents send elicitation requests when they need information from the user. This "oneOf": [ { "const": "conservative", - "title": "Conservative - Minimal changes" + "title": "Conservative - Minimal changes", + "description": "Make minimal changes and avoid broad cleanup." + }, + { + "const": "balanced", + "title": "Balanced (Recommended)", + "description": "Fix the issue and clean nearby code when it lowers risk." }, - { "const": "balanced", "title": "Balanced (Recommended)" }, { "const": "aggressive", - "title": "Aggressive - Maximum optimization" + "title": "Aggressive - Maximum optimization", + "description": "Refactor more broadly to optimize the affected area." } ], "default": "balanced" @@ -269,9 +275,21 @@ Single-select enum (with titles): "title": "Color Selection", "description": "Choose your favorite color", "oneOf": [ - { "const": "#FF0000", "title": "Red" }, - { "const": "#00FF00", "title": "Green" }, - { "const": "#0000FF", "title": "Blue" } + { + "const": "#FF0000", + "title": "Red", + "description": "High emphasis and warning-oriented." + }, + { + "const": "#00FF00", + "title": "Green", + "description": "Positive status and success-oriented." + }, + { + "const": "#0000FF", + "title": "Blue", + "description": "Neutral and informational." + } ], "default": "#FF0000" } @@ -305,9 +323,21 @@ Multi-select enum (with titles): "maxItems": 2, "items": { "anyOf": [ - { "const": "#FF0000", "title": "Red" }, - { "const": "#00FF00", "title": "Green" }, - { "const": "#0000FF", "title": "Blue" } + { + "const": "#FF0000", + "title": "Red", + "description": "High emphasis and warning-oriented." + }, + { + "const": "#00FF00", + "title": "Green", + "description": "Positive status and success-oriented." + }, + { + "const": "#0000FF", + "title": "Blue", + "description": "Neutral and informational." + } ] }, "default": ["#FF0000", "#00FF00"] @@ -368,9 +398,21 @@ The agent sends an `elicitation/create` request when it needs information from t "type": "string", "title": "Refactoring Strategy", "oneOf": [ - { "const": "conservative", "title": "Conservative" }, - { "const": "balanced", "title": "Balanced (Recommended)" }, - { "const": "aggressive", "title": "Aggressive" } + { + "const": "conservative", + "title": "Conservative", + "description": "Make minimal changes and avoid broad cleanup." + }, + { + "const": "balanced", + "title": "Balanced (Recommended)", + "description": "Fix the issue and clean nearby code when it lowers risk." + }, + { + "const": "aggressive", + "title": "Aggressive", + "description": "Refactor more broadly to optimize the affected area." + } ], "default": "balanced" } diff --git a/schema/v1/schema.unstable.json b/schema/v1/schema.unstable.json index 8a748875e..710b9d581 100644 --- a/schema/v1/schema.unstable.json +++ b/schema/v1/schema.unstable.json @@ -1509,7 +1509,7 @@ ] }, "EnumOption": { - "description": "A titled enum option with a const value and human-readable title.", + "description": "A titled enum option with a const value, human-readable title, and optional description.", "type": "object", "properties": { "const": { @@ -1519,6 +1519,10 @@ "title": { "description": "Human-readable title for this option.", "type": "string" + }, + "description": { + "description": "Optional description for this option value.", + "type": ["string", "null"] } }, "required": ["const", "title"] diff --git a/schema/v2/schema.unstable.json b/schema/v2/schema.unstable.json index a153590bc..551a1f56a 100644 --- a/schema/v2/schema.unstable.json +++ b/schema/v2/schema.unstable.json @@ -1694,7 +1694,7 @@ ] }, "EnumOption": { - "description": "A titled enum option with a const value and human-readable title.", + "description": "A titled enum option with a const value, human-readable title, and optional description.", "type": "object", "properties": { "const": { @@ -1704,6 +1704,10 @@ "title": { "description": "Human-readable title for this option.", "type": "string" + }, + "description": { + "description": "Optional description for this option value.", + "type": ["string", "null"] } }, "required": ["const", "title"] diff --git a/src/v1/elicitation.rs b/src/v1/elicitation.rs index 6ba41946a..9975dea58 100644 --- a/src/v1/elicitation.rs +++ b/src/v1/elicitation.rs @@ -60,7 +60,8 @@ pub enum ElicitationSchemaType { Object, } -/// A titled enum option with a const value and human-readable title. +/// A titled enum option with a const value, human-readable title, and optional description. +#[skip_serializing_none] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[non_exhaustive] pub struct EnumOption { @@ -69,6 +70,8 @@ pub struct EnumOption { pub value: String, /// Human-readable title for this option. pub title: String, + /// Optional description for this option value. + pub description: Option, } impl EnumOption { @@ -78,8 +81,16 @@ impl EnumOption { Self { value: value.into(), title: title.into(), + description: None, } } + + /// Optional description for this option value. + #[must_use] + pub fn description(mut self, description: impl IntoOption) -> Self { + self.description = description.into_option(); + self + } } /// Schema for string properties in an elicitation form. @@ -1763,7 +1774,7 @@ mod tests { let schema = ElicitationSchema::new().property( "country", StringPropertySchema::new().one_of(vec![ - EnumOption::new("us", "United States"), + EnumOption::new("us", "United States").description("Use US English spelling."), EnumOption::new("uk", "United Kingdom"), ]), true, @@ -1775,12 +1786,20 @@ mod tests { assert_eq!(one_of.len(), 2); assert_eq!(one_of[0]["const"], "us"); assert_eq!(one_of[0]["title"], "United States"); + assert_eq!(one_of[0]["description"], "Use US English spelling."); + assert!(one_of[1].get("description").is_none()); let roundtripped: ElicitationSchema = serde_json::from_value(json).unwrap(); if let ElicitationPropertySchema::String(s) = roundtripped.properties.get("country").unwrap() { - assert_eq!(s.one_of.as_ref().unwrap().len(), 2); + let one_of = s.one_of.as_ref().unwrap(); + assert_eq!(one_of.len(), 2); + assert_eq!( + one_of[0].description.as_deref(), + Some("Use US English spelling.") + ); + assert!(one_of[1].description.is_none()); } else { panic!("expected String variant"); } diff --git a/src/v2/conversion.rs b/src/v2/conversion.rs index f72a87921..3417269ef 100644 --- a/src/v2/conversion.rs +++ b/src/v2/conversion.rs @@ -7347,10 +7347,15 @@ impl IntoV1 for super::EnumOption { type Output = crate::v1::EnumOption; fn into_v1(self) -> Result { - let Self { value, title } = self; + let Self { + value, + title, + description, + } = self; Ok(crate::v1::EnumOption { value: value.into_v1()?, title: title.into_v1()?, + description: description.into_v1()?, }) } } @@ -7360,10 +7365,15 @@ impl IntoV2 for crate::v1::EnumOption { type Output = super::EnumOption; fn into_v2(self) -> Result { - let Self { value, title } = self; + let Self { + value, + title, + description, + } = self; Ok(super::EnumOption { value: value.into_v2()?, title: title.into_v2()?, + description: description.into_v2()?, }) } } diff --git a/src/v2/elicitation.rs b/src/v2/elicitation.rs index 69f5cd5da..0051c1347 100644 --- a/src/v2/elicitation.rs +++ b/src/v2/elicitation.rs @@ -67,7 +67,8 @@ pub enum ElicitationSchemaType { Object, } -/// A titled enum option with a const value and human-readable title. +/// A titled enum option with a const value, human-readable title, and optional description. +#[skip_serializing_none] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[non_exhaustive] pub struct EnumOption { @@ -76,6 +77,8 @@ pub struct EnumOption { pub value: String, /// Human-readable title for this option. pub title: String, + /// Optional description for this option value. + pub description: Option, } impl EnumOption { @@ -85,8 +88,16 @@ impl EnumOption { Self { value: value.into(), title: title.into(), + description: None, } } + + /// Optional description for this option value. + #[must_use] + pub fn description(mut self, description: impl IntoOption) -> Self { + self.description = description.into_option(); + self + } } /// Schema for string properties in an elicitation form. @@ -1767,7 +1778,7 @@ mod tests { let schema = ElicitationSchema::new().property( "country", StringPropertySchema::new().one_of(vec![ - EnumOption::new("us", "United States"), + EnumOption::new("us", "United States").description("Use US English spelling."), EnumOption::new("uk", "United Kingdom"), ]), true, @@ -1779,12 +1790,20 @@ mod tests { assert_eq!(one_of.len(), 2); assert_eq!(one_of[0]["const"], "us"); assert_eq!(one_of[0]["title"], "United States"); + assert_eq!(one_of[0]["description"], "Use US English spelling."); + assert!(one_of[1].get("description").is_none()); let roundtripped: ElicitationSchema = serde_json::from_value(json).unwrap(); if let ElicitationPropertySchema::String(s) = roundtripped.properties.get("country").unwrap() { - assert_eq!(s.one_of.as_ref().unwrap().len(), 2); + let one_of = s.one_of.as_ref().unwrap(); + assert_eq!(one_of.len(), 2); + assert_eq!( + one_of[0].description.as_deref(), + Some("Use US English spelling.") + ); + assert!(one_of[1].description.is_none()); } else { panic!("expected String variant"); } From 3d2f0b7cbfca7324acfbdbd61ac5fe0123570760 Mon Sep 17 00:00:00 2001 From: Ben Brandt Date: Mon, 6 Jul 2026 13:59:45 +0200 Subject: [PATCH 2/3] run generate again --- docs/protocol/v1/draft/schema.mdx | 2 +- docs/protocol/v2/draft/schema.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/protocol/v1/draft/schema.mdx b/docs/protocol/v1/draft/schema.mdx index e6470f31b..73aa43b8e 100644 --- a/docs/protocol/v1/draft/schema.mdx +++ b/docs/protocol/v1/draft/schema.mdx @@ -4440,7 +4440,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/d The constant value for this option. - + Optional description for this option value. diff --git a/docs/protocol/v2/draft/schema.mdx b/docs/protocol/v2/draft/schema.mdx index 1711c4183..5ac024050 100644 --- a/docs/protocol/v2/draft/schema.mdx +++ b/docs/protocol/v2/draft/schema.mdx @@ -4195,7 +4195,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/d The constant value for this option. - + Optional description for this option value. From 18c9aae85b1fd4b1368402166db37a92117abdb0 Mon Sep 17 00:00:00 2001 From: Ben Brandt Date: Mon, 6 Jul 2026 14:18:42 +0200 Subject: [PATCH 3/3] fix(schema): make EnumOption description lenient like sibling display fields Add the DefaultOnError / x-deserialize-default-on-error / serde(default) annotations to the new description field so a malformed value degrades to None instead of rejecting the whole elicitation request, matching every other cosmetic optional field. Also align the doc wording with sibling description fields and regenerate schemas and docs. Co-Authored-By: Claude Fable 5 --- agent-client-protocol-schema/src/v1/elicitation.rs | 7 +++++-- agent-client-protocol-schema/src/v2/elicitation.rs | 7 +++++-- docs/protocol/v1/draft/schema.mdx | 2 +- docs/protocol/v2/draft/schema.mdx | 2 +- schema/v1/schema.unstable.json | 5 +++-- schema/v2/schema.unstable.json | 5 +++-- 6 files changed, 18 insertions(+), 10 deletions(-) diff --git a/agent-client-protocol-schema/src/v1/elicitation.rs b/agent-client-protocol-schema/src/v1/elicitation.rs index b43abf29f..c169940d7 100644 --- a/agent-client-protocol-schema/src/v1/elicitation.rs +++ b/agent-client-protocol-schema/src/v1/elicitation.rs @@ -75,7 +75,10 @@ pub struct EnumOption { pub value: String, /// Human-readable title for this option. pub title: String, - /// Optional description for this option value. + /// Human-readable description. + #[serde_as(deserialize_as = "DefaultOnError")] + #[schemars(extend("x-deserialize-default-on-error" = true))] + #[serde(default)] pub description: Option, /// The _meta property is reserved by ACP to allow clients and agents to attach additional /// metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -101,7 +104,7 @@ impl EnumOption { } } - /// Optional description for this option value. + /// Human-readable description. #[must_use] pub fn description(mut self, description: impl IntoOption) -> Self { self.description = description.into_option(); diff --git a/agent-client-protocol-schema/src/v2/elicitation.rs b/agent-client-protocol-schema/src/v2/elicitation.rs index d74f5fd9b..1feb8541f 100644 --- a/agent-client-protocol-schema/src/v2/elicitation.rs +++ b/agent-client-protocol-schema/src/v2/elicitation.rs @@ -80,7 +80,10 @@ pub struct EnumOption { pub value: String, /// Human-readable title for this option. pub title: String, - /// Optional description for this option value. + /// Human-readable description. + #[serde_as(deserialize_as = "DefaultOnError")] + #[schemars(extend("x-deserialize-default-on-error" = true))] + #[serde(default)] pub description: Option, /// The _meta property is reserved by ACP to allow clients and agents to attach additional /// metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -106,7 +109,7 @@ impl EnumOption { } } - /// Optional description for this option value. + /// Human-readable description. #[must_use] pub fn description(mut self, description: impl IntoOption) -> Self { self.description = description.into_option(); diff --git a/docs/protocol/v1/draft/schema.mdx b/docs/protocol/v1/draft/schema.mdx index 73aa43b8e..3d174486a 100644 --- a/docs/protocol/v1/draft/schema.mdx +++ b/docs/protocol/v1/draft/schema.mdx @@ -4441,7 +4441,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/d The constant value for this option. - Optional description for this option value. + Human-readable description. Human-readable title for this option. diff --git a/docs/protocol/v2/draft/schema.mdx b/docs/protocol/v2/draft/schema.mdx index 5ac024050..f4e53095d 100644 --- a/docs/protocol/v2/draft/schema.mdx +++ b/docs/protocol/v2/draft/schema.mdx @@ -4196,7 +4196,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/d The constant value for this option. - Optional description for this option value. + Human-readable description. Human-readable title for this option. diff --git a/schema/v1/schema.unstable.json b/schema/v1/schema.unstable.json index f23df062c..d0d3b6964 100644 --- a/schema/v1/schema.unstable.json +++ b/schema/v1/schema.unstable.json @@ -1782,8 +1782,9 @@ "type": "string" }, "description": { - "description": "Optional description for this option value.", - "type": ["string", "null"] + "description": "Human-readable description.", + "type": ["string", "null"], + "x-deserialize-default-on-error": true }, "_meta": { "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", diff --git a/schema/v2/schema.unstable.json b/schema/v2/schema.unstable.json index c40e8f599..dca3447b7 100644 --- a/schema/v2/schema.unstable.json +++ b/schema/v2/schema.unstable.json @@ -2408,8 +2408,9 @@ "type": "string" }, "description": { - "description": "Optional description for this option value.", - "type": ["string", "null"] + "description": "Human-readable description.", + "type": ["string", "null"], + "x-deserialize-default-on-error": true }, "_meta": { "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/draft/extensibility)",