aether_project/
agent_config.rs1use crate::{McpSourceSpec, PromptSource};
2use aether_core::agent_spec::ToolFilter;
3use llm::ReasoningEffort;
4
5#[derive(Debug, Clone, Default, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema)]
6#[serde(rename_all = "camelCase", deny_unknown_fields)]
7#[schemars(transform = require_agent_invocation_surface_schema)]
8pub struct AgentConfig {
9 #[schemars(length(min = 1))]
10 pub name: String,
11 #[schemars(length(min = 1))]
12 pub description: String,
13 #[schemars(length(min = 1))]
14 pub model: String,
15 #[serde(default, skip_serializing_if = "Option::is_none")]
16 pub reasoning_effort: Option<ReasoningEffort>,
17 #[serde(default)]
18 pub user_invocable: bool,
19 #[serde(default)]
20 pub agent_invocable: bool,
21 #[serde(default, skip_serializing_if = "Vec::is_empty")]
22 #[schemars(length(min = 1))]
23 pub prompts: Vec<PromptSource>,
24 #[serde(default, skip_serializing_if = "Vec::is_empty")]
25 pub mcps: Vec<McpSourceSpec>,
26 #[serde(default, skip_serializing_if = "ToolFilter::is_empty")]
27 pub tools: ToolFilter,
28}
29
30fn require_agent_invocation_surface_schema(schema: &mut schemars::Schema) {
31 schema.insert(
32 "anyOf".to_string(),
33 serde_json::json!([
34 { "required": ["userInvocable"], "properties": { "userInvocable": { "const": true } } },
35 { "required": ["agentInvocable"], "properties": { "agentInvocable": { "const": true } } }
36 ]),
37 );
38}