Skip to main content

openclaw_channels/
routing.rs

1//! Agent routing.
2
3use openclaw_core::types::{AgentId, ChannelId, PeerId};
4
5/// Route messages to appropriate agents.
6pub struct AgentRouter {
7    routes: Vec<RouteRule>,
8    default_agent: AgentId,
9}
10
11/// Routing rule.
12#[derive(Debug, Clone)]
13pub struct RouteRule {
14    /// Channel pattern.
15    pub channel: Option<String>,
16    /// Peer ID pattern.
17    pub peer_pattern: Option<String>,
18    /// Target agent.
19    pub agent_id: AgentId,
20    /// Priority (higher = first).
21    pub priority: i32,
22}
23
24impl AgentRouter {
25    /// Create a new router with default agent.
26    #[must_use]
27    pub const fn new(default_agent: AgentId) -> Self {
28        Self {
29            routes: Vec::new(),
30            default_agent,
31        }
32    }
33
34    /// Add a routing rule.
35    pub fn add_rule(&mut self, rule: RouteRule) {
36        self.routes.push(rule);
37        self.routes.sort_by(|a, b| b.priority.cmp(&a.priority));
38    }
39
40    /// Route a message to an agent.
41    #[must_use]
42    pub fn route(&self, channel: &ChannelId, peer_id: &PeerId) -> &AgentId {
43        for rule in &self.routes {
44            if let Some(ch) = &rule.channel {
45                if ch != "*" && ch != channel.as_ref() {
46                    continue;
47                }
48            }
49
50            if let Some(pattern) = &rule.peer_pattern {
51                if pattern != "*" && pattern != peer_id.as_ref() {
52                    continue;
53                }
54            }
55
56            return &rule.agent_id;
57        }
58
59        &self.default_agent
60    }
61}
62
63impl Default for AgentRouter {
64    fn default() -> Self {
65        Self::new(AgentId::default_agent())
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn test_default_routing() {
75        let router = AgentRouter::default();
76        let agent = router.route(&ChannelId::telegram(), &PeerId::new("123"));
77        assert_eq!(agent.as_ref(), "default");
78    }
79
80    #[test]
81    fn test_specific_routing() {
82        let mut router = AgentRouter::default();
83        router.add_rule(RouteRule {
84            channel: Some("telegram".to_string()),
85            peer_pattern: Some("vip123".to_string()),
86            agent_id: AgentId::new("vip-agent"),
87            priority: 100,
88        });
89
90        let agent = router.route(&ChannelId::telegram(), &PeerId::new("vip123"));
91        assert_eq!(agent.as_ref(), "vip-agent");
92
93        let agent = router.route(&ChannelId::telegram(), &PeerId::new("other"));
94        assert_eq!(agent.as_ref(), "default");
95    }
96}