Skip to main content

agentzero_core/
agent_store.rs

1//! Trait and types for persistent agent management.
2//!
3//! The trait lives in `agentzero-core` so that `agentzero-infra` (the tool
4//! host) can depend on it without creating a circular dependency with
5//! `agentzero-orchestrator` (where the concrete `AgentStore` lives).
6
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9
10/// Status of a dynamically-created agent.
11#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(rename_all = "lowercase")]
13pub enum AgentStatus {
14    Active,
15    Stopped,
16}
17
18/// Channel configuration for a dynamic agent.
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct AgentChannelConfig {
21    #[serde(default, skip_serializing_if = "Option::is_none")]
22    pub bot_token: Option<String>,
23    #[serde(default, skip_serializing_if = "Option::is_none")]
24    pub webhook_url: Option<String>,
25    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
26    pub extra: HashMap<String, String>,
27}
28
29/// Persistent record for a dynamically-created agent.
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct AgentRecord {
32    pub agent_id: String,
33    pub name: String,
34    #[serde(default)]
35    pub description: String,
36    #[serde(default, skip_serializing_if = "Option::is_none")]
37    pub system_prompt: Option<String>,
38    #[serde(default)]
39    pub provider: String,
40    #[serde(default)]
41    pub model: String,
42    #[serde(default)]
43    pub keywords: Vec<String>,
44    #[serde(default)]
45    pub allowed_tools: Vec<String>,
46    #[serde(default)]
47    pub channels: HashMap<String, AgentChannelConfig>,
48    pub created_at: u64,
49    pub updated_at: u64,
50    pub status: AgentStatus,
51}
52
53/// Fields that can be updated on an existing agent.
54#[derive(Debug, Clone, Default, Serialize, Deserialize)]
55pub struct AgentUpdate {
56    #[serde(default, skip_serializing_if = "Option::is_none")]
57    pub name: Option<String>,
58    #[serde(default, skip_serializing_if = "Option::is_none")]
59    pub description: Option<String>,
60    #[serde(default, skip_serializing_if = "Option::is_none")]
61    pub system_prompt: Option<String>,
62    #[serde(default, skip_serializing_if = "Option::is_none")]
63    pub provider: Option<String>,
64    #[serde(default, skip_serializing_if = "Option::is_none")]
65    pub model: Option<String>,
66    #[serde(default, skip_serializing_if = "Option::is_none")]
67    pub keywords: Option<Vec<String>>,
68    #[serde(default, skip_serializing_if = "Option::is_none")]
69    pub allowed_tools: Option<Vec<String>>,
70    #[serde(default, skip_serializing_if = "Option::is_none")]
71    pub channels: Option<HashMap<String, AgentChannelConfig>>,
72}
73
74/// Trait for persistent agent CRUD operations.
75///
76/// Implemented by `AgentStore` in `agentzero-orchestrator`. Used by
77/// `AgentManageTool` in `agentzero-infra` to avoid a circular crate
78/// dependency.
79pub trait AgentStoreApi: Send + Sync {
80    fn create(&self, record: AgentRecord) -> anyhow::Result<AgentRecord>;
81    fn get(&self, agent_id: &str) -> Option<AgentRecord>;
82    fn list(&self) -> Vec<AgentRecord>;
83    fn update(&self, agent_id: &str, update: AgentUpdate) -> anyhow::Result<Option<AgentRecord>>;
84    fn delete(&self, agent_id: &str) -> anyhow::Result<bool>;
85    fn set_status(&self, agent_id: &str, status: AgentStatus) -> anyhow::Result<bool>;
86    fn count(&self) -> usize;
87}