rust_agent/
lib.rs

1// Rust Agent: AI Agent framework aligned with LangChain-Core
2
3mod core;
4mod models;
5pub mod tools;
6pub mod memory;
7mod agents;
8mod callbacks;
9mod mcp;
10
11// Re-export main components for external use
12pub use core::{Runnable, RunnableExt, RunnableSequence};
13pub use models::{ChatModel, ChatMessage as ModelChatMessage, ChatMessageContent, ChatCompletion, TokenUsage, OpenAIChatModel};
14pub use tools::{Tool, Toolkit, ExampleTool, ExampleToolkit, find_matching_tool_index, parse_model_output};
15pub use memory::{BaseMemory, SimpleMemory, MessageHistoryMemory, SummaryMemory, CompositeMemory, CompositeMemoryConfig, ChatMessageRecord, ChatMessage};
16pub use agents::{Agent, McpAgent, AgentAction, AgentFinish, AgentOutput, AgentRunner, SimpleAgent, SimpleAgentRunner};
17pub use callbacks::CallbackHandler;
18pub use mcp::{McpClient, SimpleMcpClient, McpTool, McpToolAdapter, McpServer, SimpleMcpServer};
19use anyhow::Error;
20use std::collections::HashMap;
21
22// Utility functions and error handling
23pub use core::pipe;
24// Export anyhow error handling library to ensure consistent error handling for third-party users
25pub use anyhow;
26
27// Main function to run Agent
28pub async fn run_agent(agent: &McpAgent, input: String) -> Result<String, Error> {
29    let mut inputs = HashMap::new();
30    inputs.insert("input".to_string(), input);
31    let output = agent.invoke(inputs).await?;
32    
33    match output {
34        AgentOutput::Action(action) => {
35            // Find the corresponding tool using fuzzy matching mechanism
36            let tools = agent.tools();
37            match find_matching_tool_index(&tools, &action.tool) {
38                Some(matched_name) => {
39                    // After finding a matching tool name, search for the specific tool again
40                    if let Some(tool) = tools.iter().find(|t| t.name() == matched_name) {
41                        // Invoke the tool
42                        let tool_result = tool.invoke(&action.tool_input).await?;
43                        
44                        // Feed the tool execution result back to Agent for further processing
45                        let mut new_inputs = HashMap::new();
46                        new_inputs.insert("input".to_string(), format!("[CUSTOMIZE_TOOL_RESULT] {{\"tool\": \"{}\", \"result\": {}}}", matched_name, tool_result));
47                        let new_output = agent.invoke(new_inputs).await?;
48                        
49                        match new_output {
50                            AgentOutput::Finish(finish) => {
51                                Ok(finish.return_values.get("answer").map(|s| s.clone()).unwrap_or_else(|| "".to_string()))
52                            },
53                            _ => {
54                                // If still Action, simply return the tool result for now
55                                Ok(format!("Tool {} executed successfully, result: {}", matched_name, tool_result))
56                            }
57                        }
58                    } else {
59                        Err(Error::msg(format!("Tool {} does not exist", matched_name)))
60                    }
61                },
62                None => {
63                    Err(Error::msg(format!("Tool {} does not exist", action.tool)))
64                }
65            }
66        },
67        AgentOutput::Finish(finish) => {
68            Ok(finish.return_values.get("answer").map(|s| s.clone()).unwrap_or_else(|| "".to_string()))
69        },
70    }
71}