Skip to main content

agent_engine/tools/
respond.rs

1//! RespondTool — reply to an event through its original source channel.
2use super::{Tool, ToolContext};
3use crate::Result;
4use serde_json::{json, Value};
5
6pub struct RespondTool;
7
8#[async_trait::async_trait]
9impl Tool for RespondTool {
10    fn origin(&self) -> crate::tools::ToolOrigin {
11        crate::tools::ToolOrigin::Builtin
12    }
13
14    fn name(&self) -> &str {
15        "respond"
16    }
17
18    fn description(&self) -> &str {
19        "Reply to an event through its original source channel. Sends the response text back via the event's callback URL or logs it if no callback is available."
20    }
21
22    fn parameters(&self) -> Value {
23        json!({
24            "type": "object",
25            "properties": {
26                "event_id": { "type": "string", "description": "ID of the event to respond to" },
27                "text":     { "type": "string", "description": "Response message" }
28            },
29            "required": ["event_id", "text"]
30        })
31    }
32
33    async fn execute(&self, params: Value, _ctx: ToolContext) -> Result<String> {
34        let event_id = params["event_id"]
35            .as_str()
36            .ok_or_else(|| crate::RuntimeError::Tool("Missing 'event_id' parameter".to_string()))?
37            .to_string();
38        let text = params["text"]
39            .as_str()
40            .ok_or_else(|| crate::RuntimeError::Tool("Missing 'text' parameter".to_string()))?
41            .to_string();
42
43        tracing::info!(event_id = %event_id, "respond tool invoked: {}", text);
44
45        // NOT YET IMPLEMENTED — return clear failure so the model knows
46        Ok(json!({
47            "responded": false,
48            "error": "respond tool is not yet implemented — callback dispatch not wired",
49            "event_id": event_id,
50        })
51        .to_string())
52    }
53}