aether_project/
agent_config.rs1use crate::{McpSourceSpec, PromptSource};
2use aether_core::agent_spec::ToolFilter;
3use llm::{ProviderConnectionOverrides, ReasoningEffort};
4
5#[doc = include_str!("docs/agent_config.md")]
6#[derive(Debug, Clone, Default, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema)]
7#[serde(rename_all = "camelCase", deny_unknown_fields)]
8#[schemars(transform = require_agent_invocation_surface_schema)]
9pub struct AgentConfig {
10 #[schemars(length(min = 1))]
12 pub name: String,
13 #[schemars(length(min = 1))]
15 pub description: String,
16 #[schemars(length(min = 1))]
19 pub model: String,
20 #[serde(default, skip_serializing_if = "Option::is_none")]
22 pub reasoning_effort: Option<ReasoningEffort>,
23 #[serde(default, skip_serializing_if = "Option::is_none")]
26 #[schemars(range(min = 1))]
27 pub context_window: Option<u32>,
28 #[serde(default)]
30 pub user_invocable: bool,
31 #[serde(default)]
33 pub agent_invocable: bool,
34 #[serde(default, skip_serializing_if = "ProviderConnectionOverrides::is_empty")]
36 pub providers: ProviderConnectionOverrides,
37 #[serde(default, skip_serializing_if = "Vec::is_empty")]
39 #[schemars(length(min = 1))]
40 pub prompts: Vec<PromptSource>,
41 #[serde(default, skip_serializing_if = "Vec::is_empty")]
43 pub mcps: Vec<McpSourceSpec>,
44 #[serde(default, skip_serializing_if = "ToolFilter::is_empty")]
46 pub tools: ToolFilter,
47}
48
49fn require_agent_invocation_surface_schema(schema: &mut schemars::Schema) {
50 schema.insert(
51 "anyOf".to_string(),
52 serde_json::json!([
53 { "required": ["userInvocable"], "properties": { "userInvocable": { "const": true } } },
54 { "required": ["agentInvocable"], "properties": { "agentInvocable": { "const": true } } }
55 ]),
56 );
57}