use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentSchema {
#[serde(rename = "type")]
pub agent_type: AgentType,
#[serde(default)]
pub model: Option<String>,
#[serde(default)]
pub instruction: String,
#[serde(default)]
pub tools: Vec<String>,
#[serde(default)]
pub sub_agents: Vec<String>,
#[serde(default)]
pub position: Position,
#[serde(default)]
pub max_iterations: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub temperature: Option<f32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub top_p: Option<f32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub top_k: Option<i32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_output_tokens: Option<i32>,
#[serde(default)]
pub routes: Vec<Route>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tool_timeout_secs: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_llm_iterations: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tool_retry_budget: Option<u8>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub circuit_breaker_threshold: Option<u8>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub tools_requiring_confirmation: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tool_execution_strategy: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extended_thinking: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub thinking_budget_tokens: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reasoning_effort: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub prompt_caching: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub auto_skills: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Route {
pub condition: String,
pub target: String,
}
impl AgentSchema {
pub fn llm(model: impl Into<String>) -> Self {
Self {
agent_type: AgentType::Llm,
model: Some(model.into()),
instruction: String::new(),
tools: Vec::new(),
sub_agents: Vec::new(),
position: Position::default(),
max_iterations: None,
temperature: None,
top_p: None,
top_k: None,
max_output_tokens: None,
routes: Vec::new(),
tool_timeout_secs: None,
max_llm_iterations: None,
tool_retry_budget: None,
circuit_breaker_threshold: None,
tools_requiring_confirmation: Vec::new(),
tool_execution_strategy: None,
extended_thinking: None,
thinking_budget_tokens: None,
reasoning_effort: None,
prompt_caching: None,
auto_skills: None,
}
}
pub fn with_instruction(mut self, instruction: impl Into<String>) -> Self {
self.instruction = instruction.into();
self
}
pub fn with_tools(mut self, tools: Vec<String>) -> Self {
self.tools = tools;
self
}
pub fn with_position(mut self, x: f64, y: f64) -> Self {
self.position = Position { x, y };
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum AgentType {
Llm,
Tool,
Sequential,
Parallel,
Loop,
Router,
Graph,
Custom,
}
impl Default for AgentType {
fn default() -> Self {
AgentType::Llm
}
}
impl Default for AgentSchema {
fn default() -> Self {
Self {
agent_type: AgentType::default(),
model: None,
instruction: String::new(),
tools: Vec::new(),
sub_agents: Vec::new(),
position: Position::default(),
max_iterations: None,
temperature: None,
top_p: None,
top_k: None,
max_output_tokens: None,
routes: Vec::new(),
tool_timeout_secs: None,
max_llm_iterations: None,
tool_retry_budget: None,
circuit_breaker_threshold: None,
tools_requiring_confirmation: Vec::new(),
tool_execution_strategy: None,
extended_thinking: None,
thinking_budget_tokens: None,
reasoning_effort: None,
prompt_caching: None,
auto_skills: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Position {
pub x: f64,
pub y: f64,
}