Skip to main content

clawdesk-autoreply

Automatic reply system for handling common messages without invoking the full agent pipeline. Supports trigger classification (keyword, regex, intent-based), template rendering, and send policy enforcement.

Dependencies

Internal: clawdesk-types, clawdesk-domain

External: serde, tracing, thiserror, regex

Modules

ModuleDescription
triggerTrigger classification — matches messages to auto-reply rules
templateTemplate engine for auto-reply messages with variable substitution
policySend policy enforcement — rate limits, cooldowns, channel restrictions

Key Types

/// Auto-reply rule
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AutoReplyRule {
pub id: String,
pub name: String,
pub trigger: Trigger,
pub response: ResponseTemplate,
pub policy: SendPolicy,
pub enabled: bool,
pub priority: i32,
}

/// Trigger condition for matching messages
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Trigger {
Keyword(Vec<String>),
Regex(String),
Exact(String),
Intent(String),
Always,
}

/// Response template with variable substitution
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResponseTemplate {
pub content: String,
pub variables: HashMap<String, String>,
}

/// Send policy constraints
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SendPolicy {
pub max_per_hour: Option<u32>,
pub cooldown_secs: Option<u64>,
pub channels: Option<Vec<ChannelId>>,
pub hours: Option<(u8, u8)>, // Active hours (start, end)
}

/// Auto-reply engine
pub struct AutoReplyEngine {
rules: Vec<AutoReplyRule>,
}

impl AutoReplyEngine {
/// Check if a message matches any auto-reply rule
pub fn classify(&self, message: &Message) -> Option<&AutoReplyRule> { /* ... */ }

/// Render the response template with variables
pub fn render(&self, rule: &AutoReplyRule, context: &MessageContext) -> String { /* ... */ }
}

Example Usage

use clawdesk_autoreply::{AutoReplyEngine, AutoReplyRule, Trigger, ResponseTemplate};

let engine = AutoReplyEngine::new(vec![
AutoReplyRule {
id: "greeting".into(),
name: "Greeting Reply".into(),
trigger: Trigger::Keyword(vec!["hello".into(), "hi".into(), "hey".into()]),
response: ResponseTemplate {
content: "Hello {{user_name}}! How can I help you today?".into(),
variables: Default::default(),
},
policy: SendPolicy::default(),
enabled: true,
priority: 10,
},
]);

if let Some(rule) = engine.classify(&message) {
let response = engine.render(rule, &context);
// Send response directly without agent pipeline
}
tip

Auto-reply rules are evaluated in priority order (highest first). The first matching rule wins. To bypass auto-reply, prefix messages with ! or configure channel-specific overrides.