rust_agent/agents/
agent.rs1use anyhow::Error;
3use std::collections::HashMap;
4use crate::tools::{ExampleTool, Tool};
5use crate::core::Runnable;
6
7#[derive(Clone, Debug)]
9pub struct AgentAction {
10 pub tool: String,
11 pub tool_input: String,
12 pub log: String,
13 pub thought: Option<String>,
14}
15
16#[derive(Clone, Debug)]
18pub struct AgentFinish {
19 pub return_values: HashMap<String, String>,
20}
21
22#[derive(Clone, Debug)]
24pub enum AgentOutput {
25 Action(AgentAction),
26 Finish(AgentFinish),
27}
28
29pub trait Agent: Send + Sync {
31 fn tools(&self) -> Vec<Box<dyn Tool + Send + Sync>>;
33
34 fn execute(&self, action: &AgentAction) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<String, Error>> + Send + '_>> {
36 let tools = self.tools();
37 let tool_name = action.tool.clone();
38 let tool_input = action.tool_input.clone();
39
40 Box::pin(async move {
41 for tool in tools {
43 if tool.name() == tool_name {
44 return tool.invoke(&tool_input).await;
45 }
46 }
47 Err(Error::msg(format!("The tool {} not found", tool_name)))
48 })
49 }
50
51 fn clone_agent(&self) -> Box<dyn Agent>;
53}
54
55pub trait AgentRunner: Runnable<HashMap<String, String>, AgentOutput> {
57 }
60
61pub struct SimpleAgent {
63 tools: Vec<Box<dyn Tool + Send + Sync>>,
64}
65
66impl SimpleAgent {
67 pub fn new() -> Self {
68 Self {
69 tools: Vec::new(),
70 }
71 }
72
73 pub fn add_tool(&mut self, tool: Box<dyn Tool + Send + Sync>) {
74 self.tools.push(tool);
75 }
76}
77
78impl Agent for SimpleAgent {
79 fn tools(&self) -> Vec<Box<dyn Tool + Send + Sync>> {
80 Vec::new()
82 }
83
84 fn clone_agent(&self) -> Box<dyn Agent> {
85 let mut cloned = SimpleAgent::new();
86 for tool in &self.tools {
88 let name = tool.name();
89 let description = tool.description();
90 let new_tool = Box::new(ExampleTool::new(name.to_string(), description.to_string()));
91 cloned.add_tool(new_tool);
92 }
93 Box::new(cloned)
94 }
95}
96
97pub struct SimpleAgentRunner {
99 agent: Box<dyn Agent>,
100}
101
102impl SimpleAgentRunner {
103 pub fn new(agent: impl Agent + 'static) -> Self {
104 Self {
105 agent: Box::new(agent),
106 }
107 }
108}
109
110impl Runnable<HashMap<String, String>, AgentOutput> for SimpleAgentRunner {
111 fn invoke(&self, inputs: HashMap<String, String>) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<AgentOutput, Error>> + Send>> {
112 let inputs_clone = inputs.clone();
113
114 Box::pin(async move {
115 if let Some(tool_name) = inputs_clone.get("tool") {
118 let tool_input = inputs_clone.get("input").unwrap_or(&"input empty".to_string()).clone();
119
120 Ok(AgentOutput::Action(AgentAction {
121 tool: tool_name.to_string(),
122 tool_input,
123 log: format!("Invoking tool: {}", tool_name),
124 thought: Some("Invoking tool".to_string()),
125 }))
126 } else {
127 let output_text = inputs_clone.get("input").unwrap_or(&"".to_string()).clone();
129 let mut return_values = HashMap::new();
130 return_values.insert("output".to_string(), format!("Finish processing input: {}", output_text));
131
132 Ok(AgentOutput::Finish(AgentFinish {
133 return_values,
134 }))
135 }
136 })
137 }
138
139 fn clone_to_owned(&self) -> Box<dyn Runnable<HashMap<String, String>, AgentOutput> + Send + Sync> {
140 Box::new(SimpleAgentRunner { agent: self.agent.clone_agent() })
142 }
143}
144
145impl Clone for SimpleAgent {
147 fn clone(&self) -> Self {
148 let mut agent = SimpleAgent::new();
149 for tool in &self.tools {
153 let name = tool.name();
155 let description = tool.description();
156 let new_tool = Box::new(ExampleTool::new(name.to_string(), description.to_string()));
158 agent.add_tool(new_tool);
159 }
160 agent
161 }
162}