Skip to main content

rig_core/tool/builtin/
think.rs

1use serde::{Deserialize, Serialize};
2use serde_json::json;
3
4use crate::tool::Tool;
5
6/// Arguments for the Think tool
7#[derive(Deserialize)]
8pub struct ThinkArgs {
9    /// The thought to think about
10    pub thought: String,
11}
12
13/// Error type for the Think tool
14#[derive(Debug, thiserror::Error)]
15#[error("Think tool error: {0}")]
16pub struct ThinkError(String);
17
18/// The Think tool allows agents to stop and think in complex tool use situations.
19///
20/// This tool provides a dedicated space for structured thinking during complex tasks,
21/// particularly when processing external information (e.g., tool call results).
22/// It doesn't actually perform any actions or retrieve any information - it just
23/// provides a space for the model to reason through complex problems.
24///
25/// This tool is original derived from the
26///  [Think tool](https://anthropic.com/engineering/claude-think-tool) blog post from Anthropic.
27#[derive(Deserialize, Serialize)]
28pub struct ThinkTool;
29
30impl Tool for ThinkTool {
31    const NAME: &'static str = "think";
32
33    type Error = ThinkError;
34    type Args = ThinkArgs;
35    type Output = String;
36
37    fn description(&self) -> String {
38        "Use the tool to think about something. It will not obtain new information
39            or change the database, but just append the thought to the log. Use it when complex
40            reasoning or some cache memory is needed."
41            .to_string()
42    }
43
44    fn parameters(&self) -> serde_json::Value {
45        json!({
46            "type": "object",
47            "properties": {
48                "thought": {
49                    "type": "string",
50                    "description": "A thought to think about."
51                }
52            },
53            "required": ["thought"]
54        })
55    }
56
57    async fn call(&self, args: Self::Args) -> Result<Self::Output, Self::Error> {
58        // The think tool doesn't actually do anything except echo back the thought
59        // This is intentional - it's just a space for the model to reason through problems
60        Ok(args.thought)
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use crate::tool::tool_definition;
68
69    #[test]
70    fn test_think_tool_definition() {
71        let tool = ThinkTool;
72        let definition = tool_definition(&tool);
73
74        assert_eq!(definition.name, "think");
75        assert!(
76            definition
77                .description
78                .contains("Use the tool to think about something")
79        );
80    }
81
82    #[tokio::test]
83    async fn test_think_tool_call() {
84        let tool = ThinkTool;
85        let args = ThinkArgs {
86            thought: "I need to verify the user's identity before proceeding".to_string(),
87        };
88
89        let result = tool.call(args).await.unwrap();
90        assert_eq!(
91            result,
92            "I need to verify the user's identity before proceeding"
93        );
94    }
95}