Skip to main content

crabtalk_runtime/engine/
agents.rs

1//! Agent registry — persistent and ephemeral agent management.
2
3use super::Runtime;
4use crate::{Config, Env, Hook};
5use std::sync::Arc;
6use wcore::{Agent, AgentBuilder, AgentConfig, ToolDispatcher};
7
8impl<C: Config> Runtime<C> {
9    pub fn add_agent(&self, config: AgentConfig) {
10        let _ = self.upsert_agent(config);
11    }
12
13    pub fn upsert_agent(&self, config: AgentConfig) -> AgentConfig {
14        let (name, agent) = self.build_agent(config);
15        let registered = agent.config.clone();
16        self.agents.write().insert(name, agent);
17        registered
18    }
19
20    pub fn remove_agent(&self, name: &str) -> bool {
21        self.agents.write().remove(name).is_some()
22    }
23
24    fn build_agent(&self, config: AgentConfig) -> (String, Agent<C::Provider>) {
25        let config = self.env.hook().on_build_agent(config);
26        let name = config.name.clone();
27        let tools = self.tools.filtered_snapshot(&config.tools);
28        let dispatcher: Arc<dyn ToolDispatcher> = self.env.clone();
29        let agent = AgentBuilder::new(self.model.clone())
30            .config(config)
31            .tools(tools)
32            .dispatcher(dispatcher)
33            .build();
34        (name, agent)
35    }
36
37    pub fn agent(&self, name: &str) -> Option<AgentConfig> {
38        self.agents.read().get(name).map(|a| a.config.clone())
39    }
40
41    pub fn agents(&self) -> Vec<AgentConfig> {
42        self.agents
43            .read()
44            .values()
45            .map(|a| a.config.clone())
46            .collect()
47    }
48
49    // --- Ephemeral agents ---
50
51    pub async fn add_ephemeral(&self, config: AgentConfig) {
52        let (name, agent) = self.build_agent(config);
53        self.ephemeral_agents.write().await.insert(name, agent);
54    }
55
56    pub async fn remove_ephemeral(&self, name: &str) {
57        self.ephemeral_agents.write().await.remove(name);
58    }
59
60    pub(crate) async fn resolve_agent(&self, name: &str) -> Option<Agent<C::Provider>> {
61        let persistent = self.agents.read().get(name).cloned();
62        if persistent.is_some() {
63            return persistent;
64        }
65        self.ephemeral_agents.read().await.get(name).cloned()
66    }
67
68    pub(crate) async fn has_agent(&self, name: &str) -> bool {
69        let has_persistent = self.agents.read().contains_key(name);
70        if has_persistent {
71            return true;
72        }
73        self.ephemeral_agents.read().await.contains_key(name)
74    }
75}