use serde::{Deserialize, Serialize};
pub type AgentId = String;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TriggerCondition {
NumericRange { min: f64, max: f64 },
StringContains { content: String },
StatusMatches { expected_status: String },
CustomExpression { expression: String },
ScheduleInterval { seconds: u64 },
ScheduleCron { cron_expression: String },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Agent {
pub id: AgentId,
pub name: String,
pub role: Role,
pub department_id: Option<String>,
pub llm_config: LLMConfig,
pub description: Option<String>,
pub watched_tools: Vec<String>,
pub trigger_conditions: Vec<TriggerCondition>,
}
impl Agent {
pub fn new(
id: impl Into<String>,
name: impl Into<String>,
role: Role,
llm_config: LLMConfig,
) -> Self {
Self {
id: id.into(),
name: name.into(),
role,
department_id: None,
llm_config,
description: None,
watched_tools: vec![],
trigger_conditions: vec![],
}
}
pub fn new_with_watching(
id: impl Into<String>,
name: impl Into<String>,
role: Role,
llm_config: LLMConfig,
watched_tools: Vec<String>,
trigger_conditions: Vec<TriggerCondition>,
) -> Self {
Self {
id: id.into(),
name: name.into(),
role,
department_id: None,
llm_config,
description: None,
watched_tools,
trigger_conditions,
}
}
pub fn with_department(mut self, dept_id: impl Into<String>) -> Self {
self.department_id = Some(dept_id.into());
self
}
pub fn with_watched_tools(mut self, watched_tools: Vec<String>) -> Self {
self.watched_tools = watched_tools;
self
}
pub fn with_trigger_conditions(mut self, trigger_conditions: Vec<TriggerCondition>) -> Self {
self.trigger_conditions = trigger_conditions;
self
}
pub fn add_watched_tool(mut self, tool_id: impl Into<String>) -> Self {
self.watched_tools.push(tool_id.into());
self
}
pub fn add_trigger_condition(mut self, condition: TriggerCondition) -> Self {
self.trigger_conditions.push(condition);
self
}
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = Some(description.into());
self
}
pub fn system_prompt(&self) -> String {
self.role.system_prompt.clone()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Role {
pub title: String,
pub responsibilities: Vec<String>,
pub expertise: Vec<String>,
pub system_prompt: String,
}
impl Role {
pub fn new(
title: impl Into<String>,
responsibilities: impl IntoIterator<Item = impl Into<String>>,
expertise: impl IntoIterator<Item = impl Into<String>>,
system_prompt: impl Into<String>,
) -> Self {
Self {
title: title.into(),
responsibilities: responsibilities.into_iter().map(|s| s.into()).collect(),
expertise: expertise.into_iter().map(|s| s.into()).collect(),
system_prompt: system_prompt.into(),
}
}
pub fn simple(title: impl Into<String>, system_prompt: impl Into<String>) -> Self {
Self {
title: title.into(),
responsibilities: vec![],
expertise: vec![],
system_prompt: system_prompt.into(),
}
}
pub fn with_responsibilities(mut self, items: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.responsibilities = items.into_iter().map(|s| s.into()).collect();
self
}
pub fn with_expertise(mut self, items: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.expertise = items.into_iter().map(|s| s.into()).collect();
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LLMConfig {
pub model: String,
pub api_key: String,
pub base_url: String,
}
impl LLMConfig {
pub fn openai(api_key: impl Into<String>) -> Self {
Self {
model: "gpt-4o-mini".to_string(),
api_key: api_key.into(),
base_url: "https://api.openai.com/v1".to_string(),
}
}
pub fn with_model(mut self, model: impl Into<String>) -> Self {
self.model = model.into();
self
}
pub fn with_base_url(mut self, url: impl Into<String>) -> Self {
self.base_url = url.into();
self
}
}