Skip to main content

rs_adk/tools/
exit_loop.rs

1//! Exit loop tool — allows agents to break out of loop execution.
2//!
3//! Mirrors ADK-Python's `exit_loop` tool. When called by the model,
4//! signals the loop agent to terminate by setting the escalate action.
5
6use async_trait::async_trait;
7
8use crate::error::ToolError;
9use crate::tool::ToolFunction;
10
11/// Tool that signals a loop agent to exit its loop.
12///
13/// When the model calls this tool, the loop agent's escalate flag is set,
14/// causing it to break out of the current iteration.
15#[derive(Debug, Clone, Default)]
16pub struct ExitLoopTool;
17
18impl ExitLoopTool {
19    /// Create a new exit loop tool.
20    pub fn new() -> Self {
21        Self
22    }
23}
24
25#[async_trait]
26impl ToolFunction for ExitLoopTool {
27    fn name(&self) -> &str {
28        "exit_loop"
29    }
30
31    fn description(&self) -> &str {
32        "Exits the current loop. Call this function only when you are instructed to do so."
33    }
34
35    fn parameters(&self) -> Option<serde_json::Value> {
36        None
37    }
38
39    async fn call(&self, _args: serde_json::Value) -> Result<serde_json::Value, ToolError> {
40        // The actual loop exit is handled by the runtime checking
41        // the tool name. This response confirms the exit.
42        Ok(serde_json::json!({
43            "status": "loop_exited",
44            "message": "Loop has been exited successfully."
45        }))
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn tool_name_and_description() {
55        let tool = ExitLoopTool::new();
56        assert_eq!(tool.name(), "exit_loop");
57        assert!(tool.description().contains("Exit"));
58    }
59
60    #[test]
61    fn no_parameters() {
62        let tool = ExitLoopTool::new();
63        assert!(tool.parameters().is_none());
64    }
65
66    #[tokio::test]
67    async fn call_returns_success() {
68        let tool = ExitLoopTool::new();
69        let result = tool.call(serde_json::json!({})).await.unwrap();
70        assert_eq!(result["status"], "loop_exited");
71    }
72}