├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── assets ├── concept-agent-and-swarms.png ├── concept-agent-collabration-model.png ├── design-flows.png └── design-swarms-apis.png ├── demo_btc_prediction_consensus_swarm ├── Cargo.toml └── src │ ├── agents │ ├── btc_price_ml_predictor.rs │ ├── btc_price_statistical_predictor.rs │ └── mod.rs │ ├── lib.rs │ └── tools │ ├── coingecko.rs │ ├── mod.rs │ └── yahoo_finance.rs ├── design ├── README.md ├── api │ ├── README.md │ ├── agent_communication.md │ ├── memory_integration.md │ ├── model_integration.md │ ├── prompt_management.md │ ├── storage_integration.md │ └── swarm_orchestration.md ├── diagrams │ ├── README.md │ ├── component_diagram.md │ ├── deployment_diagram.md │ ├── sequence_diagrams.md │ └── state_diagrams.md ├── interfaces │ ├── README.md │ ├── agent.md │ ├── blockchain_examples.md │ ├── memory.md │ ├── models.md │ ├── storage.md │ ├── swarm.md │ ├── task.md │ └── wallet.md └── requirements │ ├── README.md │ ├── agent_consensus.md │ ├── blockchain_security.md │ ├── consensus.md │ ├── core_functions.md │ ├── error_handling.md │ ├── message_passing.md │ ├── self_improvement.md │ ├── storage.md │ └── task_mutability.md ├── swarm_agent ├── Cargo.toml └── src │ ├── lib.rs │ ├── mock.rs │ └── service.rs ├── swarm_llm ├── Cargo.toml └── src │ ├── lib.rs │ ├── mock.rs │ └── openai.rs ├── swarm_memory ├── Cargo.toml └── src │ ├── chromadb.rs │ ├── lib.rs │ └── pinecone.rs ├── swarm_tool ├── Cargo.toml └── src │ └── lib.rs ├── swarm_wallet ├── Cargo.toml └── src │ ├── evm.rs │ ├── lib.rs │ └── solana.rs └── swarms ├── Cargo.toml └── src ├── architectures ├── circular.rs ├── fibonacci.rs ├── geometric.rs ├── graph_swarm.rs ├── grid.rs ├── harmonic.rs ├── linear.rs ├── mesh.rs ├── mod.rs ├── patterns.rs ├── prime.rs ├── pyramid.rs ├── queue_swarm.rs ├── round_robin.rs ├── star.rs └── tree_swarm.rs ├── lib.rs └── mock.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | 16 | # RustRover 17 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 18 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 19 | # and can be added to the global gitignore or merged into this file. For a more nuclear 20 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 21 | #.idea/ -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "swarms", 5 | "swarm_agent", 6 | "swarm_tool", 7 | "swarm_wallet", 8 | "swarm_llm", 9 | "swarm_memory", 10 | "demo_btc_prediction_consensus_swarm", 11 | ] 12 | 13 | [workspace.dependencies] 14 | tokio = { version = "1.0", features = ["full"] } 15 | async-trait = "0.1" 16 | serde = { version = "1.0", features = ["derive"] } 17 | serde_json = "1.0" 18 | uuid = { version = "1.0", features = ["v4", "serde"] } 19 | log = "0.4" 20 | env_logger = "0.11.6" 21 | thiserror = "2.0.11" 22 | reqwest = { version = "0.12.12", features = ["json", "blocking"] } 23 | dotenv = "0.15" 24 | rand = "0.8" 25 | tempfile = "3.2" 26 | futures = "0.3" 27 | tokio-stream = "0.1" 28 | parking_lot = "0.12" 29 | dashmap = "6.1.0" 30 | tracing = "0.1" 31 | derive_more = "1.0.0" 32 | cargo-platform = "0.1.2" 33 | alloy = { version = "0.9.2", features = ["full"] } 34 | alloy-contract = "0.9.2" 35 | solana-sdk = "2.1.8" 36 | bs58 = "0.5.1" 37 | bytes = "1.0.1" 38 | rusqlite = "0.32.1" 39 | chrono = "0.4.19" 40 | yahoo_finance_api = "2.4.0" 41 | 42 | 43 | [workspace.package] 44 | version = "0.1.0" 45 | edition = "2021" 46 | authors = ["Mind Network"] 47 | description = "A Rust implementation of the swarms multi-agent collaboration framework" 48 | license = "MIT" 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 georgesh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assets/concept-agent-and-swarms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mind-network/swarms-rust/cf0de81da24569f2367833fe01fd19dd0647e164/assets/concept-agent-and-swarms.png -------------------------------------------------------------------------------- /assets/concept-agent-collabration-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mind-network/swarms-rust/cf0de81da24569f2367833fe01fd19dd0647e164/assets/concept-agent-collabration-model.png -------------------------------------------------------------------------------- /assets/design-flows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mind-network/swarms-rust/cf0de81da24569f2367833fe01fd19dd0647e164/assets/design-flows.png -------------------------------------------------------------------------------- /assets/design-swarms-apis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mind-network/swarms-rust/cf0de81da24569f2367833fe01fd19dd0647e164/assets/design-swarms-apis.png -------------------------------------------------------------------------------- /demo_btc_prediction_consensus_swarm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "demo_btc_prediction_consensus_swarm" 3 | version = "0.1.0" 4 | edition = "2021" 5 | description = "BTC Prediction and Consensus Swarms" 6 | license = "MIT" 7 | 8 | [dependencies] 9 | swarm_tool = { path = "../swarm_tool" } 10 | swarm_llm = { path = "../swarm_llm" } 11 | swarm_wallet = { path = "../swarm_wallet" } 12 | swarm_memory = { path = "../swarm_memory" } 13 | swarm_agent = { path = "../swarm_agent" } 14 | swarms = { path = "../swarms" } 15 | tokio = { workspace = true } 16 | async-trait = { workspace = true } 17 | serde = { workspace = true } 18 | serde_json = { workspace = true } 19 | uuid = { workspace = true } 20 | log = { workspace = true } 21 | env_logger = { workspace = true } 22 | thiserror = { workspace = true } 23 | reqwest = { workspace = true } 24 | dotenv = { workspace = true } 25 | rand = { workspace = true } 26 | tempfile = { workspace = true } 27 | futures = { workspace = true } 28 | tokio-stream = { workspace = true } 29 | parking_lot = { workspace = true } 30 | dashmap = { workspace = true } 31 | tracing = { workspace = true } 32 | rusqlite = { workspace = true} 33 | chrono = { workspace = true } 34 | yahoo_finance_api = { workspace = true } 35 | 36 | [features] 37 | default = [] 38 | 39 | [dev-dependencies] 40 | wiremock = "0.5" 41 | -------------------------------------------------------------------------------- /demo_btc_prediction_consensus_swarm/src/agents/btc_price_statistical_predictor.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use std::collections::HashMap; 3 | use uuid::Uuid; 4 | 5 | use swarm_agent::{Agent, AgentConfig}; 6 | use swarm_wallet::{Wallet, WalletError, evm::EvmWallet}; 7 | use swarm_tool::{Tool, ParameterType, ToolSchema, ToolParameter}; 8 | 9 | use crate::tools::yahoo_finance::YahooFinanceTool; 10 | 11 | 12 | pub struct BtcPriceStatisticalPredictorAgent { 13 | config: AgentConfig, 14 | tools: HashMap>, 15 | wallet: Option>, 16 | schema: ToolSchema, 17 | } 18 | 19 | impl std::fmt::Debug for BtcPriceStatisticalPredictorAgent { 20 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 21 | f.debug_struct("BtcPriceStatisticalPredictorAgent") 22 | .field("config", &self.config) 23 | .field("tools", &self.tools.keys().collect::>()) 24 | .field("schema", &self.schema) 25 | .finish() 26 | } 27 | } 28 | 29 | impl BtcPriceStatisticalPredictorAgent { 30 | pub fn new(config: AgentConfig) -> Self { 31 | let mut tools = HashMap::new(); 32 | tools.insert( 33 | "yahoo-finance".to_string(), 34 | Box::new(YahooFinanceTool::new()) as Box, 35 | ); 36 | 37 | Self { 38 | config, 39 | tools, 40 | wallet: None, 41 | schema: ToolSchema { 42 | name: "btc-price-statistical-predictor".to_string(), 43 | description: "Predicts BTC price using statistical analysis".to_string(), 44 | parameters: vec![ToolParameter { 45 | name: "days".to_string(), 46 | description: "Number of days for prediction".to_string(), 47 | parameter_type: ParameterType::Integer, 48 | required: true, 49 | }], 50 | }, 51 | } 52 | } 53 | 54 | async fn calculate_moving_average(&self, data: &str) -> Result { 55 | #[derive(serde::Deserialize)] 56 | struct HistoricalData { 57 | close: f64, 58 | } 59 | 60 | let historical_data: Vec = serde_json::from_str(data) 61 | .map_err(|e| format!("Failed to parse historical data: {}", e))?; 62 | 63 | if historical_data.is_empty() { 64 | return Err("No historical data available".to_string()); 65 | } 66 | 67 | let sum: f64 = historical_data.iter().map(|entry| entry.close).sum(); 68 | Ok(sum / historical_data.len() as f64) 69 | } 70 | } 71 | 72 | #[async_trait] 73 | impl Agent for BtcPriceStatisticalPredictorAgent { 74 | async fn run(&mut self, task: &str) -> Result { 75 | // Parse number of days from task 76 | let days = task 77 | .split_whitespace() 78 | .find(|s| s.parse::().is_ok()) 79 | .and_then(|s| s.parse::().ok()) 80 | .ok_or_else(|| "Task must include number of days".to_string())?; 81 | 82 | // Get historical data using YahooFinanceApiTool 83 | let yahoo_tool = self 84 | .tools 85 | .get("yahoo-finance") 86 | .ok_or_else(|| "Yahoo Finance tool not found".to_string())?; 87 | 88 | let historical_data: String = yahoo_tool.run(&days.to_string())?; 89 | let prediction = self.calculate_moving_average(&historical_data) 90 | .await 91 | .map(|val| format!("{}", val))?; 92 | 93 | // Format prediction 94 | let result = format!("BTC Price Prediction (Moving Average): ${:.2}", prediction); 95 | 96 | Ok(result) 97 | } 98 | 99 | fn id(&self) -> Uuid { 100 | self.config.id 101 | } 102 | 103 | fn name(&self) -> &str { 104 | &self.config.name 105 | } 106 | 107 | fn system_prompt(&self) -> &str { 108 | &self.config.system_prompt 109 | } 110 | 111 | fn add_tool(&mut self, tool: Box) { 112 | self.tools.insert(tool.name().to_string(), tool); 113 | } 114 | 115 | fn config(&self) -> &AgentConfig { 116 | &self.config 117 | } 118 | } 119 | 120 | 121 | #[cfg(test)] 122 | mod tests { 123 | use super::*; 124 | 125 | // Statistical Predictor Tests 126 | #[tokio::test] 127 | async fn test_statistical_predictor_basic() { 128 | let config = AgentConfig::default(); 129 | let agent = BtcPriceStatisticalPredictorAgent::new(config); 130 | 131 | assert!(agent.name().contains("agent")); 132 | } 133 | 134 | #[tokio::test] 135 | async fn test_statistical_predictor_validation() { 136 | let config = AgentConfig::default(); 137 | let mut agent = BtcPriceStatisticalPredictorAgent::new(config); 138 | 139 | // Test invalid input (no days) 140 | let result = agent.run("predict BTC price").await; 141 | assert!(result.is_err()); 142 | 143 | // Test invalid days format 144 | let result = agent.run("predict BTC price in invalid days").await; 145 | println!("statistical predictor validation: {:?}", result); 146 | assert!(result.is_err()); 147 | } 148 | } -------------------------------------------------------------------------------- /demo_btc_prediction_consensus_swarm/src/agents/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod btc_price_statistical_predictor; 2 | pub mod btc_price_ml_predictor; -------------------------------------------------------------------------------- /demo_btc_prediction_consensus_swarm/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod tools; 2 | pub mod agents; -------------------------------------------------------------------------------- /demo_btc_prediction_consensus_swarm/src/tools/coingecko.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use reqwest::Client; 3 | use swarm_tool::{Tool, ToolSchema}; 4 | 5 | #[derive(Debug)] 6 | pub struct CoingeckoTool { 7 | client: Client, 8 | schema: ToolSchema, 9 | base_url: String, 10 | } 11 | 12 | impl Default for CoingeckoTool { 13 | fn default() -> Self { 14 | Self::new() 15 | } 16 | } 17 | 18 | impl CoingeckoTool { 19 | pub fn new() -> Self { 20 | Self { 21 | client: Client::new(), 22 | schema: ToolSchema { 23 | name: "coingecko-api".to_string(), 24 | description: "Retrieves current BTC price from Coingecko API".to_string(), 25 | parameters: vec![], 26 | }, 27 | base_url: "https://api.coingecko.com/api/v3".to_string(), 28 | } 29 | } 30 | 31 | pub fn with_base_url(mut self, base_url: String) -> Self { 32 | self.base_url = base_url; 33 | self 34 | } 35 | } 36 | 37 | impl CoingeckoTool { 38 | async fn run(&self, _input: &str) -> Result { 39 | let url = format!( 40 | "{}/simple/price?ids=bitcoin&vs_currencies=usd", 41 | self.base_url 42 | ); 43 | 44 | let response = self 45 | .client 46 | .get(url) 47 | .send() 48 | .await 49 | .map_err(|e| format!("Request failed: {}", e))?; 50 | 51 | //println!("Response: {:?}", response); 52 | 53 | let json: serde_json::Value = response 54 | .json() 55 | .await 56 | .map_err(|e| format!("Failed to parse JSON: {}", e))?; 57 | 58 | let price = json["bitcoin"]["usd"] 59 | .as_f64() 60 | .ok_or_else(|| format!("Invalid response format: {}", json))?; 61 | 62 | Ok(price.to_string()) 63 | } 64 | } 65 | 66 | #[async_trait] 67 | impl Tool for CoingeckoTool { 68 | fn name(&self) -> &str { 69 | &self.schema.name 70 | } 71 | 72 | fn description(&self) -> &str { 73 | &self.schema.description 74 | } 75 | 76 | fn schema(&self) -> &ToolSchema { 77 | &self.schema 78 | } 79 | 80 | fn run(&self, input: &str) -> Result { 81 | tokio::runtime::Runtime::new() 82 | .unwrap() 83 | .block_on(self.run(input)) 84 | } 85 | } 86 | 87 | #[cfg(test)] 88 | mod test { 89 | use serde_json::json; 90 | use wiremock::matchers::method; 91 | use wiremock::matchers::path; 92 | use wiremock::ResponseTemplate; 93 | use wiremock::MockServer; 94 | use wiremock::Mock; 95 | use super::*; 96 | 97 | #[tokio::test] 98 | async fn test_coingecko_api_tool() { 99 | let tool = CoingeckoTool::new(); 100 | assert_eq!(tool.name(), "coingecko-api"); 101 | } 102 | 103 | #[tokio::test] 104 | async fn test_coingecko_api_tool_run_mock() { 105 | // Start mock server 106 | let mock_server = MockServer::start().await; 107 | 108 | // Mock the Coingecko API response 109 | Mock::given(method("GET")) 110 | .and(path("/simple/price")) 111 | .respond_with(ResponseTemplate::new(200).set_body_json(json!({ 112 | "bitcoin": { 113 | "usd": 50000 114 | } 115 | }))) 116 | .mount(&mock_server) 117 | .await; 118 | 119 | let tool = CoingeckoTool::new().with_base_url(mock_server.uri()); 120 | let result = tool.run("").await; 121 | println!("CoingeckoApiTool mock run result: {:?}", result); 122 | 123 | assert!(result.is_ok()); 124 | let price = result.unwrap().parse::().unwrap(); 125 | assert!(price > 0.0); 126 | } 127 | 128 | #[tokio::test] 129 | async fn test_coingecko_api_tool_run() { 130 | let tool = CoingeckoTool::new(); 131 | let result = tool.run("").await; 132 | println!("CoingeckoApiTool run result: {:?}", result); 133 | 134 | assert!(result.is_ok()); 135 | let price = result.unwrap().parse::().unwrap(); 136 | assert!(price > 0.0); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /demo_btc_prediction_consensus_swarm/src/tools/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod coingecko; 2 | pub mod yahoo_finance; -------------------------------------------------------------------------------- /demo_btc_prediction_consensus_swarm/src/tools/yahoo_finance.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use serde::{Deserialize, Serialize}; 3 | use swarm_tool::{Tool, ToolSchema, ParameterType, ToolParameter}; 4 | use yahoo_finance_api::time::{self, OffsetDateTime}; 5 | use yahoo_finance_api::YahooConnector; 6 | 7 | #[derive(Debug, Serialize, Deserialize)] 8 | struct HistoricalData { 9 | timestamp: i64, 10 | open: f64, 11 | high: f64, 12 | low: f64, 13 | close: f64, 14 | volume: i64, 15 | } 16 | 17 | use chrono::Utc; 18 | use rusqlite::{Connection, OptionalExtension, Result as SqliteResult}; 19 | use std::path::PathBuf; 20 | 21 | #[derive(Debug)] 22 | pub struct YahooFinanceTool { 23 | schema: ToolSchema, 24 | db_path: PathBuf, 25 | } 26 | 27 | impl Default for YahooFinanceTool { 28 | fn default() -> Self { 29 | Self::new() 30 | } 31 | } 32 | 33 | impl YahooFinanceTool { 34 | pub fn new() -> Self { 35 | Self { 36 | schema: ToolSchema { 37 | name: "yahoo-finance".to_string(), 38 | description: "Retrieves historical BTC price data from Yahoo Finance".to_string(), 39 | parameters: vec![ToolParameter { 40 | name: "days".to_string(), 41 | description: "Number of days of historical data".to_string(), 42 | parameter_type: ParameterType::Integer, 43 | required: true, 44 | }], 45 | }, 46 | db_path: PathBuf::from("cache.db"), 47 | } 48 | } 49 | 50 | pub fn with_db_path(mut self, path: PathBuf) -> Self { 51 | self.db_path = path; 52 | self 53 | } 54 | 55 | async fn get_cached_data(&self, symbol: &str, _days: i64) -> Result, String> { 56 | let conn = Connection::open(&self.db_path) 57 | .map_err(|e| format!("Failed to open cache database: {}", e))?; 58 | 59 | conn.execute( 60 | "CREATE TABLE IF NOT EXISTS price_cache ( 61 | symbol TEXT NOT NULL, 62 | data TEXT NOT NULL, 63 | timestamp INTEGER NOT NULL 64 | )", 65 | [], 66 | ) 67 | .map_err(|e| format!("Failed to create cache table: {}", e))?; 68 | 69 | let cutoff = (Utc::now() - chrono::Duration::days(1)).timestamp(); 70 | let mut stmt = conn 71 | .prepare( 72 | "SELECT data FROM price_cache 73 | WHERE symbol = ? AND timestamp > ? 74 | ORDER BY timestamp DESC LIMIT 1", 75 | ) 76 | .map_err(|e| format!("Failed to prepare query: {}", e))?; 77 | 78 | let result: SqliteResult> = stmt 79 | .query_row([symbol, &cutoff.to_string()], |row| row.get(0)) 80 | .optional(); 81 | 82 | match result { 83 | Ok(data) => Ok(data), 84 | Err(e) => Err(format!("Failed to query cache: {}", e)), 85 | } 86 | } 87 | 88 | async fn cache_data(&self, symbol: &str, data: &str) -> Result<(), String> { 89 | let conn = Connection::open(&self.db_path) 90 | .map_err(|e| format!("Failed to open cache database: {}", e))?; 91 | 92 | conn.execute( 93 | "INSERT INTO price_cache (symbol, data, timestamp) VALUES (?, ?, ?)", 94 | [symbol, data, &Utc::now().timestamp().to_string()], 95 | ) 96 | .map_err(|e| format!("Failed to cache data: {}", e))?; 97 | 98 | Ok(()) 99 | } 100 | } 101 | 102 | impl YahooFinanceTool { 103 | async fn run(&self, input: &str) -> Result { 104 | let days = input 105 | .parse::() 106 | .map_err(|_| "Input must be a valid number of days".to_string())?; 107 | 108 | if days <= 0 { 109 | return Err("Number of days must be positive".to_string()); 110 | } 111 | 112 | // Check cache first 113 | if let Some(cached_data) = self.get_cached_data("BTC-USD", days).await? { 114 | return Ok(cached_data); 115 | } 116 | 117 | let provider = 118 | YahooConnector::new().map_err(|e| format!("Failed to create YahooConnector: {}", e))?; 119 | let end = OffsetDateTime::now_utc(); 120 | let start = end - time::Duration::days(days); 121 | 122 | let resp = provider 123 | .get_quote_history("BTC-USD", start, end) 124 | .await 125 | .map_err(|e| format!("Failed to fetch data: {}", e))?; 126 | 127 | let quotes = resp 128 | .quotes() 129 | .map_err(|e| format!("Failed to parse quotes: {}", e))?; 130 | 131 | // Convert quotes to our HistoricalData format 132 | let historical_data: Vec = quotes 133 | .into_iter() 134 | .map(|quote| HistoricalData { 135 | timestamp: quote.timestamp as i64, 136 | open: quote.open, 137 | high: quote.high, 138 | low: quote.low, 139 | close: quote.close, 140 | volume: quote.volume as i64, 141 | }) 142 | .collect(); 143 | 144 | let data = serde_json::to_string(&historical_data) 145 | .map_err(|e| format!("Failed to serialize data: {}", e))?; 146 | 147 | // Cache the fetched data 148 | self.cache_data("BTC-USD", &data).await?; 149 | 150 | Ok(data) 151 | } 152 | 153 | fn schema(&self) -> Option<&ToolSchema> { 154 | Some(&self.schema) 155 | } 156 | } 157 | 158 | #[async_trait] 159 | impl Tool for YahooFinanceTool { 160 | fn name(&self) -> &str { 161 | &self.schema.name 162 | } 163 | 164 | fn description(&self) -> &str { 165 | &self.schema.description 166 | } 167 | 168 | fn schema(&self) -> &ToolSchema { 169 | &self.schema 170 | } 171 | 172 | fn run(&self, input: &str) -> Result { 173 | tokio::runtime::Runtime::new() 174 | .unwrap() 175 | .block_on(self.run(input)) 176 | } 177 | } 178 | 179 | #[cfg(test)] 180 | mod tests { 181 | use super::*; 182 | 183 | #[tokio::test] 184 | async fn test_yahoo_finance_tool_validation() { 185 | let tool = YahooFinanceTool::new(); 186 | 187 | // Test invalid input 188 | let result = tool.run("invalid").await; 189 | assert!(result.is_err()); 190 | 191 | // Test negative days 192 | let result = tool.run("-1").await; 193 | assert!(result.is_err()); 194 | 195 | // Test zero days 196 | let result = tool.run( "0").await; 197 | assert!(result.is_err()); 198 | } 199 | 200 | #[tokio::test] 201 | async fn test_yahoo_finance_tool_schema() { 202 | let tool = YahooFinanceTool::new(); 203 | let schema = tool.schema().unwrap(); 204 | 205 | assert_eq!(schema.name, "yahoo-finance"); 206 | assert!(schema.description.contains("BTC price")); 207 | assert_eq!(schema.parameters.len(), 1); 208 | assert_eq!(schema.parameters[0].name, "days"); 209 | assert_eq!(schema.parameters[0].parameter_type, ParameterType::Integer); 210 | assert!(schema.parameters[0].required); 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /design/api/README.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust API Design 2 | 3 | This directory contains API specifications and interaction patterns: 4 | 5 | ## Contents 6 | 7 | - `agent_api.md`: Agent communication and control APIs 8 | - `swarm_api.md`: Swarm management and orchestration APIs 9 | - `model_api.md`: Language model integration APIs 10 | - `memory_api.md`: Memory system APIs 11 | - `service_api.md`: External service integration APIs 12 | 13 | Each API document includes: 14 | - Endpoint specifications 15 | - Request/response formats 16 | - Authentication requirements 17 | - Error handling patterns 18 | -------------------------------------------------------------------------------- /design/api/storage_integration.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Storage Integration API 2 | 3 | ## Overview 4 | Defines the APIs for integrating storage capabilities with agents and swarms. 5 | 6 | ## Storage Integration 7 | 8 | ### 1. Agent Storage Integration 9 | ```rust 10 | /// Agent storage integration 11 | pub trait AgentStorageIntegration { 12 | /// Initialize storage 13 | async fn init_storage(&mut self, config: AgentStorageConfig) -> Result<(), StorageError>; 14 | 15 | /// Store agent state 16 | async fn store_state(&mut self, state: &AgentState) -> Result<(), StorageError>; 17 | 18 | /// Load agent state 19 | async fn load_state(&self) -> Result; 20 | 21 | /// Store temporary data 22 | async fn store_temp( 23 | &mut self, 24 | key: &str, 25 | data: &[u8], 26 | ttl: Duration, 27 | ) -> Result<(), StorageError>; 28 | 29 | /// Clean temporary data 30 | async fn cleanup_temp(&mut self) -> Result<(), StorageError>; 31 | } 32 | 33 | /// Agent storage configuration 34 | pub struct AgentStorageConfig { 35 | /// Metadata storage settings 36 | metadata: StorageConfig, 37 | /// Configuration storage settings 38 | config: StorageConfig, 39 | /// Temporary storage settings 40 | temp: StorageConfig, 41 | /// Security settings 42 | security: SecurityConfig, 43 | } 44 | ``` 45 | 46 | ### 2. Swarm Storage Integration 47 | ```rust 48 | /// Swarm storage integration 49 | pub trait SwarmStorageIntegration { 50 | /// Initialize storage 51 | async fn init_storage(&mut self, config: SwarmStorageConfig) -> Result<(), StorageError>; 52 | 53 | /// Store swarm state 54 | async fn store_state(&mut self, state: &SwarmState) -> Result<(), StorageError>; 55 | 56 | /// Load swarm state 57 | async fn load_state(&self) -> Result; 58 | 59 | /// Store task data 60 | async fn store_task(&mut self, task: &Task) -> Result<(), StorageError>; 61 | 62 | /// Update metrics 63 | async fn update_metrics(&mut self, metrics: &SwarmMetrics) -> Result<(), StorageError>; 64 | } 65 | 66 | /// Swarm storage configuration 67 | pub struct SwarmStorageConfig { 68 | /// State storage settings 69 | state: StorageConfig, 70 | /// Task storage settings 71 | task: StorageConfig, 72 | /// Metrics storage settings 73 | metrics: StorageConfig, 74 | /// Security settings 75 | security: SecurityConfig, 76 | } 77 | ``` 78 | 79 | ## Usage Patterns 80 | 81 | ### 1. Agent Storage Usage 82 | ```rust 83 | // Initialize agent storage 84 | let storage_config = AgentStorageConfig { 85 | metadata: StorageConfig::new_memory(), 86 | config: StorageConfig::new_file("config"), 87 | temp: StorageConfig::new_memory(), 88 | security: SecurityConfig::default(), 89 | }; 90 | 91 | agent.init_storage(storage_config).await?; 92 | 93 | // Store agent state 94 | let state = agent.current_state(); 95 | agent.store_state(&state).await?; 96 | 97 | // Store temporary data 98 | agent 99 | .store_temp("task_result", &result_data, Duration::from_secs(3600)) 100 | .await?; 101 | ``` 102 | 103 | ### 2. Swarm Storage Usage 104 | ```rust 105 | // Initialize swarm storage 106 | let storage_config = SwarmStorageConfig { 107 | state: StorageConfig::new_persistent("state"), 108 | task: StorageConfig::new_persistent("tasks"), 109 | metrics: StorageConfig::new_memory(), 110 | security: SecurityConfig::with_encryption(), 111 | }; 112 | 113 | swarm.init_storage(storage_config).await?; 114 | 115 | // Store swarm state 116 | let state = swarm.current_state(); 117 | swarm.store_state(&state).await?; 118 | 119 | // Update metrics 120 | let metrics = swarm.collect_metrics(); 121 | swarm.update_metrics(&metrics).await?; 122 | ``` 123 | 124 | ## Error Handling 125 | 126 | ### 1. Storage Errors 127 | ```rust 128 | /// Storage error types 129 | pub enum StorageError { 130 | /// Initialization failed 131 | InitializationError(String), 132 | /// Operation failed 133 | OperationError(String), 134 | /// Data error 135 | DataError(String), 136 | /// Security error 137 | SecurityError(String), 138 | } 139 | 140 | /// Error recovery 141 | pub trait StorageErrorRecovery { 142 | /// Attempt recovery 143 | async fn recover_storage(&mut self, error: &StorageError) -> Result<(), RecoveryError>; 144 | 145 | /// Get recovery policy 146 | fn storage_recovery_policy(&self) -> &RecoveryPolicy; 147 | } 148 | ``` 149 | 150 | ### 2. Recovery Patterns 151 | ```rust 152 | // Implement retry with backoff 153 | async fn retry_operation( 154 | operation: F, 155 | policy: &RetryPolicy, 156 | ) -> Result 157 | where 158 | F: Future>, 159 | { 160 | let mut attempts = 0; 161 | let mut last_error = None; 162 | 163 | while attempts < policy.max_attempts { 164 | match operation.await { 165 | Ok(result) => return Ok(result), 166 | Err(error) => { 167 | last_error = Some(error); 168 | attempts += 1; 169 | if attempts < policy.max_attempts { 170 | sleep(policy.backoff(attempts)).await; 171 | } 172 | } 173 | } 174 | } 175 | 176 | Err(last_error.unwrap()) 177 | } 178 | ``` 179 | 180 | ## Security Integration 181 | 182 | ### 1. Security Configuration 183 | ```rust 184 | /// Security configuration 185 | pub struct SecurityConfig { 186 | /// Encryption settings 187 | encryption: Option, 188 | /// Access control settings 189 | access_control: AccessControlConfig, 190 | /// Audit settings 191 | audit: AuditConfig, 192 | } 193 | 194 | /// Encryption configuration 195 | pub struct EncryptionConfig { 196 | /// Encryption algorithm 197 | algorithm: EncryptionAlgorithm, 198 | /// Key management 199 | key_management: KeyManagementConfig, 200 | /// Rotation policy 201 | rotation_policy: RotationPolicy, 202 | } 203 | ``` 204 | 205 | ### 2. Security Integration 206 | ```rust 207 | /// Security integration 208 | pub trait StorageSecurity { 209 | /// Initialize security 210 | async fn init_security(&mut self, config: SecurityConfig) -> Result<(), SecurityError>; 211 | 212 | /// Encrypt data 213 | async fn encrypt_data(&self, data: &[u8]) -> Result, SecurityError>; 214 | 215 | /// Decrypt data 216 | async fn decrypt_data(&self, data: &[u8]) -> Result, SecurityError>; 217 | 218 | /// Rotate encryption keys 219 | async fn rotate_keys(&mut self) -> Result<(), SecurityError>; 220 | } 221 | ``` 222 | 223 | ## Monitoring Integration 224 | 225 | ### 1. Storage Metrics 226 | ```rust 227 | /// Storage metrics 228 | pub struct StorageMetrics { 229 | /// Operation latencies 230 | latencies: HashMap, 231 | /// Error counts 232 | errors: HashMap, 233 | /// Resource usage 234 | resources: ResourceMetrics, 235 | /// Connection stats 236 | connections: ConnectionMetrics, 237 | } 238 | 239 | /// Monitoring integration 240 | pub trait StorageMonitoring { 241 | /// Collect metrics 242 | fn collect_metrics(&self) -> StorageMetrics; 243 | 244 | /// Report health status 245 | fn health_status(&self) -> HealthStatus; 246 | 247 | /// Get monitoring config 248 | fn monitoring_config(&self) -> &MonitoringConfig; 249 | } 250 | ``` 251 | 252 | ### 2. Alerting Integration 253 | ```rust 254 | /// Alert configuration 255 | pub struct AlertConfig { 256 | /// Alert thresholds 257 | thresholds: HashMap, 258 | /// Alert channels 259 | channels: Vec, 260 | /// Alert policies 261 | policies: AlertPolicies, 262 | } 263 | 264 | /// Alerting integration 265 | pub trait StorageAlerting { 266 | /// Configure alerts 267 | fn configure_alerts(&mut self, config: AlertConfig); 268 | 269 | /// Check alert conditions 270 | fn check_alerts(&self) -> Vec; 271 | 272 | /// Send alerts 273 | async fn send_alerts(&self, alerts: &[Alert]) -> Result<(), AlertError>; 274 | } 275 | ``` 276 | -------------------------------------------------------------------------------- /design/api/swarm_orchestration.md: -------------------------------------------------------------------------------- 1 | # Swarm-Rust Orchestration API 2 | 3 | ## Overview 4 | Defines the APIs for swarm management, task orchestration, and agent coordination. 5 | 6 | ## Task Distribution API 7 | 8 | ### 1. Task Queue Management 9 | ```rust 10 | /// Task queue interface 11 | pub trait TaskQueue { 12 | /// Add task to queue 13 | async fn enqueue_task(&mut self, task: Task) -> Result; 14 | 15 | /// Get next task from queue 16 | async fn dequeue_task(&mut self) -> Result, QueueError>; 17 | 18 | /// Get task status 19 | async fn task_status(&self, task_id: TaskId) -> Result; 20 | 21 | /// Update task status 22 | async fn update_status(&mut self, task_id: TaskId, status: TaskStatus) -> Result<(), QueueError>; 23 | } 24 | 25 | /// Task distribution interface 26 | pub trait TaskDistributor { 27 | /// Distribute task to appropriate agent 28 | async fn distribute_task(&mut self, task: Task) -> Result; 29 | 30 | /// Get task assignment 31 | async fn get_assignment(&self, task_id: TaskId) -> Result, DistributionError>; 32 | 33 | /// Update task assignment 34 | async fn update_assignment( 35 | &mut self, 36 | task_id: TaskId, 37 | agent_id: AgentId, 38 | ) -> Result<(), DistributionError>; 39 | } 40 | ``` 41 | 42 | ### 2. Agent Selection 43 | ```rust 44 | /// Agent selection interface 45 | pub trait AgentSelector { 46 | /// Select agent for task 47 | async fn select_agent( 48 | &self, 49 | task: &Task, 50 | available_agents: &[AgentInfo], 51 | ) -> Result; 52 | 53 | /// Get agent capabilities 54 | fn get_capabilities(&self, agent_id: AgentId) -> Result, SelectionError>; 55 | 56 | /// Check agent availability 57 | async fn check_availability(&self, agent_id: AgentId) -> Result; 58 | } 59 | 60 | /// Load balancing interface 61 | pub trait LoadBalancer { 62 | /// Get agent load metrics 63 | async fn get_load(&self, agent_id: AgentId) -> Result; 64 | 65 | /// Update agent load 66 | async fn update_load( 67 | &mut self, 68 | agent_id: AgentId, 69 | metrics: LoadMetrics, 70 | ) -> Result<(), LoadError>; 71 | 72 | /// Get optimal agent distribution 73 | async fn optimize_distribution(&self) -> Result; 74 | } 75 | ``` 76 | 77 | ## Swarm Management API 78 | 79 | ### 1. Swarm Configuration 80 | ```rust 81 | /// Swarm configuration interface 82 | pub trait SwarmConfig { 83 | /// Update swarm configuration 84 | async fn update_config(&mut self, config: Config) -> Result<(), ConfigError>; 85 | 86 | /// Get current configuration 87 | fn get_config(&self) -> Result; 88 | 89 | /// Validate configuration 90 | fn validate_config(&self, config: &Config) -> Result<(), ConfigError>; 91 | } 92 | 93 | /// Swarm metrics interface 94 | pub trait SwarmMetrics { 95 | /// Collect swarm metrics 96 | async fn collect_metrics(&self) -> Result; 97 | 98 | /// Get agent metrics 99 | async fn agent_metrics(&self, agent_id: AgentId) -> Result; 100 | 101 | /// Get task metrics 102 | async fn task_metrics(&self, task_id: TaskId) -> Result; 103 | } 104 | ``` 105 | 106 | ### 2. Agent Lifecycle 107 | ```rust 108 | /// Agent lifecycle management 109 | pub trait AgentLifecycle { 110 | /// Initialize agent 111 | async fn initialize_agent(&mut self, config: AgentConfig) -> Result; 112 | 113 | /// Start agent 114 | async fn start_agent(&mut self, agent_id: AgentId) -> Result<(), LifecycleError>; 115 | 116 | /// Stop agent 117 | async fn stop_agent(&mut self, agent_id: AgentId) -> Result<(), LifecycleError>; 118 | 119 | /// Remove agent 120 | async fn remove_agent(&mut self, agent_id: AgentId) -> Result<(), LifecycleError>; 121 | } 122 | 123 | /// Health monitoring interface 124 | pub trait HealthMonitor { 125 | /// Check agent health 126 | async fn check_health(&self, agent_id: AgentId) -> Result; 127 | 128 | /// Monitor agent status 129 | async fn monitor_agent(&mut self, agent_id: AgentId) -> Result; 130 | 131 | /// Handle health events 132 | async fn handle_health_event(&mut self, event: HealthEvent) -> Result<(), HealthError>; 133 | } 134 | ``` 135 | 136 | ## State Management API 137 | 138 | ### 1. Shared State 139 | ```rust 140 | /// Shared state interface 141 | pub trait SharedState { 142 | /// Get state value 143 | async fn get_value(&self, key: &str) -> Result, StateError>; 144 | 145 | /// Set state value 146 | async fn set_value(&mut self, key: &str, value: Value) -> Result<(), StateError>; 147 | 148 | /// Delete state value 149 | async fn delete_value(&mut self, key: &str) -> Result<(), StateError>; 150 | 151 | /// Watch state changes 152 | async fn watch_changes(&self, key: &str) -> Result; 153 | } 154 | 155 | /// State synchronization interface 156 | pub trait StateSynchronization { 157 | /// Synchronize state 158 | async fn sync_state(&mut self) -> Result<(), SyncError>; 159 | 160 | /// Resolve conflicts 161 | async fn resolve_conflicts(&mut self, conflicts: Vec) -> Result<(), SyncError>; 162 | 163 | /// Get sync status 164 | async fn sync_status(&self) -> Result; 165 | } 166 | ``` 167 | 168 | ### 2. Context Management 169 | ```rust 170 | /// Context management interface 171 | pub trait ContextManager { 172 | /// Get task context 173 | async fn get_context(&self, task_id: TaskId) -> Result; 174 | 175 | /// Update context 176 | async fn update_context( 177 | &mut self, 178 | task_id: TaskId, 179 | context: Context, 180 | ) -> Result<(), ContextError>; 181 | 182 | /// Share context 183 | async fn share_context( 184 | &mut self, 185 | from_task: TaskId, 186 | to_task: TaskId, 187 | ) -> Result<(), ContextError>; 188 | } 189 | 190 | /// History tracking interface 191 | pub trait HistoryTracker { 192 | /// Record event 193 | async fn record_event(&mut self, event: HistoryEvent) -> Result<(), HistoryError>; 194 | 195 | /// Get event history 196 | async fn get_history(&self, filter: HistoryFilter) -> Result, HistoryError>; 197 | 198 | /// Clear history 199 | async fn clear_history(&mut self) -> Result<(), HistoryError>; 200 | } 201 | ``` 202 | 203 | ## Error Handling 204 | 205 | ### 1. Task Errors 206 | ```rust 207 | /// Task error types 208 | pub enum TaskError { 209 | /// Queue operation failed 210 | QueueError(String), 211 | /// Distribution failed 212 | DistributionError(String), 213 | /// Agent selection failed 214 | SelectionError(String), 215 | /// Load balancing failed 216 | LoadError(String), 217 | } 218 | ``` 219 | 220 | ### 2. Management Errors 221 | ```rust 222 | /// Management error types 223 | pub enum ManagementError { 224 | /// Configuration error 225 | ConfigError(String), 226 | /// Lifecycle error 227 | LifecycleError(String), 228 | /// Health monitoring error 229 | HealthError(String), 230 | /// Metrics collection error 231 | MetricsError(String), 232 | } 233 | ``` 234 | 235 | ## Usage Examples 236 | 237 | ### 1. Task Distribution 238 | ```rust 239 | // 1. Initialize components 240 | let queue = TaskQueue::new(config); 241 | let distributor = TaskDistributor::new(selector, balancer); 242 | 243 | // 2. Enqueue task 244 | let task_id = queue.enqueue_task(task).await?; 245 | 246 | // 3. Select and assign agent 247 | let agent_id = distributor.distribute_task(task).await?; 248 | 249 | // 4. Monitor execution 250 | queue.update_status(task_id, TaskStatus::InProgress).await?; 251 | monitor_execution(task_id, agent_id).await?; 252 | ``` 253 | 254 | ### 2. Agent Management 255 | ```rust 256 | // 1. Initialize agent 257 | let agent_id = lifecycle.initialize_agent(config).await?; 258 | 259 | // 2. Start monitoring 260 | let status_stream = monitor.monitor_agent(agent_id).await?; 261 | 262 | // 3. Handle health events 263 | while let Some(event) = status_stream.next().await { 264 | monitor.handle_health_event(event).await?; 265 | } 266 | 267 | // 4. Cleanup on shutdown 268 | lifecycle.stop_agent(agent_id).await?; 269 | lifecycle.remove_agent(agent_id).await?; 270 | ``` 271 | -------------------------------------------------------------------------------- /design/diagrams/README.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust System Diagrams 2 | 3 | This directory contains visual representations of system architecture: 4 | 5 | ## Diagram Types 6 | 7 | - `component_diagram.md`: System component relationships 8 | - `sequence_diagrams.md`: Interaction sequences 9 | - `state_diagrams.md`: Component state transitions 10 | - `deployment_diagram.md`: System deployment architecture 11 | 12 | Each diagram document includes: 13 | - Visual representation 14 | - Detailed description 15 | - Component relationships 16 | - Implementation notes 17 | -------------------------------------------------------------------------------- /design/diagrams/component_diagram.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Component Relationships 2 | 3 | ## System Components 4 | ```mermaid 5 | graph TB 6 | subgraph Tools 7 | BT[Blockchain Tool] 8 | HT[HTTP Tool] 9 | FT[File Tool] 10 | CT[Code Tool] 11 | DT[Data Tool] 12 | end 13 | 14 | subgraph Agents 15 | A[Agent] --> AS[Agent Storage] 16 | A --> AM[Agent Memory] 17 | A --> AI[Agent Identity] 18 | end 19 | 20 | A --> BT 21 | A --> HT 22 | A --> FT 23 | A --> CT 24 | A --> DT 25 | 26 | subgraph Swarms 27 | S[Swarm] --> SB[Swarm Brain] 28 | S --> SS[Swarm Storage] 29 | S --> SM[Swarm Memory] 30 | S --> SC[Swarm Consensus] 31 | end 32 | 33 | subgraph Storage 34 | KV[Key-Value Store] 35 | RS[Relational Store] 36 | FS[File Store] 37 | BC[Blockchain Ledger] 38 | AS --> KV 39 | AS --> FS 40 | SS --> RS 41 | SS --> KV 42 | SS --> BC 43 | end 44 | 45 | subgraph Memory 46 | VM[Vector Memory] 47 | CM[Context Memory] 48 | TM[Task Memory] 49 | OC[On-Chain State] 50 | AM --> VM 51 | AM --> CM 52 | SM --> TM 53 | SM --> VM 54 | SM --> OC 55 | end 56 | 57 | subgraph Models 58 | LM[Language Models] 59 | EM[Embedding Models] 60 | SB --> LM 61 | VM --> EM 62 | end 63 | 64 | subgraph Identity 65 | subgraph Wallet 66 | W[Wallet Core] 67 | KM[Key Management] 68 | PS[Permission System] 69 | CV[Contract Verifier] 70 | SG[Signature Generator] 71 | 72 | W --> KM 73 | W --> PS 74 | W --> CV 75 | W --> SG 76 | end 77 | 78 | AI --> W 79 | SC --> W 80 | 81 | W --> BC[Blockchain] 82 | W --> VS[Verification Service] 83 | end 84 | 85 | A --> S 86 | S --> A 87 | ``` 88 | 89 | ## Wallet Component Details 90 | 91 | ### Core Components 92 | 1. Wallet Core 93 | - Identity management 94 | - Address generation 95 | - Transaction handling 96 | - State management 97 | 98 | 2. Key Management 99 | - Private key storage 100 | - Key rotation 101 | - Backup/recovery 102 | - Access control 103 | 104 | 3. Permission System 105 | - Operation authorization 106 | - Role management 107 | - Access policies 108 | - Threshold controls 109 | 110 | 4. Contract Verifier 111 | - Code analysis 112 | - Risk assessment 113 | - Safety verification 114 | - Interaction validation 115 | 116 | 5. Signature Generator 117 | - Message signing 118 | - Transaction signing 119 | - Signature verification 120 | - Format handling 121 | 122 | ### External Integrations 123 | 1. Blockchain 124 | - Transaction submission 125 | - State queries 126 | - Event monitoring 127 | - Network selection 128 | 129 | 2. Verification Service 130 | - Identity verification 131 | - Signature validation 132 | - Chain validation 133 | - Trust anchoring 134 | 135 | ### Integration Points 136 | 1. Agent Integration 137 | - Identity verification 138 | - Operation signing 139 | - State management 140 | - Permission checks 141 | 142 | 2. Swarm Integration 143 | - Consensus signing 144 | - Multi-sig operations 145 | - Vote collection 146 | - Result verification 147 | 148 | ## Component Details 149 | 150 | ### Agent Components 151 | - Agent: Core agent implementation 152 | - Agent Tools: Task processing capabilities 153 | - Agent Storage: Local data management 154 | - Agent Memory: Context and history 155 | - Agent Identity: Blockchain verification 156 | 157 | ### Swarm Components 158 | - Swarm: Orchestration layer 159 | - Swarm Brain: Decision making 160 | - Swarm Storage: Shared state 161 | - Swarm Memory: Collective memory 162 | - Swarm Consensus: Agreement protocols 163 | 164 | ### Storage Components 165 | - Key-Value Store: Configuration/metadata 166 | - Relational Store: Structured data 167 | - File Store: Temporary/large data 168 | - Blockchain Ledger: Immutable transaction/state history 169 | 170 | ### Memory Components 171 | - Vector Memory: Embeddings storage 172 | - Context Memory: Interaction history 173 | - Task Memory: Processing state 174 | - On-Chain State: Active blockchain state/memory 175 | 176 | ### Model Components 177 | - Language Models: Text generation 178 | - Embedding Models: Vector encoding 179 | 180 | ### Tool Components 181 | - Blockchain Tool: Chain interaction and state management 182 | - HTTP Tool: External service communication 183 | - RPC Tool: Remote procedure calls 184 | - File Tool: File system operations 185 | - Code Tool: Code execution and analysis 186 | - Data Tool: Data processing and transformation 187 | 188 | ### Identity Components 189 | - Wallet: Blockchain identity 190 | - Signature verification 191 | - Message authentication 192 | 193 | ### Tool Integration 194 | 1. Core Tools 195 | - Blockchain: Chain interaction and verification 196 | - HTTP/RPC: Service communication 197 | - File System: Data persistence 198 | - Code Execution: Task processing 199 | - Data Processing: Analysis and transformation 200 | 201 | 2. Tool Management 202 | - Tool registration 203 | - Capability discovery 204 | - Access control 205 | - Resource management 206 | - Error handling 207 | 208 | 3. Tool Integration Points 209 | - Agent tool usage 210 | - Swarm tool coordination 211 | - Cross-tool communication 212 | - Resource sharing 213 | -------------------------------------------------------------------------------- /design/diagrams/deployment_diagram.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Deployment Architecture 2 | 3 | ## Deployment Patterns 4 | 5 | ### 1. Embedded Deployment 6 | ```mermaid 7 | graph TB 8 | subgraph Client Applications 9 | CLI[CLI Tools] 10 | SDK[SDK Integration] 11 | API[HTTP API] 12 | end 13 | 14 | subgraph Swarm 15 | subgraph Internal Components 16 | SO[Swarm Orchestrator] 17 | SB[Swarm Brain] 18 | SC[Swarm Consensus] 19 | DB1[Local Storage] 20 | end 21 | 22 | subgraph Embedded Agents 23 | EA1[Agent 1] 24 | EA2[Agent 2] 25 | EA3[Agent 3] 26 | end 27 | end 28 | 29 | subgraph External Services 30 | LLM[Language Models] 31 | BC[Blockchain] 32 | ES[External Services] 33 | end 34 | 35 | CLI --> API 36 | SDK --> API 37 | API --> SO 38 | 39 | SO --> EA1 40 | SO --> EA2 41 | SO --> EA3 42 | 43 | EA1 --> DB1 44 | EA2 --> DB1 45 | EA3 --> DB1 46 | 47 | EA1 --> ES 48 | EA2 --> ES 49 | EA3 --> ES 50 | 51 | EA1 --> LLM 52 | EA2 --> LLM 53 | EA3 --> LLM 54 | 55 | EA1 --> BC 56 | EA2 --> BC 57 | EA3 --> BC 58 | 59 | SB --> LLM 60 | SC --> BC 61 | ``` 62 | 63 | ### 2. Service-Based Deployment 64 | ```mermaid 65 | graph TB 66 | subgraph Client Applications 67 | CLI[CLI Tools] 68 | SDK[SDK Integration] 69 | API[HTTP API] 70 | end 71 | 72 | subgraph Swarm Service 73 | subgraph Swarm Components 74 | SO[Swarm Orchestrator] 75 | SB[Swarm Brain] 76 | SC[Swarm Consensus] 77 | DB1[Local Storage] 78 | end 79 | end 80 | 81 | subgraph Agent Services 82 | subgraph Agent Service 1 83 | AS1[Agent Service] 84 | DB2[Local Storage] 85 | end 86 | 87 | subgraph Agent Service 2 88 | AS2[Agent Service] 89 | DB3[Local Storage] 90 | end 91 | end 92 | 93 | subgraph External Services 94 | LLM[Language Models] 95 | BC[Blockchain] 96 | ES[External Services] 97 | end 98 | 99 | CLI --> API 100 | SDK --> API 101 | API --> SO 102 | 103 | SO --> AS1 104 | SO --> AS2 105 | 106 | AS1 --> DB2 107 | AS2 --> DB3 108 | SO --> DB1 109 | 110 | AS1 --> ES 111 | AS2 --> ES 112 | 113 | AS1 --> LLM 114 | AS2 --> LLM 115 | 116 | AS1 --> BC 117 | AS2 --> BC 118 | 119 | SB --> LLM 120 | SC --> BC 121 | 122 | subgraph Service Access Methods 123 | HTTP[HTTP REST API] 124 | RPC[RPC Service] 125 | 126 | SO --> HTTP 127 | SO --> RPC 128 | HTTP --> AS1 129 | HTTP --> AS2 130 | RPC --> AS1 131 | RPC --> AS2 132 | end 133 | 134 | SO --- note1["Orchestrator invokes agents via:
- HTTP REST endpoints
- RPC service endpoints
Each agent can support one or both"] 135 | ``` 136 | 137 | ### 3. Hybrid Deployment 138 | ```mermaid 139 | graph TB 140 | subgraph Client Applications 141 | CLI[CLI Tools] 142 | SDK[SDK Integration] 143 | API[HTTP API] 144 | end 145 | 146 | subgraph Swarm 147 | subgraph Swarm Components 148 | SO[Swarm Orchestrator] 149 | SB[Swarm Brain] 150 | SC[Swarm Consensus] 151 | DB1[Local Storage] 152 | end 153 | 154 | subgraph Embedded Agents 155 | EA1[Agent 1] 156 | EA2[Agent 2] 157 | end 158 | end 159 | 160 | subgraph External Agent Services 161 | subgraph Agent Service 1 162 | AS1[Agent Service] 163 | DB2[Local Storage] 164 | end 165 | end 166 | 167 | subgraph External Services 168 | LLM[Language Models] 169 | BC[Blockchain] 170 | ES[External Services] 171 | end 172 | 173 | CLI --> API 174 | SDK --> API 175 | API --> SO 176 | 177 | SO --> EA1 178 | SO --> EA2 179 | SO --> AS1 180 | 181 | EA1 --> DB1 182 | EA2 --> DB1 183 | AS1 --> DB2 184 | 185 | EA1 --> ES 186 | EA2 --> ES 187 | AS1 --> ES 188 | 189 | EA1 --> LLM 190 | EA2 --> LLM 191 | AS1 --> LLM 192 | 193 | EA1 --> BC 194 | EA2 --> BC 195 | AS1 --> BC 196 | 197 | SB --> LLM 198 | SC --> BC 199 | 200 | EA1 ---|"Note"| EmbeddedAgentsNote 201 | EmbeddedAgentsNote[Note: Embedded agents are called directly as callbacks by the orchestrator] 202 | 203 | AS1 ---|"Note"| ServiceAgentsNote 204 | ServiceAgentsNote[Note: Service agents support both HTTP REST endpoints and RPC service endpoints] 205 | 206 | 207 | subgraph Service Access Methods 208 | HTTP[HTTP REST API] 209 | RPC[RPC Service] 210 | 211 | SO --> HTTP 212 | SO --> RPC 213 | HTTP --> AS1 214 | RPC --> AS1 215 | end note 216 | ``` 217 | 218 | ## Deployment Details 219 | 220 | ### Client Layer 221 | - CLI Tools: Command-line interface 222 | - SDK Integration: Library integration 223 | - HTTP API: RESTful interface 224 | 225 | ### Core Services 226 | 1. Swarm Service 227 | - Orchestrator: Task management 228 | - Brain: Decision making 229 | - Consensus: Agreement protocols 230 | 231 | 2. Agent Service 232 | - Manager: Agent lifecycle 233 | - Pool: Agent instances 234 | - Tools: Processing capabilities 235 | 236 | 3. Storage Services 237 | - Key-Value: Fast access 238 | - Relational: Structured data 239 | - File: Large objects 240 | - Blockchain: Immutable ledger storage 241 | 242 | 4. Memory Service 243 | - Vector: Embeddings 244 | - Context: History 245 | - Metadata: System data 246 | 247 | ### External Services 248 | - Language Models: AI processing 249 | - Blockchain: Identity/verification 250 | - External Services: Integration points 251 | 252 | ## Scaling and Availability 253 | 254 | ### Atomic Unit Scaling 255 | ```mermaid 256 | graph TB 257 | subgraph Gateway 258 | GLB[Gateway LB] 259 | end 260 | 261 | subgraph Swarm Unit 1 262 | subgraph S1[Swarm Instance 1] 263 | SO1[Orchestrator] 264 | LB1[Load Balancer] 265 | DB1[Storage] 266 | 267 | subgraph Agents 1 268 | A11[Agent 1] 269 | A12[Agent 2] 270 | end 271 | end 272 | end 273 | 274 | subgraph Swarm Unit 2 275 | subgraph S2[Swarm Instance 2] 276 | SO2[Orchestrator] 277 | LB2[Load Balancer] 278 | DB2[Storage] 279 | 280 | subgraph Agents 2 281 | A21[Agent 1] 282 | A22[Agent 2] 283 | end 284 | end 285 | end 286 | 287 | GLB --> LB1 288 | GLB --> LB2 289 | 290 | LB1 --> SO1 291 | SO1 --> A11 292 | SO1 --> A12 293 | A11 --> DB1 294 | A12 --> DB1 295 | 296 | LB2 --> SO2 297 | SO2 --> A21 298 | SO2 --> A22 299 | A21 --> DB2 300 | A22 --> DB2 301 | ``` 302 | 303 | ### High Availability with Atomic Units 304 | ```mermaid 305 | graph TB 306 | subgraph Primary Region 307 | subgraph P_Swarm[Primary Swarm] 308 | P_LB[Load Balancer] 309 | P_O[Orchestrator] 310 | P_DB[Storage] 311 | 312 | subgraph P_Agents[Agents] 313 | PA1[Agent 1] 314 | PA2[Agent 2] 315 | end 316 | end 317 | end 318 | 319 | subgraph Backup Region 320 | subgraph B_Swarm[Backup Swarm] 321 | B_LB[Load Balancer] 322 | B_O[Orchestrator] 323 | B_DB[Storage] 324 | 325 | subgraph B_Agents[Agents] 326 | BA1[Agent 1] 327 | BA2[Agent 2] 328 | end 329 | end 330 | end 331 | 332 | P_LB --> P_O 333 | P_O --> PA1 334 | P_O --> PA2 335 | PA1 --> P_DB 336 | PA2 --> P_DB 337 | P_DB --> B_DB 338 | 339 | B_LB --> B_O 340 | B_O --> BA1 341 | B_O --> BA2 342 | BA1 --> B_DB 343 | BA2 --> B_DB 344 | ``` 345 | -------------------------------------------------------------------------------- /design/diagrams/state_diagrams.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust State Transitions 2 | 3 | ## Agent States 4 | ```mermaid 5 | stateDiagram-v2 6 | [*] --> Initializing 7 | Initializing --> Ready: Storage/Memory Ready 8 | Ready --> Processing: Receive Task 9 | Processing --> Verifying: Task Complete 10 | Verifying --> Ready: Verification Success 11 | Verifying --> Failed: Verification Failed 12 | Processing --> Failed: Processing Error 13 | Failed --> Ready: Recovery Success 14 | Failed --> [*]: Unrecoverable 15 | ``` 16 | 17 | ## Swarm States 18 | ```mermaid 19 | stateDiagram-v2 20 | [*] --> Initializing 21 | 22 | state Initializing { 23 | [*] --> AgentDiscovery: Start Discovery 24 | 25 | state AgentDiscovery { 26 | [*] --> DetectingAgents 27 | DetectingAgents --> RangingAgents: Agents Found 28 | RangingAgents --> OrderingAgents: Capabilities Known 29 | OrderingAgents --> AgentsDetected: Order Established 30 | 31 | DetectingAgents --> DetectingAgents: New Agent Found 32 | RangingAgents --> DetectingAgents: Insufficient Capabilities 33 | OrderingAgents --> RangingAgents: Invalid Order 34 | } 35 | 36 | AgentDiscovery --> GroupFormation: Agents Detected 37 | 38 | state GroupFormation { 39 | [*] --> ValidatingGroup 40 | ValidatingGroup --> AssigningRoles: Group Size Valid 41 | AssigningRoles --> GroupValidated: Roles Assigned 42 | 43 | ValidatingGroup --> ValidatingGroup: Check Requirements 44 | AssigningRoles --> ValidatingGroup: Missing Capabilities 45 | } 46 | 47 | GroupFormation --> OrchestrationSetup: Group Validated 48 | 49 | state OrchestrationSetup { 50 | [*] --> ConfiguringAgents 51 | ConfiguringAgents --> EstablishingConnections: Agents Configured 52 | EstablishingConnections --> SetupComplete: Connections Ready 53 | 54 | ConfiguringAgents --> ConfiguringAgents: Update Config 55 | EstablishingConnections --> ConfiguringAgents: Connection Failed 56 | } 57 | 58 | OrchestrationSetup --> ReadinessCheck: Setup Complete 59 | 60 | state ReadinessCheck { 61 | [*] --> VerifyingMinimalGroup 62 | VerifyingMinimalGroup --> CheckingCapabilities: Group Size Valid 63 | CheckingCapabilities --> ReadinessVerified: Required Capabilities Present 64 | 65 | VerifyingMinimalGroup --> VerifyingMinimalGroup: Wait for Agents 66 | CheckingCapabilities --> VerifyingMinimalGroup: Missing Requirements 67 | } 68 | } 69 | 70 | Initializing --> Ready: Minimal Group Ready 71 | 72 | state Ready { 73 | [*] --> Idle 74 | Idle --> TaskValidation: Task Received 75 | TaskValidation --> AgentSelection: Task Valid 76 | AgentSelection --> [*]: Agents Selected 77 | } 78 | 79 | Ready --> Distributing: New Task 80 | Distributing --> Processing: Task Assigned 81 | Processing --> ConsensusBuilding: Results Ready 82 | ConsensusBuilding --> Completing: Consensus Reached 83 | ConsensusBuilding --> Retrying: No Consensus 84 | Completing --> Ready: Task Complete 85 | Retrying --> Distributing: Retry Task 86 | 87 | state Processing { 88 | [*] --> AgentExecution 89 | AgentExecution --> ResultCollection: Execution Complete 90 | ResultCollection --> ValidationCheck: Results Collected 91 | ValidationCheck --> [*]: Results Valid 92 | 93 | AgentExecution --> AgentFailure: Execution Error 94 | ValidationCheck --> AgentExecution: Invalid Results 95 | } 96 | 97 | Processing --> Failed: Agent Failure 98 | Failed --> Ready: Recovery Success 99 | Failed --> Initializing: Rebuild Required 100 | 101 | note right of Initializing 102 | Swarm ensures minimal viable 103 | agent group before proceeding 104 | end note 105 | 106 | note right of Ready 107 | Requires configured number 108 | of capable agents 109 | end note 110 | 111 | note right of Processing 112 | Monitors agent health and 113 | execution progress 114 | end note 115 | ``` 116 | 117 | ## Storage States 118 | ```mermaid 119 | stateDiagram-v2 120 | [*] --> Initializing 121 | Initializing --> Ready: Connection Success 122 | Ready --> Writing: Write Request 123 | Ready --> Reading: Read Request 124 | Writing --> Verifying: Write Complete 125 | Reading --> Processing: Data Retrieved 126 | Verifying --> Ready: Verification Success 127 | Processing --> Ready: Processing Complete 128 | Writing --> Failed: Write Error 129 | Reading --> Failed: Read Error 130 | Failed --> Ready: Recovery Success 131 | ``` 132 | 133 | ## Consensus States 134 | ```mermaid 135 | stateDiagram-v2 136 | [*] --> Initializing 137 | Initializing --> Collecting: Start Voting 138 | Collecting --> Processing: All Votes In 139 | Collecting --> Timeout: Vote Timeout 140 | Processing --> Resolved: Consensus Reached 141 | Processing --> Deadlock: No Consensus 142 | Timeout --> Retry: Can Retry 143 | Deadlock --> Retry: Can Retry 144 | Retry --> Collecting: New Round 145 | Resolved --> [*]: Complete 146 | ``` 147 | -------------------------------------------------------------------------------- /design/interfaces/README.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Conceptual Interfaces 2 | 3 | This directory contains the virtual interface definitions for core system components: 4 | 5 | ## Components 6 | 7 | - `task.md`: Task definition and lifecycle 8 | - `agent.md`: Agent capabilities and responsibilities 9 | - `swarm.md`: Swarm orchestration and management 10 | - `models.md`: Language model integration interfaces 11 | - `memory.md`: Memory system interfaces 12 | 13 | Each interface document defines: 14 | - Core traits and methods 15 | - Component responsibilities 16 | - Interaction patterns 17 | - Implementation requirements 18 | -------------------------------------------------------------------------------- /design/interfaces/memory.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Memory Interface 2 | 3 | ## Overview 4 | Defines the memory system interfaces for context management and persistence. 5 | 6 | ## Core Traits 7 | 8 | ```rust 9 | /// Core memory system capabilities 10 | pub trait Memory: Send + Sync { 11 | /// Store data in memory 12 | async fn store(&mut self, key: &str, data: &MemoryData) -> Result<(), MemoryError>; 13 | 14 | /// Retrieve data from memory 15 | async fn retrieve(&self, key: &str) -> Result, MemoryError>; 16 | 17 | /// Search memory by similarity 18 | async fn search(&self, query: &str, limit: usize) -> Result, MemoryError>; 19 | 20 | /// Delete data from memory 21 | async fn delete(&mut self, key: &str) -> Result<(), MemoryError>; 22 | 23 | /// Clear all memory 24 | async fn clear(&mut self) -> Result<(), MemoryError>; 25 | } 26 | 27 | /// Vector store capabilities 28 | pub trait VectorStore: Send + Sync { 29 | /// Store vector embeddings 30 | async fn store_vectors( 31 | &mut self, 32 | vectors: &[Vector], 33 | metadata: &[Metadata], 34 | ) -> Result<(), StoreError>; 35 | 36 | /// Query similar vectors 37 | async fn query_vectors( 38 | &self, 39 | query: &Vector, 40 | limit: usize, 41 | ) -> Result, StoreError>; 42 | 43 | /// Delete vectors 44 | async fn delete_vectors(&mut self, ids: &[VectorId]) -> Result<(), StoreError>; 45 | } 46 | 47 | /// Memory data structure 48 | pub struct MemoryData { 49 | /// Content to store 50 | content: String, 51 | /// Vector embedding 52 | embedding: Option>, 53 | /// Associated metadata 54 | metadata: Metadata, 55 | /// Storage timestamp 56 | timestamp: DateTime, 57 | } 58 | 59 | /// Memory match result 60 | pub struct MemoryMatch { 61 | /// Matched memory data 62 | data: MemoryData, 63 | /// Similarity score 64 | score: f32, 65 | /// Match metadata 66 | metadata: Metadata, 67 | } 68 | 69 | /// Memory configuration 70 | pub struct MemoryConfig { 71 | /// Storage backend 72 | backend: StorageBackend, 73 | /// Vector dimensions 74 | vector_dimensions: usize, 75 | /// Index configuration 76 | index_config: IndexConfig, 77 | /// Cache configuration 78 | cache_config: Option, 79 | } 80 | 81 | /// Storage backend 82 | pub enum StorageBackend { 83 | InMemory, 84 | Persistent(PersistentConfig), 85 | Distributed(DistributedConfig), 86 | Custom(Box), 87 | } 88 | ``` 89 | 90 | ## Responsibilities 91 | 92 | 1. Data Management 93 | - Storage operations 94 | - Retrieval operations 95 | - Deletion handling 96 | - Data validation 97 | 98 | 2. Vector Operations 99 | - Embedding storage 100 | - Similarity search 101 | - Index management 102 | - Optimization 103 | 104 | 3. Persistence 105 | - Data durability 106 | - Backup management 107 | - Recovery handling 108 | - Consistency 109 | 110 | 4. Performance 111 | - Caching strategy 112 | - Query optimization 113 | - Resource efficiency 114 | - Scalability 115 | 116 | ## Implementation Requirements 117 | 118 | 1. Concurrency 119 | - Thread-safe operations 120 | - Concurrent access 121 | - Lock management 122 | - Transaction support 123 | 124 | 2. Persistence 125 | - Durable storage 126 | - Crash recovery 127 | - Backup/restore 128 | - Data integrity 129 | 130 | 3. Performance 131 | - Efficient indexing 132 | - Query optimization 133 | - Cache management 134 | - Resource limits 135 | 136 | 4. Scalability 137 | - Horizontal scaling 138 | - Sharding support 139 | - Load balancing 140 | - Replication 141 | 142 | ## Usage Patterns 143 | 144 | 1. Memory Creation 145 | ```rust 146 | let memory = Memory::new(config)?; 147 | memory.initialize().await?; 148 | ``` 149 | 150 | 2. Data Storage 151 | ```rust 152 | let data = MemoryData::new(content, embedding, metadata); 153 | memory.store("key", &data).await?; 154 | ``` 155 | 156 | 3. Similarity Search 157 | ```rust 158 | let matches = memory.search(query, 10).await?; 159 | process_matches(matches); 160 | ``` 161 | 162 | 4. Vector Operations 163 | ```rust 164 | let store = VectorStore::new(config)?; 165 | store.store_vectors(&vectors, &metadata).await?; 166 | let similar = store.query_vectors(&query, 5).await?; 167 | ``` 168 | -------------------------------------------------------------------------------- /design/interfaces/models.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Models Interface 2 | 3 | ## Overview 4 | Defines the language model integration interfaces and provider abstractions. 5 | 6 | ## Core Traits 7 | 8 | ```rust 9 | /// Core language model capabilities 10 | pub trait LanguageModel: Send + Sync { 11 | /// Generate text completion 12 | async fn generate(&self, prompt: &str) -> Result; 13 | 14 | /// Generate embeddings 15 | async fn embed(&self, text: &str) -> Result, ModelError>; 16 | 17 | /// Get model configuration 18 | fn config(&self) -> &ModelConfig; 19 | 20 | /// Update model configuration 21 | fn update_config(&mut self, config: ModelConfig) -> Result<(), ModelError>; 22 | } 23 | 24 | /// Model provider capabilities 25 | pub trait ModelProvider: Send + Sync { 26 | /// Create new model instance 27 | fn create_model(&self, config: ModelConfig) -> Result, ModelError>; 28 | 29 | /// List available models 30 | fn available_models(&self) -> Result, ModelError>; 31 | 32 | /// Get provider metrics 33 | fn metrics(&self) -> Result; 34 | } 35 | 36 | /// Model configuration 37 | pub struct ModelConfig { 38 | /// Model identifier 39 | model_id: String, 40 | /// Temperature setting 41 | temperature: f32, 42 | /// Maximum tokens 43 | max_tokens: usize, 44 | /// Stop sequences 45 | stop_sequences: Vec, 46 | /// Sampling parameters 47 | sampling_params: SamplingParams, 48 | /// Response format 49 | response_format: ResponseFormat, 50 | } 51 | 52 | /// Model information 53 | pub struct ModelInfo { 54 | /// Model identifier 55 | id: String, 56 | /// Model capabilities 57 | capabilities: Vec, 58 | /// Context window size 59 | context_size: usize, 60 | /// Token limit 61 | token_limit: usize, 62 | /// Pricing information 63 | pricing: Option, 64 | } 65 | 66 | /// Model capabilities 67 | pub enum ModelCapability { 68 | TextCompletion, 69 | ChatCompletion, 70 | Embeddings, 71 | CodeGeneration, 72 | ImageGeneration, 73 | Custom(String), 74 | } 75 | 76 | /// Response format 77 | pub enum ResponseFormat { 78 | Text, 79 | Json, 80 | MessageArray, 81 | Custom(String), 82 | } 83 | ``` 84 | 85 | ## Responsibilities 86 | 87 | 1. Text Generation 88 | - Prompt processing 89 | - Response generation 90 | - Parameter handling 91 | - Error management 92 | 93 | 2. Model Management 94 | - Configuration 95 | - Instance creation 96 | - Capability checking 97 | - Resource management 98 | 99 | 3. Provider Integration 100 | - API abstraction 101 | - Authentication 102 | - Rate limiting 103 | - Error handling 104 | 105 | 4. Performance Monitoring 106 | - Token counting 107 | - Usage tracking 108 | - Error reporting 109 | - Latency monitoring 110 | 111 | ## Implementation Requirements 112 | 113 | 1. Concurrency 114 | - Thread-safe operations 115 | - Async request handling 116 | - Request batching 117 | - Connection pooling 118 | 119 | 2. Error Handling 120 | - API errors 121 | - Rate limits 122 | - Timeouts 123 | - Invalid responses 124 | 125 | 3. Resource Management 126 | - Token budgeting 127 | - Request throttling 128 | - Connection pooling 129 | - Cache management 130 | 131 | 4. Security 132 | - API key management 133 | - Request validation 134 | - Response sanitization 135 | - Access control 136 | 137 | ## Usage Patterns 138 | 139 | 1. Model Creation 140 | ```rust 141 | let provider = OpenAIProvider::new(credentials); 142 | let model = provider.create_model(config)?; 143 | ``` 144 | 145 | 2. Text Generation 146 | ```rust 147 | let response = model.generate(prompt).await?; 148 | process_response(response); 149 | ``` 150 | 151 | 3. Embedding Generation 152 | ```rust 153 | let embeddings = model.embed(text).await?; 154 | store_embeddings(embeddings); 155 | ``` 156 | 157 | 4. Model Selection 158 | ```rust 159 | let models = provider.available_models()?; 160 | let suitable_model = select_model(models, requirements); 161 | ``` 162 | -------------------------------------------------------------------------------- /design/interfaces/storage.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Storage Interface 2 | 3 | ## Overview 4 | Defines the storage capabilities for agents and swarms to manage metadata, configuration, and temporary data. 5 | 6 | ## Core Traits 7 | 8 | ```rust 9 | /// Core storage capabilities 10 | pub trait Storage: Send + Sync { 11 | /// Store data with key 12 | async fn set(&mut self, key: &str, value: &StorageValue) -> Result<(), StorageError>; 13 | 14 | /// Retrieve data by key 15 | async fn get(&self, key: &str) -> Result, StorageError>; 16 | 17 | /// Delete data by key 18 | async fn delete(&mut self, key: &str) -> Result<(), StorageError>; 19 | 20 | /// Check if key exists 21 | async fn exists(&self, key: &str) -> Result; 22 | 23 | /// List all keys with optional prefix 24 | async fn list_keys(&self, prefix: Option<&str>) -> Result, StorageError>; 25 | 26 | /// Clear all data 27 | async fn clear(&mut self) -> Result<(), StorageError>; 28 | } 29 | 30 | /// Key-value storage implementation 31 | pub trait KeyValueStorage: Storage { 32 | /// Atomic increment 33 | async fn increment(&mut self, key: &str, amount: i64) -> Result; 34 | 35 | /// Set with expiration 36 | async fn set_ex( 37 | &mut self, 38 | key: &str, 39 | value: &StorageValue, 40 | expiry: Duration, 41 | ) -> Result<(), StorageError>; 42 | 43 | /// Get time-to-live for key 44 | async fn ttl(&self, key: &str) -> Result, StorageError>; 45 | } 46 | 47 | /// Relational storage capabilities 48 | pub trait RelationalStorage: Storage { 49 | /// Execute query 50 | async fn query( 51 | &self, 52 | query: &str, 53 | params: &[QueryParam], 54 | ) -> Result; 55 | 56 | /// Begin transaction 57 | async fn begin_transaction(&mut self) -> Result; 58 | 59 | /// Get schema information 60 | fn schema(&self) -> &StorageSchema; 61 | 62 | /// Migrate schema 63 | async fn migrate(&mut self, migrations: &[Migration]) -> Result<(), StorageError>; 64 | } 65 | 66 | /// File storage capabilities 67 | pub trait FileStorage: Storage { 68 | /// Write file 69 | async fn write_file( 70 | &mut self, 71 | path: &str, 72 | content: &[u8], 73 | ) -> Result<(), StorageError>; 74 | 75 | /// Read file 76 | async fn read_file(&self, path: &str) -> Result, StorageError>; 77 | 78 | /// Delete file 79 | async fn delete_file(&mut self, path: &str) -> Result<(), StorageError>; 80 | 81 | /// List files in directory 82 | async fn list_files( 83 | &self, 84 | directory: &str, 85 | ) -> Result, StorageError>; 86 | } 87 | 88 | /// Storage value types 89 | #[derive(Debug, Clone, Serialize, Deserialize)] 90 | pub enum StorageValue { 91 | /// String value 92 | String(String), 93 | /// Integer value 94 | Integer(i64), 95 | /// Float value 96 | Float(f64), 97 | /// Boolean value 98 | Boolean(bool), 99 | /// Binary data 100 | Binary(Vec), 101 | /// JSON value 102 | Json(serde_json::Value), 103 | /// Custom serializable value 104 | Custom(Box), 105 | } 106 | 107 | /// Storage configuration 108 | pub struct StorageConfig { 109 | /// Storage type 110 | storage_type: StorageType, 111 | /// Connection information 112 | connection: ConnectionInfo, 113 | /// Storage options 114 | options: StorageOptions, 115 | /// Encryption configuration 116 | encryption: Option, 117 | } 118 | 119 | /// Storage types 120 | pub enum StorageType { 121 | /// In-memory storage 122 | Memory, 123 | /// File system storage 124 | FileSystem, 125 | /// Redis storage 126 | Redis, 127 | /// SQLite storage 128 | SQLite, 129 | /// PostgreSQL storage 130 | PostgreSQL, 131 | /// Custom storage implementation 132 | Custom(String), 133 | } 134 | ``` 135 | 136 | ## Responsibilities 137 | 138 | ### 1. Data Management 139 | - Key-value operations 140 | - Query execution 141 | - File operations 142 | - Transaction handling 143 | - Data validation 144 | 145 | ### 2. Configuration 146 | - Connection management 147 | - Options handling 148 | - Schema management 149 | - Migration support 150 | - Encryption setup 151 | 152 | ### 3. Error Handling 153 | - Connection errors 154 | - Operation failures 155 | - Validation errors 156 | - Schema errors 157 | - Security errors 158 | 159 | ### 4. Performance 160 | - Connection pooling 161 | - Query optimization 162 | - Caching strategy 163 | - Resource management 164 | - Monitoring 165 | 166 | ## Implementation Requirements 167 | 168 | ### 1. Concurrency 169 | - Thread-safe operations 170 | - Transaction isolation 171 | - Lock management 172 | - Connection pooling 173 | - Error propagation 174 | 175 | ### 2. Security 176 | - Data encryption 177 | - Access control 178 | - Audit logging 179 | - Secure connections 180 | - Key management 181 | 182 | ### 3. Reliability 183 | - Error recovery 184 | - Data consistency 185 | - Backup support 186 | - Migration handling 187 | - Monitoring 188 | 189 | ### 4. Performance 190 | - Connection pooling 191 | - Query optimization 192 | - Index management 193 | - Cache utilization 194 | - Resource limits 195 | 196 | ## Usage Patterns 197 | 198 | ### 1. Key-Value Storage 199 | ```rust 200 | // Store configuration 201 | let config = StorageValue::Json(serde_json::json!({ 202 | "api_key": "secret", 203 | "endpoint": "https://api.example.com" 204 | })); 205 | storage.set("agent_config", &config).await?; 206 | 207 | // Retrieve configuration 208 | let config = storage.get("agent_config").await? 209 | .and_then(|v| v.as_json()) 210 | .ok_or_else(|| "Config not found")?; 211 | ``` 212 | 213 | ### 2. Relational Storage 214 | ```rust 215 | // Execute query 216 | let result = storage 217 | .query( 218 | "SELECT * FROM tasks WHERE status = ?", 219 | &[QueryParam::String("pending")], 220 | ) 221 | .await?; 222 | 223 | // Process results 224 | for row in result.rows() { 225 | process_task(row.get("task_id")?); 226 | } 227 | ``` 228 | 229 | ### 3. File Storage 230 | ```rust 231 | // Store temporary data 232 | let data = serialize_task_result(&result)?; 233 | storage 234 | .write_file("tmp/task_123/result.bin", &data) 235 | .await?; 236 | 237 | // Read temporary data 238 | let data = storage 239 | .read_file("tmp/task_123/result.bin") 240 | .await?; 241 | let result = deserialize_task_result(&data)?; 242 | ``` 243 | 244 | ## Error Handling 245 | 246 | ### 1. Storage Errors 247 | ```rust 248 | /// Storage error types 249 | pub enum StorageError { 250 | /// Connection failed 251 | ConnectionFailed(String), 252 | /// Operation failed 253 | OperationFailed(String), 254 | /// Invalid data 255 | InvalidData(String), 256 | /// Schema error 257 | SchemaError(String), 258 | /// Security error 259 | SecurityError(String), 260 | } 261 | ``` 262 | 263 | ### 2. Recovery Strategies 264 | 1. Retry failed operations 265 | 2. Use fallback storage 266 | 3. Clear corrupted data 267 | 4. Rebuild indices 268 | 5. Restore from backup 269 | 270 | ## Security Considerations 271 | 272 | ### 1. Data Protection 273 | - Encrypt sensitive data 274 | - Secure connections 275 | - Access control 276 | - Audit logging 277 | - Key rotation 278 | 279 | ### 2. Error Handling 280 | - Secure error messages 281 | - Validation checks 282 | - Input sanitization 283 | - Output encoding 284 | - Error logging 285 | -------------------------------------------------------------------------------- /design/interfaces/task.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Task Interface 2 | 3 | ## Overview 4 | Defines the core task abstraction that agents process within the swarm ecosystem. 5 | 6 | ## Core Traits 7 | 8 | ```rust 9 | /// Represents a task that can be processed by agents 10 | pub trait Task { 11 | /// Get the task's unique identifier 12 | fn id(&self) -> TaskId; 13 | 14 | /// Get the task description/prompt 15 | fn description(&self) -> &str; 16 | 17 | /// Get task-specific parameters 18 | fn parameters(&self) -> &TaskParameters; 19 | 20 | /// Get task status 21 | fn status(&self) -> TaskStatus; 22 | 23 | /// Update task status 24 | fn update_status(&mut self, status: TaskStatus); 25 | 26 | /// Get task results 27 | fn results(&self) -> Option<&TaskResults>; 28 | 29 | /// Set task results 30 | fn set_results(&mut self, results: TaskResults); 31 | 32 | /// Check if task requires verification 33 | fn requires_verification(&self) -> bool; 34 | 35 | /// Get verification requirements 36 | fn verification_requirements(&self) -> Option<&VerificationConfig>; 37 | } 38 | 39 | /// Task status states 40 | pub enum TaskStatus { 41 | Pending, 42 | InProgress, 43 | Completed, 44 | Failed, 45 | RequiresVerification, 46 | Verified, 47 | } 48 | 49 | /// Task parameters 50 | pub struct TaskParameters { 51 | /// Key-value pairs of task-specific parameters 52 | parameters: HashMap, 53 | /// Required capabilities for processing this task 54 | required_capabilities: Vec, 55 | /// Task priority level 56 | priority: Priority, 57 | /// Task timeout duration 58 | timeout: Duration, 59 | } 60 | 61 | /// Task results 62 | pub struct TaskResults { 63 | /// Output data from task execution 64 | output: Value, 65 | /// Processing metadata 66 | metadata: TaskMetadata, 67 | /// Verification signature if required 68 | signature: Option, 69 | } 70 | 71 | /// Task verification configuration 72 | pub struct VerificationConfig { 73 | /// Required verification method 74 | method: VerificationMethod, 75 | /// Required verifier capabilities 76 | required_capabilities: Vec, 77 | /// Verification timeout 78 | timeout: Duration, 79 | } 80 | ``` 81 | 82 | ## Responsibilities 83 | 84 | 1. Task Definition 85 | - Unique identification 86 | - Clear description/prompt 87 | - Structured parameters 88 | - Status tracking 89 | - Result storage 90 | 91 | 2. Verification Support 92 | - Optional verification requirements 93 | - Signature verification 94 | - Capability requirements 95 | 96 | 3. Parameter Management 97 | - Type-safe parameter storage 98 | - Required capability specification 99 | - Priority handling 100 | - Timeout management 101 | 102 | 4. Result Handling 103 | - Structured output storage 104 | - Processing metadata 105 | - Optional verification signatures 106 | 107 | ## Implementation Requirements 108 | 109 | 1. Thread Safety 110 | - Must be Send + Sync 111 | - Thread-safe status updates 112 | - Concurrent result access 113 | 114 | 2. Serialization 115 | - JSON/CBOR serialization support 116 | - Binary format support for efficiency 117 | - Schema versioning 118 | 119 | 3. Error Handling 120 | - Clear error types 121 | - Status transition validation 122 | - Timeout handling 123 | 124 | 4. Memory Management 125 | - Efficient parameter storage 126 | - Result caching options 127 | - Memory limit enforcement 128 | 129 | ## Usage Patterns 130 | 131 | 1. Task Creation 132 | ```rust 133 | let task = Task::new( 134 | description, 135 | parameters, 136 | verification_config, 137 | ); 138 | ``` 139 | 140 | 2. Status Updates 141 | ```rust 142 | task.update_status(TaskStatus::InProgress); 143 | // Process task 144 | task.update_status(TaskStatus::Completed); 145 | ``` 146 | 147 | 3. Result Setting 148 | ```rust 149 | let results = TaskResults { 150 | output: process_result, 151 | metadata: execution_metadata, 152 | signature: Some(sign_output(process_result)), 153 | }; 154 | task.set_results(results); 155 | ``` 156 | 157 | 4. Verification 158 | ```rust 159 | if task.requires_verification() { 160 | let config = task.verification_requirements().unwrap(); 161 | verify_task_results(task, config); 162 | } 163 | ``` 164 | -------------------------------------------------------------------------------- /design/interfaces/wallet.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Wallet Interface 2 | 3 | ## Overview 4 | Defines the wallet capabilities for blockchain interaction and web3 functionality in agents and swarms. 5 | 6 | ## Core Traits 7 | 8 | ```rust 9 | /// Core wallet capabilities 10 | pub trait BlockchainWallet: Send + Sync { 11 | /// Get wallet chain type 12 | fn chain_type(&self) -> ChainType; 13 | 14 | /// Get wallet address 15 | fn address(&self) -> &str; 16 | 17 | /// Sign message 18 | async fn sign_message(&self, message: &[u8]) -> Result, WalletError>; 19 | 20 | /// Verify signature 21 | async fn verify_signature( 22 | &self, 23 | message: &[u8], 24 | signature: &[u8], 25 | address: &str, 26 | ) -> Result; 27 | } 28 | 29 | /// Web3 interaction capabilities 30 | pub trait Web3Capabilities: Send + Sync { 31 | /// Execute smart contract call 32 | async fn execute_contract( 33 | &self, 34 | contract: Address, 35 | function: &str, 36 | params: &[Value], 37 | ) -> Result; 38 | 39 | /// Query contract state 40 | async fn query_contract( 41 | &self, 42 | contract: Address, 43 | function: &str, 44 | params: &[Value], 45 | ) -> Result; 46 | 47 | /// Transfer tokens 48 | async fn transfer_tokens( 49 | &self, 50 | token: Address, 51 | recipient: Address, 52 | amount: U256, 53 | ) -> Result; 54 | 55 | /// Query chain data 56 | async fn query_chain( 57 | &self, 58 | query: ChainQuery, 59 | ) -> Result; 60 | } 61 | 62 | /// Chain state machine interface 63 | pub trait ChainStateMachine: Send + Sync { 64 | /// Get current state 65 | async fn get_state(&self) -> Result; 66 | 67 | /// Watch state changes 68 | async fn watch_state( 69 | &self, 70 | filter: StateFilter, 71 | ) -> Result; 72 | 73 | /// Get state updates 74 | async fn get_updates( 75 | &self, 76 | from_block: BlockNumber, 77 | to_block: Option, 78 | ) -> Result, StateError>; 79 | } 80 | 81 | /// Wallet object combining all capabilities 82 | pub struct Wallet { 83 | /// Chain-specific wallet implementations 84 | wallets: HashMap>, 85 | /// Web3 capabilities 86 | capabilities: WalletCapabilities, 87 | /// Connection state 88 | state: WalletState, 89 | } 90 | 91 | /// Supported blockchain types 92 | pub enum ChainType { 93 | /// EVM-compatible chains 94 | EVM { 95 | chain_id: u64, 96 | network: String, 97 | }, 98 | /// Solana 99 | Solana { 100 | cluster: String, 101 | }, 102 | /// Custom chain implementation 103 | Custom(String), 104 | } 105 | 106 | /// Web3 capabilities configuration 107 | pub struct WalletCapabilities { 108 | /// Message signing 109 | signing: bool, 110 | /// Smart contract interaction 111 | contract_interaction: bool, 112 | /// Token transfers 113 | token_transfers: bool, 114 | /// NFT handling 115 | nft_support: bool, 116 | /// Chain data queries 117 | chain_queries: bool, 118 | } 119 | 120 | /// Wallet connection state 121 | pub struct WalletState { 122 | /// Connected networks 123 | networks: HashMap, 124 | /// Connection status 125 | status: ConnectionStatus, 126 | /// Last error 127 | last_error: Option, 128 | } 129 | ``` 130 | 131 | ## Responsibilities 132 | 133 | ### 1. Blockchain Interaction 134 | - Message signing and verification 135 | - Transaction creation and submission 136 | - Network connection management 137 | - State synchronization 138 | 139 | ### 2. Smart Contract Operations 140 | - Function calls 141 | - State queries 142 | - Event monitoring 143 | - Gas estimation 144 | 145 | ### 3. Token Management 146 | - Balance checks 147 | - Transfer operations 148 | - Approval management 149 | - Token standards support 150 | 151 | ### 4. Chain Data Access 152 | - Block queries 153 | - Transaction monitoring 154 | - State inspection 155 | - Event filtering 156 | 157 | ## Implementation Requirements 158 | 159 | ### 1. Security 160 | - Private key protection 161 | - Signature verification 162 | - Transaction validation 163 | - Access control 164 | 165 | ### 2. State Management 166 | - Network connectivity 167 | - Transaction tracking 168 | - Error handling 169 | - Recovery mechanisms 170 | 171 | ### 3. Performance 172 | - Connection pooling 173 | - Request batching 174 | - Cache management 175 | - Resource limits 176 | 177 | ### 4. Reliability 178 | - Error recovery 179 | - Transaction retry 180 | - State consistency 181 | - Timeout handling 182 | 183 | ## Usage Patterns 184 | 185 | ### 1. Wallet Creation 186 | ```rust 187 | // Create wallet with specific chain support 188 | let mut wallet = Wallet::new(WalletConfig { 189 | capabilities: WalletCapabilities { 190 | signing: true, 191 | contract_interaction: true, 192 | token_transfers: true, 193 | chain_queries: true, 194 | ..Default::default() 195 | }, 196 | ..Default::default() 197 | }); 198 | 199 | // Add chain-specific implementations 200 | wallet.add_chain( 201 | ChainType::EVM { 202 | chain_id: 1, 203 | network: "mainnet".into() 204 | }, 205 | Box::new(EvmWallet::new(config)?), 206 | )?; 207 | ``` 208 | 209 | ### 2. Contract Interaction 210 | ```rust 211 | // Execute contract call 212 | let tx_hash = wallet 213 | .execute_contract( 214 | contract_address, 215 | "transfer", 216 | &[ 217 | Value::Address(recipient), 218 | Value::Uint(amount), 219 | ], 220 | ) 221 | .await?; 222 | 223 | // Query contract state 224 | let balance = wallet 225 | .query_contract( 226 | token_address, 227 | "balanceOf", 228 | &[Value::Address(owner)], 229 | ) 230 | .await?; 231 | ``` 232 | 233 | ### 3. State Machine Updates 234 | ```rust 235 | // Watch for state changes 236 | let mut watcher = wallet 237 | .watch_state(StateFilter { 238 | addresses: vec![contract_address], 239 | topics: vec![event_signature], 240 | }) 241 | .await?; 242 | 243 | while let Some(update) = watcher.next().await { 244 | match update { 245 | StateUpdate::NewBlock(block) => { 246 | process_block(block); 247 | } 248 | StateUpdate::Event(event) => { 249 | handle_event(event); 250 | } 251 | StateUpdate::Error(error) => { 252 | handle_error(error); 253 | } 254 | } 255 | } 256 | ``` 257 | 258 | ### 4. Token Operations 259 | ```rust 260 | // Transfer tokens 261 | let tx_hash = wallet 262 | .transfer_tokens( 263 | token_address, 264 | recipient, 265 | amount, 266 | ) 267 | .await?; 268 | 269 | // Check transaction status 270 | let receipt = wallet 271 | .query_chain(ChainQuery::Transaction(tx_hash)) 272 | .await?; 273 | ``` 274 | 275 | ## Error Handling 276 | 277 | ### 1. Wallet Errors 278 | ```rust 279 | pub enum WalletError { 280 | /// Connection failed 281 | ConnectionFailed(String), 282 | /// Transaction failed 283 | TransactionFailed(String), 284 | /// Invalid signature 285 | InvalidSignature(String), 286 | /// Chain error 287 | ChainError(String), 288 | /// Configuration error 289 | ConfigError(String), 290 | } 291 | ``` 292 | 293 | ### 2. Recovery Strategies 294 | 1. Connection retry with backoff 295 | 2. Transaction resubmission 296 | 3. Network fallback 297 | 4. State resynchronization 298 | 299 | ## Security Considerations 300 | 301 | ### 1. Key Management 302 | - Secure storage 303 | - Access control 304 | - Key rotation 305 | - Backup mechanisms 306 | 307 | ### 2. Transaction Safety 308 | - Gas limits 309 | - Value limits 310 | - Destination validation 311 | - Simulation before sending 312 | 313 | ### 3. Error Protection 314 | - Rate limiting 315 | - Duplicate detection 316 | - Timeout handling 317 | - Validation checks 318 | -------------------------------------------------------------------------------- /design/requirements/README.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Implementation Requirements 2 | 3 | This directory contains detailed implementation requirements: 4 | 5 | ## Categories 6 | 7 | - `core_functions.md`: Essential system functionality 8 | - `service_integration.md`: External service integration 9 | - `blockchain_verification.md`: Identity verification requirements 10 | - `error_handling.md`: Error handling and recovery 11 | - `security.md`: Security requirements and constraints 12 | 13 | Each requirement document specifies: 14 | - Functional requirements 15 | - Non-functional requirements 16 | - Implementation constraints 17 | - Performance criteria 18 | -------------------------------------------------------------------------------- /design/requirements/agent_consensus.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Agent Consensus Design 2 | 3 | ## Overview 4 | Defines the consensus mechanisms for multi-agent collaboration and decision making. 5 | 6 | ## Core Components 7 | 8 | ### 1. Consensus Types 9 | ```rust 10 | /// Types of consensus mechanisms 11 | pub enum ConsensusType { 12 | /// Simple binary voting (true/false decisions) 13 | BinaryVote, 14 | /// Simple majority voting with optional confidence 15 | MajorityVote, 16 | /// Weighted voting based on agent confidence 17 | WeightedVote, 18 | /// LLM-based arbitration 19 | LLMArbitration, 20 | /// Custom consensus implementation 21 | Custom(Box), 22 | } 23 | 24 | /// Consensus result 25 | pub struct ConsensusResult { 26 | /// Agreed upon result 27 | result: T, 28 | /// Confidence score 29 | confidence: f32, 30 | /// Contributing agents 31 | contributors: Vec, 32 | /// Verification signature if required 33 | signature: Option, 34 | } 35 | ``` 36 | 37 | ### 2. Task Distribution 38 | ```rust 39 | /// Task distribution strategies 40 | pub enum DistributionStrategy { 41 | /// Send to all agents 42 | Broadcast, 43 | /// Send to specific subset 44 | TargetedGroup(Vec), 45 | /// Send to agents with required capabilities 46 | CapabilityBased(Vec), 47 | } 48 | 49 | /// Distribution configuration 50 | pub struct DistributionConfig { 51 | /// Distribution strategy 52 | strategy: DistributionStrategy, 53 | /// Minimum required responses 54 | min_responses: usize, 55 | /// Timeout duration 56 | timeout: Duration, 57 | /// Required verification 58 | require_verification: bool, 59 | } 60 | ``` 61 | 62 | ### 3. Result Collection 63 | ```rust 64 | /// Result collection handler 65 | pub trait ResultCollector { 66 | /// Collect agent responses 67 | async fn collect_responses( 68 | &self, 69 | task_id: TaskId, 70 | timeout: Duration, 71 | ) -> Result, CollectionError>; 72 | 73 | /// Validate responses 74 | fn validate_responses( 75 | &self, 76 | responses: &[AgentResponse], 77 | ) -> Result<(), ValidationError>; 78 | 79 | /// Aggregate results 80 | fn aggregate_results( 81 | &self, 82 | responses: &[AgentResponse], 83 | ) -> Result; 84 | } 85 | ``` 86 | 87 | ## Implementation Requirements 88 | 89 | ### 1. Task Distribution 90 | - Support both broadcast and targeted distribution 91 | - Handle timeouts and partial responses 92 | - Track task distribution state 93 | - Verify agent capabilities 94 | 95 | ### 2. Response Collection 96 | - Gather responses from multiple agents 97 | - Handle timeout conditions 98 | - Support partial results 99 | - Validate response integrity 100 | 101 | ### 3. Consensus Building 102 | - Implement voting mechanisms 103 | - Support weighted decisions 104 | - Allow LLM-based arbitration 105 | - Handle disagreements 106 | 107 | ### 4. Result Verification 108 | - Verify agent signatures 109 | - Validate consensus process 110 | - Ensure minimum participation 111 | - Track decision confidence 112 | 113 | ## Usage Patterns 114 | 115 | ### 1. Simple Majority Vote 116 | ```rust 117 | // 1. Distribute task 118 | let responses = swarm.broadcast_task(task, config).await?; 119 | 120 | // 2. Collect votes 121 | let votes = consensus.collect_votes(responses)?; 122 | 123 | // 3. Determine result 124 | let final_result = consensus.majority_decision(votes)?; 125 | ``` 126 | 127 | ### 2. Weighted Consensus 128 | ```rust 129 | // 1. Configure weighted voting 130 | let config = ConsensusConfig { 131 | strategy: ConsensusType::WeightedVote, 132 | weights: agent_weights, 133 | threshold: 0.7, 134 | }; 135 | 136 | // 2. Process responses 137 | let weighted_result = consensus 138 | .process_weighted_responses(responses, config) 139 | .await?; 140 | ``` 141 | 142 | ### 3. LLM Arbitration 143 | ```rust 144 | // 1. Collect diverse responses 145 | let responses = swarm.gather_responses(task).await?; 146 | 147 | // 2. Handle disagreement 148 | if consensus.has_significant_disagreement(responses) { 149 | // Use LLM to analyze and reconcile 150 | let arbitrated = consensus.llm_arbitrate(responses).await?; 151 | return Ok(arbitrated); 152 | } 153 | ``` 154 | 155 | ## Integration with Swarm 156 | 157 | ### 1. Swarm Configuration 158 | ```rust 159 | /// Swarm consensus configuration 160 | pub struct SwarmConsensusConfig { 161 | /// Default consensus type 162 | consensus_type: ConsensusType, 163 | /// Distribution strategy 164 | distribution: DistributionStrategy, 165 | /// Minimum confidence threshold 166 | confidence_threshold: f32, 167 | /// Verification requirements 168 | verification: VerificationConfig, 169 | } 170 | ``` 171 | 172 | ### 2. Agent Integration 173 | ```rust 174 | /// Agent consensus capabilities 175 | pub trait ConsensusCapable { 176 | /// Vote on result 177 | async fn vote(&self, proposal: &Proposal) -> Result; 178 | 179 | /// Validate consensus 180 | fn validate_consensus(&self, result: &ConsensusResult) -> Result<(), ValidationError>; 181 | 182 | /// Sign consensus result 183 | async fn sign_result(&self, result: &ConsensusResult) -> Result; 184 | } 185 | ``` 186 | 187 | ## Error Handling 188 | 189 | ### 1. Consensus Errors 190 | ```rust 191 | /// Consensus error types 192 | pub enum ConsensusError { 193 | /// Insufficient responses 194 | InsufficientResponses(String), 195 | /// Validation failed 196 | ValidationFailed(String), 197 | /// Timeout occurred 198 | ConsensusTimeout(String), 199 | /// Verification failed 200 | VerificationFailed(String), 201 | } 202 | ``` 203 | 204 | ### 2. Recovery Strategies 205 | 1. Retry with expanded agent set 206 | 2. Fallback to simpler consensus mechanism 207 | 3. Escalate to human operator 208 | 4. Log and report consensus failures 209 | 210 | ## Security Considerations 211 | 212 | 1. Response Verification 213 | - Validate agent signatures 214 | - Verify response integrity 215 | - Track agent reputation 216 | 217 | 2. Consensus Protection 218 | - Prevent manipulation 219 | - Ensure fair participation 220 | - Audit consensus process 221 | 222 | 3. Result Integrity 223 | - Sign consensus results 224 | - Verify decision chain 225 | - Maintain audit logs 226 | -------------------------------------------------------------------------------- /design/requirements/core_functions.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Core Functions and Implementation Requirements 2 | 3 | ## Agent Core Functions 4 | 5 | ### 1. Task Processing 6 | - Process input tasks and generate outputs 7 | - Handle task validation and verification 8 | - Support task routing and delegation 9 | - Manage task state and lifecycle 10 | - Track task history and metadata 11 | 12 | ### 2. Communication 13 | - Exchange messages with other agents 14 | - Support synchronous/asynchronous patterns 15 | - Handle message validation and routing 16 | - Manage communication state 17 | - Support broadcast and targeted messages 18 | 19 | ### 3. Identity Management 20 | - Maintain unique agent identity 21 | - Handle blockchain wallet integration 22 | - Sign messages and outputs 23 | - Verify signatures from other agents 24 | - Manage authentication credentials 25 | 26 | ### 4. Service Integration 27 | - Support HTTP/gRPC endpoints 28 | - Handle service health monitoring 29 | - Manage connection pooling 30 | - Implement retry mechanisms 31 | - Support circuit breaking 32 | 33 | ## Swarm Core Functions 34 | 35 | ### 1. Agent Orchestration 36 | - Manage agent lifecycle 37 | - Handle agent registration/deregistration 38 | - Monitor agent health 39 | - Balance workload distribution 40 | - Track agent metrics 41 | 42 | ### 2. Task Distribution 43 | - Route tasks to appropriate agents 44 | - Handle task dependencies 45 | - Manage task priorities 46 | - Track task progress 47 | - Handle task failures 48 | 49 | ### 3. Decision Making 50 | - LLM-based decision making 51 | - Task routing decisions 52 | - Agent selection logic 53 | - Performance optimization 54 | - Error recovery strategies 55 | 56 | ### 4. State Management 57 | - Maintain shared state 58 | - Handle state synchronization 59 | - Manage consistency 60 | - Track state history 61 | - Handle state conflicts 62 | 63 | ## Memory Core Functions 64 | 65 | ### 1. Vector Operations 66 | - Store and retrieve vectors 67 | - Build and maintain indices 68 | - Perform similarity search 69 | - Handle vector updates 70 | - Manage vector metadata 71 | 72 | ### 2. Context Management 73 | - Store task context 74 | - Share context between agents 75 | - Update context state 76 | - Handle context persistence 77 | - Manage context lifecycle 78 | 79 | ### 3. Cache Operations 80 | - Implement caching strategies 81 | - Handle cache invalidation 82 | - Manage cache distribution 83 | - Monitor cache performance 84 | - Handle cache failures 85 | 86 | ### 4. Persistence 87 | - Ensure data durability 88 | - Handle backup/restore 89 | - Manage consistency 90 | - Support data migration 91 | - Handle recovery 92 | 93 | ## Model Core Functions 94 | 95 | ### 1. Provider Integration 96 | - Support multiple providers 97 | - Handle authentication 98 | - Manage rate limiting 99 | - Track usage metrics 100 | - Handle provider errors 101 | 102 | ### 2. Inference Management 103 | - Control inference processes 104 | - Manage resource allocation 105 | - Handle timeouts 106 | - Implement retry logic 107 | - Track performance 108 | 109 | ### 3. Decision Support 110 | - Generate completions 111 | - Evaluate options 112 | - Provide explanations 113 | - Handle uncertainty 114 | - Support streaming 115 | 116 | ### 4. Function Calling 117 | - Register functions 118 | - Handle function calls 119 | - Validate inputs/outputs 120 | - Manage timeouts 121 | - Track usage 122 | 123 | ## Implementation Requirements 124 | 125 | ### 1. Concurrency 126 | - Thread-safe operations 127 | - Async/await support 128 | - Lock management 129 | - Resource sharing 130 | - Error propagation 131 | 132 | ### 2. Error Handling 133 | - Clear error types 134 | - Error recovery 135 | - Timeout handling 136 | - Retry mechanisms 137 | - Failure isolation 138 | 139 | ### 3. Security 140 | - Authentication 141 | - Authorization 142 | - Message signing 143 | - Secure storage 144 | - Access control 145 | 146 | ### 4. Performance 147 | - Resource efficiency 148 | - Scalability 149 | - Monitoring 150 | - Optimization 151 | - Load balancing 152 | 153 | ### 5. Testing 154 | - Unit tests 155 | - Integration tests 156 | - Performance tests 157 | - Security tests 158 | - Failure testing 159 | 160 | ### 6. Documentation 161 | - API documentation 162 | - Usage examples 163 | - Architecture docs 164 | - Error handling 165 | - Best practices 166 | 167 | ## Blockchain Requirements 168 | 169 | ### 1. Wallet Integration 170 | - Support multiple wallet types 171 | - Handle key management 172 | - Implement signing logic 173 | - Verify signatures 174 | - Track wallet state 175 | 176 | ### 2. Message Signing 177 | - Sign agent outputs 178 | - Verify signatures 179 | - Handle key rotation 180 | - Support multiple algorithms 181 | - Track signature history 182 | 183 | ### 3. Identity Verification 184 | - Verify agent identity 185 | - Handle wallet addresses 186 | - Manage trust levels 187 | - Track verification history 188 | - Handle verification failures 189 | 190 | ### 4. Security 191 | - Secure key storage 192 | - Handle key recovery 193 | - Implement access control 194 | - Monitor security events 195 | - Handle security breaches 196 | 197 | ## Quality Requirements 198 | 199 | ### 1. Reliability 200 | - High availability 201 | - Fault tolerance 202 | - Data consistency 203 | - Error recovery 204 | - Monitoring 205 | 206 | ### 2. Maintainability 207 | - Clean code 208 | - Clear documentation 209 | - Easy deployment 210 | - Simple configuration 211 | - Effective logging 212 | 213 | ### 3. Scalability 214 | - Horizontal scaling 215 | - Load balancing 216 | - Resource management 217 | - Performance monitoring 218 | - Capacity planning 219 | 220 | ### 4. Usability 221 | - Clear interfaces 222 | - Good documentation 223 | - Error messages 224 | - Configuration 225 | - Examples 226 | 227 | ## Development Guidelines 228 | 229 | ### 1. Code Organization 230 | - Clear structure 231 | - Modular design 232 | - Clean interfaces 233 | - Good documentation 234 | - Consistent style 235 | 236 | ### 2. Error Handling 237 | - Clear error types 238 | - Good messages 239 | - Recovery logic 240 | - Logging 241 | - Monitoring 242 | 243 | ### 3. Testing Strategy 244 | - Unit tests 245 | - Integration tests 246 | - Performance tests 247 | - Security tests 248 | - Documentation 249 | 250 | ### 4. Documentation 251 | - API docs 252 | - Architecture 253 | - Examples 254 | - Deployment 255 | - Troubleshooting 256 | -------------------------------------------------------------------------------- /design/requirements/error_handling.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Error Handling Requirements 2 | 3 | ## Overview 4 | Defines standardized error handling patterns for fault-tolerant agent and swarm operations. 5 | 6 | ## Core Components 7 | 8 | ```rust 9 | /// Core error types for agent operations 10 | #[derive(Debug, thiserror::Error)] 11 | pub enum AgentError { 12 | #[error("Task processing failed: {0}")] 13 | TaskProcessing(String), 14 | 15 | #[error("Configuration error: {0}")] 16 | Configuration(String), 17 | 18 | #[error("Resource unavailable: {0}")] 19 | ResourceUnavailable(String), 20 | 21 | #[error("Identity verification failed: {0}")] 22 | IdentityVerification(String), 23 | 24 | #[error("Service error: {0}")] 25 | Service(#[from] ServiceError), 26 | 27 | #[error("Storage error: {0}")] 28 | Storage(#[from] StorageError), 29 | 30 | #[error("Memory error: {0}")] 31 | Memory(#[from] MemoryError), 32 | 33 | #[error("Model error: {0}")] 34 | Model(#[from] ModelError), 35 | 36 | #[error("Chain error: {0}")] 37 | Chain(#[from] ChainError), 38 | } 39 | 40 | /// Core error types for swarm operations 41 | #[derive(Debug, thiserror::Error)] 42 | pub enum SwarmError { 43 | #[error("Agent error: {0}")] 44 | Agent(#[from] AgentError), 45 | 46 | #[error("Consensus error: {0}")] 47 | Consensus(#[from] ConsensusError), 48 | 49 | #[error("Orchestration error: {0}")] 50 | Orchestration(String), 51 | 52 | #[error("State error: {0}")] 53 | State(String), 54 | 55 | #[error("Resource error: {0}")] 56 | Resource(String), 57 | 58 | #[error("Communication error: {0}")] 59 | Communication(String), 60 | } 61 | 62 | /// Error recovery strategy 63 | pub enum RecoveryStrategy { 64 | /// Retry the operation 65 | Retry { 66 | max_attempts: usize, 67 | backoff: Duration, 68 | }, 69 | /// Use alternative approach 70 | Alternative { 71 | strategy: Box, 72 | fallback: Option>, 73 | }, 74 | /// Reset to known good state 75 | Reset { 76 | checkpoint: StateCheckpoint, 77 | cleanup: bool, 78 | }, 79 | /// Fail operation 80 | Fail { 81 | cleanup: bool, 82 | notification: Option, 83 | }, 84 | } 85 | 86 | /// Error context for recovery 87 | pub struct ErrorContext { 88 | /// Error details 89 | error: Box, 90 | /// Operation being performed 91 | operation: Operation, 92 | /// System state at error 93 | state: SystemState, 94 | /// Available resources 95 | resources: ResourceState, 96 | /// Recovery attempts 97 | attempts: usize, 98 | } 99 | ``` 100 | 101 | ## Error Handling Patterns 102 | 103 | ### 1. Standardized Recovery Flow 104 | ```rust 105 | impl ErrorHandler { 106 | async fn handle_error( 107 | &self, 108 | error: impl std::error::Error, 109 | context: ErrorContext, 110 | ) -> Result { 111 | // Analyze error and context 112 | let analysis = self.analyze_error(&error, &context).await?; 113 | 114 | // Select recovery strategy 115 | let strategy = self.select_strategy(analysis, &context)?; 116 | 117 | // Apply recovery strategy 118 | match strategy { 119 | RecoveryStrategy::Retry { max_attempts, backoff } => { 120 | if context.attempts < max_attempts { 121 | Ok(RecoveryAction::Retry { delay: backoff }) 122 | } else { 123 | Ok(RecoveryAction::Fail) 124 | } 125 | } 126 | RecoveryStrategy::Alternative { strategy, fallback } => { 127 | self.apply_alternative(strategy, fallback, &context).await 128 | } 129 | RecoveryStrategy::Reset { checkpoint, cleanup } => { 130 | self.perform_reset(checkpoint, cleanup, &context).await 131 | } 132 | RecoveryStrategy::Fail { cleanup, notification } => { 133 | self.handle_failure(cleanup, notification, &context).await 134 | } 135 | } 136 | } 137 | } 138 | ``` 139 | 140 | ### 2. Autonomous Error Recovery 141 | ```rust 142 | impl AutonomousRecovery { 143 | async fn recover( 144 | &self, 145 | error: impl std::error::Error, 146 | context: ErrorContext, 147 | ) -> Result { 148 | // Learn from error 149 | self.learn_from_error(&error, &context).await?; 150 | 151 | // Generate recovery plan 152 | let plan = self.generate_recovery_plan(&error, &context).await?; 153 | 154 | // Execute recovery steps 155 | for step in plan.steps { 156 | match self.execute_step(step).await { 157 | Ok(result) => { 158 | self.record_success(step, result).await?; 159 | } 160 | Err(e) => { 161 | self.record_failure(step, e).await?; 162 | return Err(RecoveryError::StepFailed { step, error: e }); 163 | } 164 | } 165 | } 166 | 167 | Ok(RecoveryResult::Success) 168 | } 169 | } 170 | ``` 171 | 172 | ## Implementation Requirements 173 | 174 | ### 1. Error Classification 175 | - Error type hierarchy 176 | - Error categorization 177 | - Severity levels 178 | - Impact assessment 179 | - Recovery requirements 180 | 181 | ### 2. Recovery Mechanisms 182 | - Retry policies 183 | - Alternative strategies 184 | - State restoration 185 | - Resource cleanup 186 | - Failure notification 187 | 188 | ### 3. Monitoring and Analysis 189 | - Error tracking 190 | - Pattern detection 191 | - Performance impact 192 | - Resource usage 193 | - Success rates 194 | 195 | ### 4. Learning and Adaptation 196 | - Error pattern learning 197 | - Strategy optimization 198 | - Recovery improvement 199 | - Knowledge sharing 200 | - Continuous adaptation 201 | 202 | ## Usage Examples 203 | 204 | ### 1. Agent Error Handling 205 | ```rust 206 | impl Agent { 207 | async fn handle_task_error( 208 | &mut self, 209 | error: AgentError, 210 | task: &Task, 211 | ) -> Result { 212 | let context = ErrorContext { 213 | error: Box::new(error), 214 | operation: Operation::TaskProcessing(task.clone()), 215 | state: self.current_state(), 216 | resources: self.available_resources(), 217 | attempts: self.attempt_count(), 218 | }; 219 | 220 | self.error_handler.handle_error(error, context).await 221 | } 222 | } 223 | ``` 224 | 225 | ### 2. Swarm Error Recovery 226 | ```rust 227 | impl Swarm { 228 | async fn recover_from_error( 229 | &mut self, 230 | error: SwarmError, 231 | context: ErrorContext, 232 | ) -> Result<(), RecoveryError> { 233 | // Attempt autonomous recovery 234 | match self.autonomous_recovery.recover(error, context).await { 235 | Ok(_) => Ok(()), 236 | Err(e) => { 237 | // Fallback to manual recovery if autonomous fails 238 | self.manual_recovery.recover(error, context).await 239 | } 240 | } 241 | } 242 | } 243 | ``` 244 | 245 | ## Security Considerations 246 | 247 | ### 1. Error Information 248 | - Sensitive data handling 249 | - Error message sanitization 250 | - Stack trace protection 251 | - Log security 252 | - Access control 253 | 254 | ### 2. Recovery Operations 255 | - Permission verification 256 | - Resource protection 257 | - State validation 258 | - Operation auditing 259 | - Recovery logging 260 | 261 | ### 3. Autonomous Actions 262 | - Action validation 263 | - Resource limits 264 | - Safety constraints 265 | - Audit trails 266 | - Rollback capability 267 | -------------------------------------------------------------------------------- /design/requirements/self_improvement.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Self-Improvement Requirements 2 | 3 | ## Overview 4 | Defines the self-reflection and improvement capabilities for autonomous agents and swarms. 5 | 6 | ## Core Components 7 | 8 | ```rust 9 | /// Performance analysis for agents 10 | pub struct PerformanceAnalysis { 11 | /// Success rate 12 | success_rate: f32, 13 | /// Average response time 14 | avg_response_time: Duration, 15 | /// Error patterns 16 | error_patterns: Vec, 17 | /// Resource utilization 18 | resource_usage: ResourceMetrics, 19 | /// Improvement opportunities 20 | opportunities: Vec, 21 | } 22 | 23 | /// Areas for improvement 24 | pub struct ImprovementArea { 25 | /// Area identifier 26 | id: String, 27 | /// Description 28 | description: String, 29 | /// Current performance 30 | current_performance: MetricValue, 31 | /// Target performance 32 | target_performance: MetricValue, 33 | /// Improvement strategy 34 | strategy: ImprovementStrategy, 35 | /// Required resources 36 | required_resources: Vec, 37 | } 38 | 39 | /// Task experience for learning 40 | pub struct TaskExperience { 41 | /// Task details 42 | task: Task, 43 | /// Execution result 44 | result: TaskResults, 45 | /// Performance metrics 46 | metrics: PerformanceMetrics, 47 | /// Learning points 48 | learnings: Vec, 49 | /// Context information 50 | context: ExecutionContext, 51 | } 52 | 53 | /// Swarm performance analysis 54 | pub struct SwarmPerformanceAnalysis { 55 | /// Overall efficiency 56 | efficiency: f32, 57 | /// Agent utilization 58 | agent_utilization: Vec, 59 | /// Communication patterns 60 | communication_patterns: Vec, 61 | /// Resource distribution 62 | resource_distribution: ResourceDistribution, 63 | /// Bottlenecks 64 | bottlenecks: Vec, 65 | } 66 | 67 | /// Composition changes for swarm optimization 68 | pub struct CompositionChanges { 69 | /// Agent additions 70 | additions: Vec, 71 | /// Agent removals 72 | removals: Vec, 73 | /// Role reassignments 74 | reassignments: Vec, 75 | /// Capability adjustments 76 | capability_adjustments: Vec, 77 | } 78 | 79 | /// Coordination improvements 80 | pub struct CoordinationImprovements { 81 | /// Pattern optimizations 82 | pattern_optimizations: Vec, 83 | /// Communication enhancements 84 | communication_enhancements: Vec, 85 | /// Workflow adjustments 86 | workflow_adjustments: Vec, 87 | /// Resource optimizations 88 | resource_optimizations: Vec, 89 | } 90 | ``` 91 | 92 | ## Implementation Requirements 93 | 94 | ### 1. Agent Self-Improvement 95 | - Performance monitoring 96 | - Error pattern analysis 97 | - Resource optimization 98 | - Capability enhancement 99 | - Learning from experience 100 | 101 | ### 2. Swarm Self-Improvement 102 | - Composition optimization 103 | - Role distribution 104 | - Communication patterns 105 | - Resource allocation 106 | - Workflow enhancement 107 | 108 | ### 3. Learning Mechanisms 109 | - Experience collection 110 | - Pattern recognition 111 | - Strategy adaptation 112 | - Knowledge sharing 113 | - Continuous improvement 114 | 115 | ### 4. Metrics and Analysis 116 | - Performance tracking 117 | - Resource monitoring 118 | - Error analysis 119 | - Improvement tracking 120 | - Success measurement 121 | 122 | ## Usage Examples 123 | 124 | ### 1. Agent Self-Improvement 125 | ```rust 126 | // Perform self-reflection 127 | let analysis = agent.analyze_performance().await?; 128 | 129 | // Identify improvements 130 | let improvements = analysis.opportunities.into_iter() 131 | .filter(|imp| imp.is_feasible()) 132 | .collect(); 133 | 134 | // Apply improvements 135 | agent.apply_improvements(improvements).await?; 136 | 137 | // Learn from experience 138 | agent.learn_from_experience(task_experience).await?; 139 | ``` 140 | 141 | ### 2. Swarm Optimization 142 | ```rust 143 | // Analyze swarm performance 144 | let analysis = swarm.analyze_swarm_performance().await?; 145 | 146 | // Optimize composition 147 | let changes = swarm.optimize_composition().await?; 148 | apply_composition_changes(swarm, changes).await?; 149 | 150 | // Improve coordination 151 | let improvements = swarm.improve_coordination().await?; 152 | apply_coordination_improvements(swarm, improvements).await?; 153 | ``` 154 | 155 | ## Security Considerations 156 | 157 | ### 1. Safe Learning 158 | - Validation of improvements 159 | - Resource limits 160 | - Safety constraints 161 | - Rollback capability 162 | - State verification 163 | 164 | ### 2. Access Control 165 | - Permission management 166 | - Change authorization 167 | - Resource protection 168 | - State integrity 169 | - Audit logging 170 | 171 | ### 3. Data Protection 172 | - Experience privacy 173 | - Metric security 174 | - Analysis protection 175 | - Knowledge sharing controls 176 | - State encryption 177 | -------------------------------------------------------------------------------- /design/requirements/storage.md: -------------------------------------------------------------------------------- 1 | # Swarms-Rust Storage Requirements 2 | 3 | ## Overview 4 | Defines the requirements and constraints for implementing storage capabilities in agents and swarms. 5 | 6 | ## Storage Types 7 | 8 | ### 1. Key-Value Storage 9 | - Required for: 10 | - Agent configuration 11 | - Runtime metadata 12 | - Cache data 13 | - Session state 14 | - Implementation options: 15 | - In-memory 16 | - Redis 17 | - RocksDB 18 | - Custom backends 19 | 20 | ### 2. Relational Storage 21 | - Required for: 22 | - Task history 23 | - Agent relationships 24 | - Performance metrics 25 | - Audit logs 26 | - Implementation options: 27 | - SQLite 28 | - PostgreSQL 29 | - Custom backends 30 | 31 | ### 3. File Storage 32 | - Required for: 33 | - Temporary data 34 | - Large objects 35 | - Binary artifacts 36 | - Log files 37 | - Implementation options: 38 | - Local filesystem 39 | - Object storage 40 | - Custom backends 41 | 42 | ## Implementation Requirements 43 | 44 | ### 1. Core Requirements 45 | - Thread-safe operations 46 | - Async/await support 47 | - Error recovery 48 | - Transaction support 49 | - Monitoring capabilities 50 | 51 | ### 2. Performance Requirements 52 | - Low latency access 53 | - Connection pooling 54 | - Query optimization 55 | - Cache support 56 | - Resource limits 57 | 58 | ### 3. Security Requirements 59 | - Data encryption 60 | - Access control 61 | - Audit logging 62 | - Secure deletion 63 | - Key management 64 | 65 | ### 4. Reliability Requirements 66 | - Data consistency 67 | - Backup support 68 | - Error recovery 69 | - Migration handling 70 | - Health monitoring 71 | 72 | ## Storage Patterns 73 | 74 | ### 1. Agent Storage 75 | ```rust 76 | /// Agent storage configuration 77 | pub struct AgentStorageConfig { 78 | /// Metadata storage 79 | metadata_storage: StorageConfig, 80 | /// Configuration storage 81 | config_storage: StorageConfig, 82 | /// Temporary storage 83 | temp_storage: StorageConfig, 84 | } 85 | 86 | /// Agent storage requirements 87 | pub trait AgentStorage { 88 | /// Store agent metadata 89 | async fn store_metadata(&mut self, metadata: &AgentMetadata) -> Result<(), StorageError>; 90 | 91 | /// Load agent configuration 92 | async fn load_config(&self) -> Result; 93 | 94 | /// Store temporary data 95 | async fn store_temp( 96 | &mut self, 97 | key: &str, 98 | data: &[u8], 99 | ttl: Duration, 100 | ) -> Result<(), StorageError>; 101 | } 102 | ``` 103 | 104 | ### 2. Swarm Storage 105 | ```rust 106 | /// Swarm storage configuration 107 | pub struct SwarmStorageConfig { 108 | /// State storage 109 | state_storage: StorageConfig, 110 | /// Task storage 111 | task_storage: StorageConfig, 112 | /// Metrics storage 113 | metrics_storage: StorageConfig, 114 | } 115 | 116 | /// Swarm storage requirements 117 | pub trait SwarmStorage { 118 | /// Store swarm state 119 | async fn store_state(&mut self, state: &SwarmState) -> Result<(), StorageError>; 120 | 121 | /// Store task data 122 | async fn store_task(&mut self, task: &Task) -> Result<(), StorageError>; 123 | 124 | /// Update metrics 125 | async fn update_metrics(&mut self, metrics: &SwarmMetrics) -> Result<(), StorageError>; 126 | } 127 | ``` 128 | 129 | ## Error Handling 130 | 131 | ### 1. Storage Errors 132 | ```rust 133 | /// Storage error categories 134 | pub enum StorageErrorCategory { 135 | /// Connection errors 136 | Connection, 137 | /// Operation errors 138 | Operation, 139 | /// Data errors 140 | Data, 141 | /// Security errors 142 | Security, 143 | /// Resource errors 144 | Resource, 145 | } 146 | 147 | /// Error recovery strategies 148 | pub trait ErrorRecovery { 149 | /// Attempt recovery 150 | async fn recover(&mut self, error: &StorageError) -> Result<(), RecoveryError>; 151 | 152 | /// Get recovery policy 153 | fn recovery_policy(&self) -> &RecoveryPolicy; 154 | 155 | /// Update recovery metrics 156 | fn update_metrics(&mut self, attempt: &RecoveryAttempt); 157 | } 158 | ``` 159 | 160 | ### 2. Recovery Strategies 161 | 1. Retry Operations 162 | - Exponential backoff 163 | - Maximum attempts 164 | - Circuit breaking 165 | - Fallback options 166 | 167 | 2. Data Recovery 168 | - Backup restoration 169 | - State reconstruction 170 | - Consistency checks 171 | - Repair operations 172 | 173 | 3. Resource Management 174 | - Connection pooling 175 | - Resource cleanup 176 | - Memory management 177 | - Cache invalidation 178 | 179 | ## Security Considerations 180 | 181 | ### 1. Data Protection 182 | - Encryption at rest 183 | - Encryption in transit 184 | - Access control 185 | - Key rotation 186 | - Secure deletion 187 | 188 | ### 2. Access Control 189 | - Authentication 190 | - Authorization 191 | - Role-based access 192 | - Audit logging 193 | - Session management 194 | 195 | ### 3. Compliance 196 | - Data retention 197 | - Privacy controls 198 | - Audit requirements 199 | - Regulatory compliance 200 | - Security standards 201 | 202 | ## Monitoring Requirements 203 | 204 | ### 1. Performance Metrics 205 | - Operation latency 206 | - Resource usage 207 | - Cache hit rates 208 | - Error rates 209 | - Connection stats 210 | 211 | ### 2. Health Checks 212 | - Connection status 213 | - Storage capacity 214 | - Error patterns 215 | - Resource limits 216 | - Backup status 217 | 218 | ### 3. Alerting 219 | - Error thresholds 220 | - Resource warnings 221 | - Security events 222 | - Performance issues 223 | - Recovery failures 224 | 225 | ## Implementation Guidelines 226 | 227 | ### 1. Storage Selection 228 | - Consider requirements: 229 | - Performance needs 230 | - Reliability requirements 231 | - Security constraints 232 | - Resource limitations 233 | - Operational costs 234 | 235 | ### 2. Error Handling 236 | - Implement recovery: 237 | - Retry strategies 238 | - Fallback options 239 | - Error reporting 240 | - Monitoring 241 | - Alerting 242 | 243 | ### 3. Security 244 | - Follow best practices: 245 | - Encryption 246 | - Access control 247 | - Audit logging 248 | - Key management 249 | - Secure configuration 250 | 251 | ### 4. Performance 252 | - Optimize for: 253 | - Low latency 254 | - High throughput 255 | - Resource efficiency 256 | - Scalability 257 | - Reliability 258 | -------------------------------------------------------------------------------- /swarm_agent/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "swarm_agent" 3 | version = "0.1.0" 4 | edition = "2021" 5 | description = "agent traits for the swarms framework" 6 | license = "MIT" 7 | 8 | [dependencies] 9 | swarm_wallet = { path = "../swarm_wallet" } 10 | swarm_tool = { path = "../swarm_tool" } 11 | swarm_llm = { path = "../swarm_llm" } 12 | swarm_memory = { path = "../swarm_memory" } 13 | tokio = { workspace = true } 14 | async-trait = { workspace = true } 15 | serde = { workspace = true } 16 | serde_json = { workspace = true } 17 | uuid = { workspace = true } 18 | log = { workspace = true } 19 | env_logger = { workspace = true } 20 | thiserror = { workspace = true } 21 | reqwest = { workspace = true } 22 | dotenv = { workspace = true } 23 | rand = { workspace = true } 24 | tempfile = { workspace = true } 25 | futures = { workspace = true } 26 | tokio-stream = { workspace = true } 27 | parking_lot = { workspace = true } 28 | dashmap = { workspace = true } 29 | tracing = { workspace = true } 30 | 31 | [features] 32 | default = [] 33 | 34 | [dev-dependencies] 35 | wiremock = "0.5" 36 | -------------------------------------------------------------------------------- /swarm_agent/src/lib.rs: -------------------------------------------------------------------------------- 1 | use uuid::Uuid; 2 | use async_trait::async_trait; 3 | use swarm_tool::Tool; 4 | use swarm_llm::{LLMConfig, mock::MockConfig}; 5 | 6 | /// Core trait defining agent capabilities 7 | #[async_trait] 8 | pub trait Agent: Send + Sync { 9 | /// Run the agent on a given task 10 | async fn run(&mut self, task: &str) -> Result; 11 | 12 | /// Get the agent's unique identifier 13 | fn id(&self) -> Uuid; 14 | 15 | /// Get the agent's name 16 | fn name(&self) -> &str; 17 | 18 | /// Get the agent's system prompt 19 | fn system_prompt(&self) -> &str; 20 | 21 | /// Add a tool to the agent 22 | fn add_tool(&mut self, tool: Box); 23 | 24 | /// Get the agent's configuration 25 | fn config(&self) -> &AgentConfig; 26 | } 27 | 28 | /// Configuration for an agent 29 | #[derive(Debug, Clone)] 30 | pub struct AgentConfig { 31 | pub id: Uuid, 32 | pub name: String, 33 | pub system_prompt: String, 34 | pub max_loops: usize, 35 | pub llm_config: Box, // Use Box for trait objects 36 | pub stopping_condition: Option, 37 | pub test_mode: bool, 38 | pub autosave: bool, // Matches Python: autosave=True/False 39 | pub cloud_enabled: bool, 40 | pub cloud_endpoint: Option, 41 | pub cloud_api_key: Option, 42 | pub distributed: bool, // Enable distributed processing 43 | pub wallet_enabled: bool, // Enable wallet-based identity verification 44 | pub wallet_key: Option, // Optional wallet private key 45 | } 46 | 47 | impl Default for AgentConfig { 48 | fn default() -> Self { 49 | Self { 50 | id: Uuid::new_v4(), 51 | name: "default-agent".to_string(), 52 | system_prompt: "You are a helpful AI assistant.".to_string(), 53 | max_loops: 1, 54 | llm_config: Box::new(MockConfig::default()), 55 | stopping_condition: None, 56 | test_mode: cfg!(test), 57 | autosave: false, // Default to false, enable explicitly when needed 58 | cloud_enabled: false, 59 | cloud_endpoint: None, 60 | cloud_api_key: None, 61 | distributed: false, // Default to local processing 62 | wallet_enabled: false, // Default to disabled 63 | wallet_key: None, 64 | } 65 | } 66 | } 67 | 68 | pub mod service; 69 | pub mod mock; 70 | -------------------------------------------------------------------------------- /swarm_agent/src/mock.rs: -------------------------------------------------------------------------------- 1 | //! Mock agent implementation for testing and development 2 | 3 | use super::{Agent, AgentConfig}; 4 | use swarm_tool::Tool; 5 | use swarm_wallet::{Wallet, WalletError, evm::EvmWallet}; 6 | use async_trait::async_trait; 7 | use swarm_llm::{LLM, mock::MockLLM}; 8 | use uuid::Uuid; 9 | 10 | /// Mock agent implementation 11 | pub struct MockAgent { 12 | config: AgentConfig, 13 | llm: MockLLM, 14 | wallet: Option>, 15 | } 16 | 17 | impl MockAgent { 18 | /// Create a new mock agent 19 | pub fn new(config: AgentConfig) -> Self { 20 | Self { 21 | config, 22 | llm: MockLLM::new(), 23 | wallet: Some(Box::new(EvmWallet::new().unwrap())) 24 | } 25 | } 26 | 27 | /// Add wallet-based identity verification 28 | pub fn with_wallet(mut self, wallet: Box) -> Self { 29 | self.wallet = Some(wallet); 30 | self 31 | } 32 | 33 | /// Configure mock responses 34 | pub fn with_responses(mut self, responses: I) -> Self 35 | where 36 | I: IntoIterator, 37 | S: Into, 38 | { 39 | let mut llm = MockLLM::new(); 40 | for (pattern, response) in responses { 41 | llm.add_pattern(pattern, response); 42 | } 43 | self.llm = llm; 44 | self 45 | } 46 | } 47 | 48 | #[async_trait] 49 | impl Agent for MockAgent { 50 | async fn run(&mut self, task: &str) -> Result { 51 | // Generate response using MockLLM 52 | let response = self.llm.generate(task).await.map_err(|e| e.to_string())?; 53 | 54 | // Sign response if identity verification is enabled 55 | if let Some(wallet) = &self.wallet { 56 | let signature = wallet 57 | .sign_message(&response) 58 | .await 59 | .map_err(|e| e.to_string())?; 60 | 61 | Ok(format!( 62 | "Response: {}\nSignature: {}\nAddress: {}", 63 | response, 64 | signature, 65 | wallet.address() 66 | )) 67 | } else { 68 | Ok(response) 69 | } 70 | } 71 | 72 | fn id(&self) -> Uuid { 73 | self.config.id 74 | } 75 | 76 | fn name(&self) -> &str { 77 | &self.config.name 78 | } 79 | 80 | fn system_prompt(&self) -> &str { 81 | &self.config.system_prompt 82 | } 83 | 84 | fn add_tool(&mut self, _tool: Box) { 85 | // Tools not implemented in mock agent 86 | } 87 | 88 | fn config(&self) -> &AgentConfig { 89 | &self.config 90 | } 91 | } 92 | 93 | impl MockAgent { 94 | fn address(&self) -> Option { 95 | match &self.wallet { 96 | Some(wallet) => Some(wallet.address()), 97 | None => None, 98 | } 99 | } 100 | 101 | async fn sign_message(&self, message: &str) -> Result { 102 | if let Some(wallet) = &self.wallet { 103 | wallet 104 | .sign_message(message) 105 | .await 106 | .map_err(|e| WalletError::SigningError(e.to_string())) 107 | } else { 108 | Err(WalletError::KeyError( 109 | "No wallet configured".to_string(), 110 | )) 111 | } 112 | } 113 | 114 | async fn verify_signature( 115 | &self, 116 | message: &str, 117 | signature: &str, 118 | address: &str, 119 | ) -> Result { 120 | if let Some(wallet) = &self.wallet { 121 | wallet 122 | .verify_signature(message, signature, address) 123 | .await 124 | .map_err(|e| WalletError::SigningVerifyError(e.to_string())) 125 | } else { 126 | Err(WalletError::KeyError( 127 | "No wallet configured".to_string(), 128 | )) 129 | } 130 | } 131 | } 132 | 133 | #[cfg(test)] 134 | mod tests { 135 | use swarm_wallet::evm::EvmWallet; 136 | 137 | use crate::{mock::MockAgent, Agent, AgentConfig}; 138 | 139 | 140 | #[tokio::test] 141 | async fn test_mock_agent_run() { 142 | let config = AgentConfig::default(); 143 | let mut agent = MockAgent::new(config); 144 | 145 | let response = agent.run("mockagent task").await.unwrap(); 146 | //println!("mockagent response: {}", response); 147 | assert!(response.contains("MockLLM response")); 148 | } 149 | 150 | #[tokio::test] 151 | async fn test_mock_agent_with_responses() { 152 | let config = AgentConfig::default(); 153 | let mut agent = MockAgent::new(config) 154 | .with_responses(vec![("hello", "Hello, world!"), ("bye", "Goodbye!")]); 155 | 156 | let response = agent.run("say hello").await.unwrap(); 157 | assert!(response.contains("Hello, world!")); 158 | } 159 | 160 | #[tokio::test] 161 | async fn test_mock_agent_with_wallet() { 162 | let config = AgentConfig::default(); 163 | let wallet = EvmWallet::new().unwrap(); 164 | let mut agent = MockAgent::new(config).with_wallet(Box::new(wallet)); 165 | 166 | let response = agent.run("mockagent task").await.unwrap(); 167 | assert!(response.contains("Response:")); 168 | assert!(response.contains("Signature:")); 169 | assert!(response.contains("Address:")); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /swarm_agent/src/service.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use serde::{Deserialize, Serialize}; 3 | use std::{collections::HashMap, time::Duration}; 4 | use uuid::Uuid; 5 | 6 | use crate::{Agent, AgentConfig}; 7 | 8 | /// Service agent configuration 9 | #[derive(Debug, Clone, Serialize, Deserialize)] 10 | pub struct ServiceAgentConfig { 11 | /// Service endpoint URL 12 | pub endpoint: String, 13 | /// Optional API key for service authentication 14 | pub api_key: Option, 15 | /// Request timeout 16 | pub timeout: Duration, 17 | /// Maximum retries for failed requests 18 | pub max_retries: u32, 19 | /// Health check endpoint (optional) 20 | pub health_endpoint: Option, 21 | /// Health check interval in seconds 22 | pub health_check_interval: u64 23 | } 24 | 25 | impl Default for ServiceAgentConfig { 26 | fn default() -> Self { 27 | Self { 28 | endpoint: String::new(), 29 | api_key: None, 30 | timeout: Duration::from_secs(30), 31 | max_retries: 3, 32 | health_endpoint: None, 33 | health_check_interval: 60, 34 | } 35 | } 36 | } 37 | 38 | /// Error types for service agent operations 39 | #[derive(Debug, thiserror::Error)] 40 | pub enum ServiceError { 41 | #[error("Service request failed: {0}")] 42 | RequestFailed(String), 43 | #[error("Service unavailable: {0}")] 44 | ServiceUnavailable(String), 45 | #[error("Authentication failed: {0}")] 46 | AuthenticationFailed(String), 47 | #[error("Identity verification failed: {0}")] 48 | IdentityVerificationFailed(String), 49 | #[error("Task execution failed: {0}")] 50 | TaskExecutionError(String), 51 | #[error("Configuration error: {0}")] 52 | ConfigurationError(String), 53 | #[error("Initialization error: {0}")] 54 | InitializationError(String), 55 | } 56 | 57 | 58 | /// Extended agent trait for service-based implementations 59 | #[async_trait] 60 | pub trait ServiceAgent: Agent { 61 | /// Get service configuration 62 | fn service_config(&self) -> &ServiceAgentConfig; 63 | 64 | /// Check service health 65 | async fn health_check(&self) -> Result; 66 | 67 | /// Sign agent output for verification 68 | async fn sign_message(&self, output: &str) -> Result; 69 | 70 | /// Verify signed output from another agent 71 | async fn verify_message( 72 | &self, 73 | output: &str, 74 | signature: &str, 75 | agent_address: &str, 76 | ) -> Result; 77 | } -------------------------------------------------------------------------------- /swarm_llm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "swarm_llm" 3 | version = "0.1.0" 4 | edition = "2021" 5 | description = "llm traits for the swarms framework" 6 | license = "MIT" 7 | 8 | [dependencies] 9 | tokio = { workspace = true } 10 | async-trait = { workspace = true } 11 | serde = { workspace = true } 12 | serde_json = { workspace = true } 13 | uuid = { workspace = true } 14 | log = { workspace = true } 15 | env_logger = { workspace = true } 16 | thiserror = { workspace = true } 17 | reqwest = { workspace = true } 18 | dotenv = { workspace = true } 19 | rand = { workspace = true } 20 | tempfile = { workspace = true } 21 | futures = { workspace = true } 22 | tokio-stream = { workspace = true } 23 | parking_lot = { workspace = true } 24 | dashmap = { workspace = true } 25 | tracing = { workspace = true } 26 | 27 | [features] 28 | default = [] 29 | 30 | [dev-dependencies] 31 | wiremock = "0.5" 32 | -------------------------------------------------------------------------------- /swarm_llm/src/lib.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use serde::{Deserialize, Serialize}; 3 | use std::fmt; 4 | 5 | /// Error type for LLM operations 6 | #[derive(Debug, Clone, Serialize, Deserialize)] 7 | pub enum LLMError { 8 | ApiError(String), 9 | ConfigError(String), 10 | NetworkError(String), 11 | AuthError(String), 12 | EnvError(String), 13 | } 14 | 15 | impl fmt::Display for LLMError { 16 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 17 | match self { 18 | LLMError::ApiError(msg) => write!(f, "API error: {}", msg), 19 | LLMError::ConfigError(msg) => write!(f, "Configuration error: {}", msg), 20 | LLMError::NetworkError(msg) => write!(f, "Network error: {}", msg), 21 | LLMError::AuthError(msg) => write!(f, "Authentication error: {}", msg), 22 | LLMError::EnvError(msg) => write!(f, "Environment error: {}", msg), 23 | } 24 | } 25 | } 26 | 27 | impl From for String { 28 | fn from(err: LLMError) -> Self { 29 | err.to_string() 30 | } 31 | } 32 | 33 | /// Common interface for LLM configurations 34 | pub trait LLMConfig: std::fmt::Debug + Send + Sync { 35 | fn model_name(&self) -> &str; 36 | fn temperature(&self) -> f32; 37 | fn max_tokens(&self) -> usize; 38 | fn mock_responses(&self) -> bool; 39 | fn clone_box(&self) -> Box; 40 | } 41 | 42 | impl Clone for Box { 43 | fn clone(&self) -> Box { 44 | self.clone_box() 45 | } 46 | } 47 | 48 | /// Core trait for LLM providers 49 | #[async_trait] 50 | pub trait LLM: Send + Sync { 51 | /// Generate text from a prompt 52 | async fn generate(&self, prompt: &str) -> Result; 53 | 54 | /// Get the model name 55 | fn model_name(&self) -> &str; 56 | 57 | /// Get the provider name 58 | fn provider_name(&self) -> &str; 59 | } 60 | 61 | 62 | 63 | 64 | pub mod mock; 65 | pub mod openai; -------------------------------------------------------------------------------- /swarm_llm/src/mock.rs: -------------------------------------------------------------------------------- 1 | //! Mock implementations for testing and examples 2 | 3 | use serde::{Deserialize, Serialize}; 4 | use std::collections::HashMap; 5 | 6 | use super::{LLM, LLMError, LLMConfig}; 7 | use async_trait::async_trait; 8 | 9 | 10 | /// Configuration for mock LLM responses 11 | #[derive(Debug, Clone, Serialize, Deserialize)] 12 | pub struct MockConfig { 13 | //pub model_name: String, 14 | pub temperature: f32, 15 | pub max_tokens: usize, 16 | pub mock_responses: bool, 17 | 18 | /// Default response when no pattern matches 19 | pub default_response: String, 20 | /// Map of prompt patterns to responses 21 | pub response_patterns: HashMap, 22 | /// Whether to include agent name in response 23 | pub include_agent_name: bool, 24 | /// Mock model name 25 | pub model_name: String, 26 | /// Mock provider name 27 | pub provider_name: String, 28 | } 29 | 30 | impl Default for MockConfig { 31 | fn default() -> Self { 32 | Self { 33 | temperature: 0.1, 34 | max_tokens: 1000, 35 | mock_responses: true, 36 | 37 | default_response: "MockLLM response".to_string(), 38 | response_patterns: HashMap::new(), 39 | include_agent_name: true, 40 | model_name: "mockllm-model".to_string(), 41 | provider_name: "mockllm-provider".to_string(), 42 | } 43 | } 44 | } 45 | 46 | impl LLMConfig for MockConfig { 47 | fn model_name(&self) -> &str { 48 | &self.model_name 49 | } 50 | 51 | fn temperature(&self) -> f32 { 52 | self.temperature 53 | } 54 | 55 | fn max_tokens(&self) -> usize { 56 | self.max_tokens 57 | } 58 | 59 | fn mock_responses(&self) -> bool { 60 | self.mock_responses 61 | } 62 | 63 | fn clone_box(&self) -> Box { 64 | Box::new(self.clone()) // Clone the current instance and wrap it in a Box 65 | } 66 | } 67 | 68 | impl MockConfig { 69 | /// Add a response pattern 70 | pub fn add_pattern>(&mut self, pattern: S, response: S) { 71 | self.response_patterns 72 | .insert(pattern.into(), response.into()); 73 | } 74 | 75 | /// Get response for prompt 76 | pub fn get_response(&self, prompt: &str) -> String { 77 | for (pattern, response) in &self.response_patterns { 78 | if prompt.contains(pattern) { 79 | return response.clone(); 80 | } 81 | } 82 | self.default_response.clone() 83 | } 84 | } 85 | 86 | 87 | 88 | /// Mock LLM client for testing and examples 89 | #[derive(Debug, Clone)] 90 | pub struct MockLLM { 91 | config: MockConfig, 92 | } 93 | 94 | impl MockLLM { 95 | /// Create a new MockLLM with default configuration 96 | pub fn new() -> Self { 97 | Self { 98 | config: MockConfig::default(), 99 | } 100 | } 101 | 102 | /// Create a new MockLLM with custom configuration 103 | pub fn with_config(config: MockConfig) -> Self { 104 | Self { config } 105 | } 106 | 107 | /// Add a response pattern 108 | pub fn add_pattern>(&mut self, pattern: S, response: S) { 109 | self.config.add_pattern(pattern, response); 110 | } 111 | } 112 | 113 | impl Default for MockLLM { 114 | fn default() -> Self { 115 | Self::new() 116 | } 117 | } 118 | 119 | #[async_trait] 120 | impl LLM for MockLLM { 121 | async fn generate(&self, prompt: &str) -> Result { 122 | let response = self.config.get_response(prompt); 123 | 124 | if self.config.include_agent_name { 125 | Ok(format!("test-agent: {}", response)) 126 | } else { 127 | Ok(response) 128 | } 129 | } 130 | 131 | fn model_name(&self) -> &str { 132 | &self.config.model_name 133 | } 134 | 135 | fn provider_name(&self) -> &str { 136 | &self.config.provider_name 137 | } 138 | } 139 | 140 | #[cfg(test)] 141 | mod tests { 142 | use super::*; 143 | 144 | #[tokio::test] 145 | async fn test_mock_response_generation() { 146 | let llm = MockLLM::new(); 147 | let response = llm.generate("test prompt").await.unwrap(); 148 | println!("mockllm response: {}", response); 149 | assert!(response.contains("test-agent")); 150 | assert!(response.contains("MockLLM response")); 151 | } 152 | 153 | #[tokio::test] 154 | async fn test_mock_llm_patterns() { 155 | let mut config = MockConfig::default(); 156 | config.add_pattern("hello", "Hello, world!"); 157 | config.add_pattern("bye", "Goodbye!"); 158 | 159 | let llm = MockLLM::with_config(config); 160 | 161 | let response = llm.generate("say hello").await.unwrap(); 162 | assert!(response.contains("Hello, world!")); 163 | 164 | let response = llm.generate("say bye").await.unwrap(); 165 | assert!(response.contains("Goodbye!")); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /swarm_llm/src/openai.rs: -------------------------------------------------------------------------------- 1 | //! OpenAI API client implementation 2 | 3 | use reqwest::Client; 4 | use async_trait::async_trait; 5 | use serde::{Deserialize, Serialize}; 6 | use std::env; 7 | 8 | use crate::{LLM, LLMError, LLMConfig}; 9 | 10 | /// Configuration for OpenAI API calls 11 | #[derive(Debug, Clone, Serialize, Deserialize)] 12 | pub struct OpenAIConfig { 13 | pub model_name: String, 14 | pub temperature: f32, 15 | pub max_tokens: usize, 16 | pub mock_responses: bool, 17 | } 18 | 19 | impl Default for OpenAIConfig { 20 | fn default() -> Self { 21 | Self { 22 | model_name: "gpt-4o-mini".to_string(), 23 | temperature: 0.1, 24 | max_tokens: 1000, 25 | mock_responses: cfg!(test), 26 | } 27 | } 28 | } 29 | 30 | impl LLMConfig for OpenAIConfig { 31 | fn model_name(&self) -> &str { 32 | &self.model_name 33 | } 34 | 35 | fn temperature(&self) -> f32 { 36 | self.temperature 37 | } 38 | 39 | fn max_tokens(&self) -> usize { 40 | self.max_tokens 41 | } 42 | 43 | fn mock_responses(&self) -> bool { 44 | self.mock_responses 45 | } 46 | 47 | fn clone_box(&self) -> Box { 48 | Box::new(self.clone()) // Clone the current instance and wrap it in a Box 49 | } 50 | } 51 | 52 | /// Client for interacting with OpenAI's API 53 | pub struct OpenAIClient { 54 | api_key: String, 55 | client: Client, 56 | config: OpenAIConfig, 57 | } 58 | 59 | impl std::fmt::Debug for OpenAIClient { 60 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 61 | f.debug_struct("OpenAIClient") 62 | .field("api_key", &"[redacted]") 63 | .field("config", &self.config) 64 | .finish() 65 | } 66 | } 67 | 68 | impl OpenAIClient { 69 | /// Create a new OpenAI client with the given configuration 70 | pub fn new(config: OpenAIConfig) -> Result { 71 | // In mock mode, use test key 72 | if config.mock_responses { 73 | return Ok(Self { 74 | api_key: "test-key".to_string(), 75 | client: Client::new(), 76 | config, 77 | }); 78 | } 79 | 80 | // In non-mock mode, require valid API key 81 | match env::var("OPENAI_API_KEY") { 82 | Ok(key) if key.is_empty() => Err(LLMError::ApiError("API key is empty".to_string())), 83 | Ok(key) => Ok(Self { 84 | api_key: key, 85 | client: Client::new(), 86 | config, 87 | }), 88 | Err(e) => Err(LLMError::EnvError(e.to_string())), 89 | } 90 | } 91 | 92 | } 93 | #[async_trait] 94 | impl LLM for OpenAIClient{ 95 | /// Generate a response for the given prompt 96 | async fn generate(&self, prompt: &str) -> Result { 97 | // Return mock response in test mode 98 | if self.config.mock_responses { 99 | return Ok(format!( 100 | "Mock OpenAI response for prompt: {}\n\nAnalysis:\n- ROTH IRA information\n- Tax implications\n- Investment strategies\n- Regulatory requirements", 101 | prompt 102 | )); 103 | } 104 | 105 | // Validate API key 106 | if self.api_key.is_empty() { 107 | return Err(LLMError::ApiError("API key not set".to_string())); 108 | } 109 | 110 | // Make real API call 111 | let response = self 112 | .client 113 | .post("https://api.openai.com/v1/chat/completions") 114 | .header("Authorization", format!("Bearer {}", self.api_key)) 115 | .json(&serde_json::json!({ 116 | "model": self.config.model_name, 117 | "messages": [{"role": "user", "content": prompt}], 118 | "temperature": self.config.temperature, 119 | "max_tokens": self.config.max_tokens 120 | })) 121 | .send() 122 | .await 123 | .map_err(|e| LLMError::NetworkError(e.to_string()))? 124 | .json::() 125 | .await 126 | .map_err(|e| LLMError::NetworkError(e.to_string()))?; 127 | 128 | // Extract response text 129 | response["choices"][0]["message"]["content"] 130 | .as_str() 131 | .map(|s| s.to_string()) 132 | .ok_or_else(|| LLMError::ApiError("Invalid response format".to_string())) 133 | } 134 | 135 | #[doc = " Get the model name"] 136 | fn model_name(&self) -> &str { 137 | todo!() 138 | } 139 | 140 | #[doc = " Get the provider name"] 141 | fn provider_name(&self) -> &str { 142 | todo!() 143 | } 144 | } 145 | 146 | 147 | 148 | 149 | #[cfg(test)] 150 | #[tokio::test] 151 | async fn test_openai_client_creation_without_env() { 152 | // Save original environment 153 | let original_key = env::var("OPENAI_API_KEY").ok(); 154 | env::remove_var("OPENAI_API_KEY"); 155 | 156 | // Test with mock responses enabled (should work without API key) 157 | let config = OpenAIConfig { 158 | mock_responses: true, 159 | ..OpenAIConfig::default() 160 | }; 161 | let result = OpenAIClient::new(config); 162 | assert!(result.is_ok(), "Should succeed with mock_responses=true"); 163 | let client = result.unwrap(); 164 | assert_eq!(client.api_key, "test-key"); 165 | 166 | // Test without mock responses (should fail without API key) 167 | let config = OpenAIConfig { 168 | mock_responses: false, 169 | ..OpenAIConfig::default() 170 | }; 171 | let result = OpenAIClient::new(config); 172 | assert!( 173 | result.is_err(), 174 | "Should fail with mock_responses=false and no API key" 175 | ); 176 | assert!( 177 | matches!(result, Err(LLMError::EnvError(_))), 178 | "Expected EnvError when API key is missing" 179 | ); 180 | 181 | // Test with empty API key 182 | env::set_var("OPENAI_API_KEY", ""); 183 | let config = OpenAIConfig { 184 | mock_responses: false, 185 | ..OpenAIConfig::default() 186 | }; 187 | let result = OpenAIClient::new(config); 188 | assert!(result.is_err(), "Should fail with empty API key"); 189 | assert!( 190 | matches!(result, Err(LLMError::ApiError(_))), 191 | "Expected ApiError with empty API key" 192 | ); 193 | 194 | // Restore original environment 195 | if let Some(key) = original_key { 196 | env::set_var("OPENAI_API_KEY", key); 197 | } else { 198 | env::remove_var("OPENAI_API_KEY"); 199 | } 200 | } 201 | 202 | #[tokio::test] 203 | async fn test_mock_response_generation() { 204 | let config = OpenAIConfig { 205 | mock_responses: true, 206 | ..OpenAIConfig::default() 207 | }; 208 | let client = OpenAIClient::new(config).unwrap(); 209 | 210 | let response = client.generate("Test OpenAI prompt").await.unwrap(); 211 | assert!(response.contains("Mock OpenAI response")); 212 | assert!(response.contains("ROTH IRA")); 213 | } 214 | -------------------------------------------------------------------------------- /swarm_memory/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "swarm_memory" 3 | version = "0.1.0" 4 | edition = "2021" 5 | description = "memory traits for the swarms framework" 6 | license = "MIT" 7 | 8 | [dependencies] 9 | tokio = { workspace = true } 10 | async-trait = { workspace = true } 11 | serde = { workspace = true } 12 | serde_json = { workspace = true } 13 | uuid = { workspace = true } 14 | log = { workspace = true } 15 | env_logger = { workspace = true } 16 | thiserror = { workspace = true } 17 | reqwest = { workspace = true } 18 | dotenv = { workspace = true } 19 | rand = { workspace = true } 20 | tempfile = { workspace = true } 21 | futures = { workspace = true } 22 | tokio-stream = { workspace = true } 23 | parking_lot = { workspace = true } 24 | dashmap = { workspace = true } 25 | tracing = { workspace = true } 26 | 27 | [features] 28 | default = [] 29 | 30 | [dev-dependencies] 31 | wiremock = "0.5" 32 | -------------------------------------------------------------------------------- /swarm_memory/src/chromadb.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use serde::{Deserialize, Serialize}; 3 | use serde_json::Value; 4 | 5 | use super::{MemoryError, VectorStore}; 6 | 7 | /// Configuration for ChromaDB connection 8 | #[derive(Debug, Clone, Serialize, Deserialize)] 9 | pub struct ChromaDBConfig { 10 | pub host: String, 11 | pub port: u16, 12 | pub collection_name: String, 13 | } 14 | 15 | impl Default for ChromaDBConfig { 16 | fn default() -> Self { 17 | Self { 18 | host: "localhost".to_string(), 19 | port: 8000, 20 | collection_name: "default".to_string(), 21 | } 22 | } 23 | } 24 | 25 | /// ChromaDB vector store implementation 26 | pub struct ChromaDBStore { 27 | #[allow(dead_code)] 28 | config: ChromaDBConfig, 29 | } 30 | 31 | impl ChromaDBStore { 32 | pub fn new(config: ChromaDBConfig) -> Result { 33 | if config.host.is_empty() { 34 | return Err(MemoryError::ConfigError("Host cannot be empty".to_string())); 35 | } 36 | if config.port == 0 { 37 | return Err(MemoryError::ConfigError("Port cannot be 0".to_string())); 38 | } 39 | if config.collection_name.is_empty() { 40 | return Err(MemoryError::ConfigError( 41 | "Collection name cannot be empty".to_string(), 42 | )); 43 | } 44 | Ok(Self { config }) 45 | } 46 | } 47 | 48 | #[async_trait] 49 | impl VectorStore for ChromaDBStore { 50 | async fn store( 51 | &mut self, 52 | vectors: Vec, 53 | _metadata: Option, 54 | ) -> Result<(), MemoryError> { 55 | if vectors.is_empty() { 56 | return Err(MemoryError::StoreError( 57 | "Vector list cannot be empty".to_string(), 58 | )); 59 | } 60 | // TODO: Implement actual ChromaDB API calls 61 | // For now, return mock implementation 62 | Ok(()) 63 | } 64 | 65 | async fn query( 66 | &self, 67 | query_vector: Vec, 68 | top_k: usize, 69 | ) -> Result)>, MemoryError> { 70 | if query_vector.is_empty() { 71 | return Err(MemoryError::QueryError( 72 | "Query vector cannot be empty".to_string(), 73 | )); 74 | } 75 | if top_k == 0 { 76 | return Err(MemoryError::QueryError( 77 | "top_k must be greater than 0".to_string(), 78 | )); 79 | } 80 | // TODO: Implement actual ChromaDB API calls 81 | // For now, return mock results 82 | Ok(vec![(1.0, None)]) 83 | } 84 | 85 | async fn delete(&mut self, ids: Vec) -> Result<(), MemoryError> { 86 | if ids.is_empty() { 87 | return Err(MemoryError::DeleteError( 88 | "ID list cannot be empty".to_string(), 89 | )); 90 | } 91 | // TODO: Implement actual ChromaDB API calls 92 | Ok(()) 93 | } 94 | } 95 | 96 | 97 | 98 | #[tokio::test] 99 | async fn test_chromadb_store() { 100 | let config = ChromaDBConfig::default(); 101 | let mut store = ChromaDBStore::new(config).unwrap(); 102 | 103 | // Test store 104 | let vectors = vec![1.0, 2.0, 3.0]; 105 | let result = store.store(vectors.clone(), None).await; 106 | assert!(result.is_ok()); 107 | 108 | // Test query 109 | let results = store.query(vectors, 1).await.unwrap(); 110 | assert_eq!(results.len(), 1); 111 | 112 | // Test delete 113 | let result = store.delete(vec!["test_id".to_string()]).await; 114 | assert!(result.is_ok()); 115 | } 116 | 117 | #[tokio::test] 118 | async fn test_chromadb_errors() { 119 | // Test invalid config 120 | let config = ChromaDBConfig { 121 | host: "".to_string(), 122 | ..ChromaDBConfig::default() 123 | }; 124 | let result = ChromaDBStore::new(config); 125 | assert!(matches!(result, Err(MemoryError::ConfigError(_)))); 126 | 127 | // Test store errors 128 | let mut store = ChromaDBStore::new(ChromaDBConfig::default()).unwrap(); 129 | let result = store.store(vec![], None).await; 130 | assert!(matches!(result, Err(MemoryError::StoreError(_)))); 131 | 132 | // Test query errors 133 | let result = store.query(vec![], 1).await; 134 | assert!(matches!(result, Err(MemoryError::QueryError(_)))); 135 | let result = store.query(vec![1.0], 0).await; 136 | assert!(matches!(result, Err(MemoryError::QueryError(_)))); 137 | 138 | // Test delete errors 139 | let result = store.delete(vec![]).await; 140 | assert!(matches!(result, Err(MemoryError::DeleteError(_)))); 141 | } 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /swarm_memory/src/lib.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use serde_json::Value; 3 | use thiserror::Error; 4 | 5 | /// Error type for memory operations 6 | #[derive(Error, Debug)] 7 | pub enum MemoryError { 8 | #[error("Failed to store vectors: {0}")] 9 | StoreError(String), 10 | 11 | #[error("Failed to query vectors: {0}")] 12 | QueryError(String), 13 | 14 | #[error("Failed to delete vectors: {0}")] 15 | DeleteError(String), 16 | 17 | #[error("Connection error: {0}")] 18 | ConnectionError(String), 19 | 20 | #[error("Invalid configuration: {0}")] 21 | ConfigError(String), 22 | } 23 | 24 | /// Trait for vector storage implementations 25 | #[async_trait] 26 | pub trait VectorStore: Send + Sync { 27 | /// Store vectors with metadata 28 | async fn store( 29 | &mut self, 30 | vectors: Vec, 31 | metadata: Option, 32 | ) -> Result<(), MemoryError>; 33 | 34 | /// Query vectors by similarity 35 | async fn query( 36 | &self, 37 | query_vector: Vec, 38 | top_k: usize, 39 | ) -> Result)>, MemoryError>; 40 | 41 | /// Delete vectors by id 42 | async fn delete(&mut self, ids: Vec) -> Result<(), MemoryError>; 43 | } 44 | 45 | 46 | mod chromadb; 47 | mod pinecone; -------------------------------------------------------------------------------- /swarm_memory/src/pinecone.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use serde::{Deserialize, Serialize}; 3 | use serde_json::Value; 4 | 5 | use super::{MemoryError, VectorStore}; 6 | 7 | /// Configuration for Pinecone connection 8 | #[derive(Debug, Clone, Serialize, Deserialize)] 9 | pub struct PineconeConfig { 10 | pub api_key: String, 11 | pub environment: String, 12 | pub index_name: String, 13 | } 14 | 15 | impl Default for PineconeConfig { 16 | fn default() -> Self { 17 | Self { 18 | api_key: String::new(), 19 | environment: "us-west1-gcp".to_string(), 20 | index_name: "default".to_string(), 21 | } 22 | } 23 | } 24 | 25 | /// Pinecone vector store implementation 26 | pub struct PineconeStore { 27 | #[allow(dead_code)] 28 | config: PineconeConfig, 29 | } 30 | 31 | impl PineconeStore { 32 | pub fn new(config: PineconeConfig) -> Result { 33 | if config.api_key.is_empty() { 34 | return Err(MemoryError::ConfigError( 35 | "API key cannot be empty".to_string(), 36 | )); 37 | } 38 | if config.environment.is_empty() { 39 | return Err(MemoryError::ConfigError( 40 | "Environment cannot be empty".to_string(), 41 | )); 42 | } 43 | if config.index_name.is_empty() { 44 | return Err(MemoryError::ConfigError( 45 | "Index name cannot be empty".to_string(), 46 | )); 47 | } 48 | Ok(Self { config }) 49 | } 50 | } 51 | 52 | #[async_trait] 53 | impl VectorStore for PineconeStore { 54 | async fn store( 55 | &mut self, 56 | vectors: Vec, 57 | _metadata: Option, 58 | ) -> Result<(), MemoryError> { 59 | if vectors.is_empty() { 60 | return Err(MemoryError::StoreError( 61 | "Vector list cannot be empty".to_string(), 62 | )); 63 | } 64 | // TODO: Implement actual Pinecone API calls 65 | // For now, return mock implementation 66 | Ok(()) 67 | } 68 | 69 | async fn query( 70 | &self, 71 | query_vector: Vec, 72 | top_k: usize, 73 | ) -> Result)>, MemoryError> { 74 | if query_vector.is_empty() { 75 | return Err(MemoryError::QueryError( 76 | "Query vector cannot be empty".to_string(), 77 | )); 78 | } 79 | if top_k == 0 { 80 | return Err(MemoryError::QueryError( 81 | "top_k must be greater than 0".to_string(), 82 | )); 83 | } 84 | // TODO: Implement actual Pinecone API calls 85 | // For now, return mock results 86 | Ok(vec![(1.0, None)]) 87 | } 88 | 89 | async fn delete(&mut self, ids: Vec) -> Result<(), MemoryError> { 90 | if ids.is_empty() { 91 | return Err(MemoryError::DeleteError( 92 | "ID list cannot be empty".to_string(), 93 | )); 94 | } 95 | // TODO: Implement actual Pinecone API calls 96 | Ok(()) 97 | } 98 | } 99 | 100 | 101 | #[tokio::test] 102 | async fn test_pinecone_store() { 103 | let mut config = PineconeConfig::default(); 104 | config.api_key = "test-key".to_string(); 105 | let mut store = PineconeStore::new(config).unwrap(); 106 | 107 | // Test store 108 | let vectors = vec![1.0, 2.0, 3.0]; 109 | let result = store.store(vectors.clone(), None).await; 110 | assert!(result.is_ok()); 111 | 112 | // Test query 113 | let results = store.query(vectors, 1).await.unwrap(); 114 | assert_eq!(results.len(), 1); 115 | 116 | // Test delete 117 | let result = store.delete(vec!["test_id".to_string()]).await; 118 | assert!(result.is_ok()); 119 | } 120 | 121 | #[tokio::test] 122 | async fn test_pinecone_errors() { 123 | // Test invalid config 124 | let config = PineconeConfig { 125 | api_key: "".to_string(), 126 | ..PineconeConfig::default() 127 | }; 128 | let result = PineconeStore::new(config); 129 | assert!(matches!(result, Err(MemoryError::ConfigError(_)))); 130 | 131 | // Test store errors 132 | let mut config = PineconeConfig::default(); 133 | config.api_key = "test-key".to_string(); 134 | let mut store = PineconeStore::new(config).unwrap(); 135 | let result = store.store(vec![], None).await; 136 | assert!(matches!(result, Err(MemoryError::StoreError(_)))); 137 | 138 | // Test query errors 139 | let result = store.query(vec![], 1).await; 140 | assert!(matches!(result, Err(MemoryError::QueryError(_)))); 141 | let result = store.query(vec![1.0], 0).await; 142 | assert!(matches!(result, Err(MemoryError::QueryError(_)))); 143 | 144 | // Test delete errors 145 | let result = store.delete(vec![]).await; 146 | assert!(matches!(result, Err(MemoryError::DeleteError(_)))); 147 | } 148 | -------------------------------------------------------------------------------- /swarm_tool/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "swarm_tool" 3 | version = "0.1.0" 4 | edition = "2021" 5 | description = "tool traits for the swarms framework" 6 | license = "MIT" 7 | 8 | [dependencies] 9 | tokio = { workspace = true } 10 | async-trait = { workspace = true } 11 | serde = { workspace = true } 12 | serde_json = { workspace = true } 13 | uuid = { workspace = true } 14 | log = { workspace = true } 15 | env_logger = { workspace = true } 16 | thiserror = { workspace = true } 17 | reqwest = { workspace = true } 18 | dotenv = { workspace = true } 19 | rand = { workspace = true } 20 | tempfile = { workspace = true } 21 | futures = { workspace = true } 22 | tokio-stream = { workspace = true } 23 | parking_lot = { workspace = true } 24 | dashmap = { workspace = true } 25 | tracing = { workspace = true } 26 | 27 | [features] 28 | default = [] 29 | 30 | 31 | -------------------------------------------------------------------------------- /swarm_tool/src/lib.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use serde::{Deserialize, Serialize}; 3 | use std::fmt::Debug; 4 | 5 | 6 | /// Represents a tool that can be used by an agent 7 | pub trait Tool: Send + Sync + Debug{ 8 | fn run(&self, input: &str) -> Result; 9 | fn name(&self) -> &str; 10 | fn description(&self) -> &str; 11 | /// Get the tool's schema for input validation 12 | fn schema(&self) -> &ToolSchema; 13 | } 14 | 15 | /// Schema for tool input validation 16 | #[derive(Debug, Clone, Serialize, Deserialize)] 17 | pub struct ToolSchema { 18 | pub name: String, 19 | pub description: String, 20 | pub parameters: Vec, 21 | } 22 | 23 | /// Parameter definition for tool schema 24 | #[derive(Debug, Clone, Serialize, Deserialize)] 25 | pub struct ToolParameter { 26 | pub name: String, 27 | pub description: String, 28 | pub parameter_type: ParameterType, 29 | pub required: bool, 30 | } 31 | 32 | /// Supported parameter types 33 | #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] 34 | #[serde(rename_all = "lowercase")] 35 | pub enum ParameterType { 36 | String, 37 | Integer, 38 | Float, 39 | Boolean, 40 | Array, 41 | Object, 42 | } -------------------------------------------------------------------------------- /swarm_wallet/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "swarm_wallet" 3 | version = "0.1.0" 4 | edition = "2021" 5 | description = "wallet traits for the swarms framework" 6 | license = "MIT" 7 | 8 | [dependencies] 9 | tokio = { workspace = true } 10 | async-trait = { workspace = true } 11 | serde = { workspace = true } 12 | serde_json = { workspace = true } 13 | uuid = { workspace = true } 14 | log = { workspace = true } 15 | env_logger = { workspace = true } 16 | thiserror = { workspace = true } 17 | reqwest = { workspace = true } 18 | dotenv = { workspace = true } 19 | rand = { workspace = true } 20 | tempfile = { workspace = true } 21 | futures = { workspace = true } 22 | tokio-stream = { workspace = true } 23 | parking_lot = { workspace = true } 24 | dashmap = { workspace = true } 25 | tracing = { workspace = true } 26 | alloy = { workspace = true} 27 | alloy-contract = { workspace = true} 28 | solana-sdk = { workspace = true} 29 | bs58 = { workspace = true} 30 | 31 | [features] 32 | default = [] 33 | 34 | [dev-dependencies] 35 | wiremock = "0.5" 36 | -------------------------------------------------------------------------------- /swarm_wallet/src/evm.rs: -------------------------------------------------------------------------------- 1 | use super::{Wallet, ChainType, WalletError}; 2 | use alloy::hex; 3 | use alloy::primitives::{bytes, Address}; 4 | use alloy::signers::{local::PrivateKeySigner, SignerSync}; 5 | use alloy::signers::{Signer, Signature}; 6 | use async_trait::async_trait; 7 | use std::str::FromStr; 8 | 9 | /// EVM wallet implementation 10 | pub struct EvmWallet { 11 | signer: PrivateKeySigner, 12 | } 13 | 14 | impl EvmWallet { 15 | /// Create a new random wallet 16 | #[allow(dead_code)] 17 | pub fn new() -> Result { 18 | let signer = PrivateKeySigner::random(); 19 | Ok(Self { signer }) 20 | } 21 | 22 | /// Create from private key 23 | #[allow(dead_code)] 24 | pub fn from_private_key(key: &str) -> Result { 25 | PrivateKeySigner::from_str(key) 26 | .map(|signer| Self { signer }) 27 | .map_err(|e| WalletError::KeyError(e.to_string())) 28 | } 29 | } 30 | 31 | #[async_trait] 32 | impl Wallet for EvmWallet { 33 | fn address(&self) -> String { 34 | format!("{:?}", self.signer.address()) 35 | } 36 | 37 | async fn sign_message(&self, message: &str) -> Result { 38 | // Sign the message directly 39 | let signature = self 40 | .signer 41 | .sign_message(message.as_bytes()) 42 | .await 43 | .map_err(|e| WalletError::SigningError(e.to_string()))?; 44 | 45 | // Serialize the signature to hexadecimal 46 | Ok(hex::encode(signature.as_bytes())) // Serialize to hexadecimal 47 | } 48 | 49 | async fn verify_signature( 50 | &self, 51 | message: &str, 52 | signature: &str, 53 | address: &str, 54 | ) -> Result { 55 | // Parse the signature 56 | let sig = Signature::from_str(signature) 57 | .map_err(|e| WalletError::SigningVerifyError(format!("Invalid signature: {}", e)))?; 58 | 59 | // Recover the address from the message and signature 60 | let recovered_address = sig 61 | .recover_address_from_msg(message.as_bytes()) 62 | .map_err(|e| WalletError::SigningVerifyError(format!("Recovery failed: {}", e)))?; 63 | 64 | // Parse the expected address 65 | let expected_address = Address::from_str(address) 66 | .map_err(|e| WalletError::SigningVerifyError(format!("Invalid address: {}", e)))?; 67 | 68 | // Compare the recovered address with the expected address 69 | Ok(recovered_address == expected_address) 70 | } 71 | 72 | fn chain_type(&self) -> ChainType { 73 | ChainType::Evm 74 | } 75 | } 76 | 77 | #[cfg(test)] 78 | mod tests { 79 | use super::*; 80 | 81 | #[tokio::test] 82 | async fn test_evm_wallet_creation() { 83 | let wallet = EvmWallet::new().unwrap(); 84 | assert!(!wallet.address().is_empty()); 85 | } 86 | 87 | #[tokio::test] 88 | async fn test_evm_wallet_signing() { 89 | let wallet = EvmWallet::new().unwrap(); 90 | let message = "Test message signing"; 91 | let signature = wallet.sign_message(message).await.unwrap(); 92 | assert!(!signature.is_empty()); 93 | } 94 | 95 | #[tokio::test] 96 | async fn test_evm_wallet_signing_verify() { 97 | let wallet = EvmWallet::new().unwrap(); 98 | let message = "Test message signing and verification"; 99 | 100 | // Sign the message 101 | let signature = wallet.sign_message(message).await.unwrap(); 102 | println!("Generated Signature: {}", signature); 103 | 104 | // Verify the signature 105 | let verified = wallet 106 | .verify_signature(message, &signature, &wallet.address()) 107 | .await 108 | .unwrap(); 109 | 110 | assert!( 111 | verified, 112 | "Signature verification failed. Signature: {}, Address: {}", 113 | signature, 114 | wallet.address() 115 | ); 116 | } 117 | } -------------------------------------------------------------------------------- /swarm_wallet/src/lib.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use serde::{Deserialize, Serialize}; 3 | use thiserror::Error; 4 | 5 | /// Core trait for wallet implementations 6 | #[async_trait] 7 | pub trait Wallet: Send + Sync { 8 | /// Get wallet address 9 | fn address(&self) -> String; 10 | 11 | /// Sign a message 12 | async fn sign_message(&self, message: &str) -> Result; 13 | 14 | /// Verify a signature 15 | async fn verify_signature( 16 | &self, 17 | message: &str, 18 | signature: &str, 19 | address: &str, 20 | ) -> Result; 21 | 22 | /// Get chain type 23 | fn chain_type(&self) -> ChainType; 24 | } 25 | 26 | /// Supported chain types 27 | #[derive(Debug, Clone, Serialize, Deserialize)] 28 | pub enum ChainType { 29 | Evm, 30 | Solana, 31 | } 32 | 33 | 34 | /// Error types for wallet operations 35 | #[derive(Debug, Error)] 36 | pub enum WalletError { 37 | #[error("Wallet Key error: {0}")] 38 | KeyError(String), 39 | #[error("Wallet Signing error: {0}")] 40 | SigningError(String), 41 | #[error("Wallet Signing Verify error: {0}")] 42 | SigningVerifyError(String), 43 | #[error("Wallet Chain error: {0}")] 44 | ChainError(String), 45 | } 46 | 47 | pub mod evm; 48 | pub mod solana; -------------------------------------------------------------------------------- /swarm_wallet/src/solana.rs: -------------------------------------------------------------------------------- 1 | use super::{Wallet, ChainType, WalletError}; 2 | use solana_sdk::{ 3 | signature::{Keypair, Signer as SolanaSigner, Signature}, 4 | pubkey::Pubkey, 5 | message::Message, 6 | }; 7 | use async_trait::async_trait; 8 | use std::str::FromStr; 9 | 10 | /// Solana wallet implementation 11 | pub struct SolanaWallet { 12 | signer: Keypair, 13 | } 14 | 15 | impl SolanaWallet { 16 | /// Create a new random wallet 17 | #[allow(dead_code)] 18 | pub fn new() -> Result { 19 | let signer = Keypair::new(); 20 | Ok(Self { signer }) 21 | } 22 | 23 | /// Create from private key 24 | #[allow(dead_code)] 25 | pub fn from_private_key(key: &str) -> Result { 26 | let key_bytes = bs58::decode(key) 27 | .into_vec() 28 | .map_err(|e| WalletError::KeyError(format!("Invalid private key: {}", e)))?; 29 | let signer = Keypair::from_bytes(&key_bytes) 30 | .map_err(|e| WalletError::KeyError(format!("Failed to create keypair: {}", e)))?; 31 | Ok(Self { signer }) 32 | } 33 | } 34 | 35 | #[async_trait] 36 | impl Wallet for SolanaWallet { 37 | fn address(&self) -> String { 38 | self.signer.pubkey().to_string() 39 | } 40 | 41 | async fn sign_message(&self, message: &str) -> Result { 42 | let message_bytes = message.as_bytes(); 43 | let signature = self 44 | .signer 45 | .try_sign_message(message_bytes) 46 | .map_err(|e| WalletError::SigningError(format!("Failed to sign message: {}", e)))?; 47 | Ok(signature.to_string()) 48 | } 49 | 50 | async fn verify_signature( 51 | &self, 52 | message: &str, 53 | signature: &str, 54 | address: &str, 55 | ) -> Result { 56 | let message_bytes = message.as_bytes(); 57 | let signature = Signature::from_str(signature) 58 | .map_err(|e| WalletError::SigningVerifyError(format!("Invalid signature: {}", e)))?; 59 | let pubkey = Pubkey::from_str(address) 60 | .map_err(|e| WalletError::SigningVerifyError(format!("Invalid address: {}", e)))?; 61 | Ok(signature.verify(pubkey.as_ref(), message_bytes)) 62 | } 63 | 64 | fn chain_type(&self) -> ChainType { 65 | ChainType::Solana 66 | } 67 | } 68 | 69 | #[cfg(test)] 70 | mod tests { 71 | use super::*; 72 | 73 | #[tokio::test] 74 | async fn test_solana_wallet_creation() { 75 | let wallet = SolanaWallet::new().unwrap(); 76 | assert!(!wallet.address().is_empty()); 77 | } 78 | 79 | #[tokio::test] 80 | async fn test_solana_wallet_signing() { 81 | let wallet = SolanaWallet::new().unwrap(); 82 | let message = "Test message signing"; 83 | let signature = wallet.sign_message(message).await.unwrap(); 84 | assert!(!signature.is_empty()); 85 | } 86 | 87 | #[tokio::test] 88 | async fn test_solana_wallet_signing_verify() { 89 | let wallet = SolanaWallet::new().unwrap(); 90 | let message = "Test message signing and verification"; 91 | let signature = wallet.sign_message(message).await.unwrap(); 92 | let verified = wallet 93 | .verify_signature(&message, &signature, &wallet.address()) 94 | .await 95 | .unwrap(); 96 | assert!(verified); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /swarms/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "swarms" 3 | version = "0.1.0" 4 | edition = "2021" 5 | description = "swarms traits for the swarms framework" 6 | license = "MIT" 7 | 8 | [dependencies] 9 | swarm_tool = { path = "../swarm_tool" } 10 | swarm_llm = { path = "../swarm_llm" } 11 | swarm_wallet = { path = "../swarm_wallet" } 12 | swarm_memory = { path = "../swarm_memory" } 13 | swarm_agent = { path = "../swarm_agent" } 14 | tokio = { workspace = true } 15 | async-trait = { workspace = true } 16 | serde = { workspace = true } 17 | serde_json = { workspace = true } 18 | uuid = { workspace = true } 19 | log = { workspace = true } 20 | env_logger = { workspace = true } 21 | thiserror = { workspace = true } 22 | reqwest = { workspace = true } 23 | dotenv = { workspace = true } 24 | rand = { workspace = true } 25 | tempfile = { workspace = true } 26 | futures = { workspace = true } 27 | tokio-stream = { workspace = true } 28 | parking_lot = { workspace = true } 29 | dashmap = { workspace = true } 30 | tracing = { workspace = true } 31 | 32 | [features] 33 | default = [] 34 | 35 | [dev-dependencies] 36 | wiremock = "0.5" 37 | -------------------------------------------------------------------------------- /swarms/src/architectures/circular.rs: -------------------------------------------------------------------------------- 1 | use swarm_agent::Agent; 2 | 3 | /// Implements a circular swarm where agents pass tasks in a circular manner. 4 | pub async fn circular_swarm( 5 | agents: &mut [A], 6 | tasks: &[String], 7 | ) -> Result, String> { 8 | let mut results = Vec::new(); 9 | 10 | // Ensure we have agents and tasks 11 | if agents.is_empty() || tasks.is_empty() { 12 | return Err("Agents and tasks lists cannot be empty.".to_string()); 13 | } 14 | 15 | // Process each task through all agents in a circular pattern 16 | for task in tasks { 17 | for agent in agents.iter_mut() { 18 | match agent.run(task).await { 19 | Ok(response) => results.push(response), 20 | Err(e) => return Err(format!("Agent error: {}", e)), 21 | } 22 | } 23 | } 24 | 25 | Ok(results) 26 | } 27 | 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use swarm_agent::{AgentConfig, mock::MockAgent}; 32 | 33 | use super::*; 34 | 35 | #[tokio::test] 36 | async fn test_circular_swarm() { 37 | let config = AgentConfig { 38 | name: "test-agent".to_string(), 39 | ..AgentConfig::default() 40 | }; 41 | 42 | let mut agents = vec![ 43 | MockAgent::new(config.clone()), 44 | MockAgent::new(config.clone()), 45 | ]; 46 | 47 | let tasks = vec!["Task 1".to_string(), "Task 2".to_string()]; 48 | 49 | let result = circular_swarm(&mut agents, &tasks).await.unwrap(); 50 | assert_eq!(result.len(), 4); // 2 agents * 2 tasks 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /swarms/src/architectures/fibonacci.rs: -------------------------------------------------------------------------------- 1 | use swarm_agent::Agent; 2 | 3 | /// Implements a Fibonacci swarm where agents are arranged according to Fibonacci sequence 4 | pub async fn fibonacci_swarm( 5 | agents: &mut [A], 6 | tasks: &[String], 7 | ) -> Result, String> { 8 | let mut results = Vec::new(); 9 | 10 | if agents.is_empty() || tasks.is_empty() { 11 | return Err("Agents and tasks lists cannot be empty.".to_string()); 12 | } 13 | 14 | // Generate Fibonacci sequence up to agents.len() 15 | let mut fib = vec![1, 1]; 16 | while fib.last().unwrap() < &agents.len() { 17 | let next = fib[fib.len() - 1] + fib[fib.len() - 2]; 18 | if next >= agents.len() { 19 | break; 20 | } 21 | fib.push(next); 22 | } 23 | 24 | // Process tasks according to Fibonacci pattern 25 | let mut task_iter = tasks.iter(); 26 | for &fib_num in &fib { 27 | if let Some(task) = task_iter.next() { 28 | if fib_num < agents.len() { 29 | match agents[fib_num].run(task).await { 30 | Ok(response) => results.push(response), 31 | Err(e) => return Err(format!("Agent error: {}", e)), 32 | } 33 | } 34 | } 35 | } 36 | 37 | Ok(results) 38 | } 39 | 40 | #[cfg(test)] 41 | mod tests { 42 | use swarm_agent::{AgentConfig, mock::MockAgent}; 43 | use super::*; 44 | 45 | #[tokio::test] 46 | async fn test_fibonacci_swarm() { 47 | let config = AgentConfig::default(); 48 | let mut agents: Vec<_> = (0..5) 49 | .map(|_| MockAgent::new(config.clone())) 50 | .collect(); 51 | 52 | let tasks = vec![ 53 | "Task 1".to_string(), 54 | "Task 2".to_string(), 55 | "Task 3".to_string(), 56 | ]; 57 | 58 | let result = fibonacci_swarm(&mut agents, &tasks).await.unwrap(); 59 | assert!(!result.is_empty()); 60 | // Should process tasks at indices 1, 1, 2, 3 (Fibonacci sequence) 61 | assert!(result.len() <= tasks.len()); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /swarms/src/architectures/geometric.rs: -------------------------------------------------------------------------------- 1 | use swarm_agent::Agent; 2 | 3 | /// Implements a geometric swarm where agents are arranged according to geometric progression 4 | pub async fn geometric_swarm( 5 | agents: &mut [A], 6 | tasks: &[String], 7 | ) -> Result, String> { 8 | let mut results = Vec::new(); 9 | 10 | if agents.is_empty() || tasks.is_empty() { 11 | return Err("Agents and tasks lists cannot be empty.".to_string()); 12 | } 13 | 14 | let ratio: f32 = 2.0; // Common ratio for geometric progression 15 | let mut task_iter = tasks.iter(); 16 | 17 | // Process tasks using geometric progression indices 18 | for i in 0..agents.len() { 19 | let index = (ratio.powi(i as i32)) as usize; 20 | if index < agents.len() { 21 | if let Some(task) = task_iter.next() { 22 | match agents[index].run(task).await { 23 | Ok(response) => results.push(response), 24 | Err(e) => return Err(format!("Agent error: {}", e)), 25 | } 26 | } 27 | } 28 | } 29 | 30 | Ok(results) 31 | } 32 | 33 | 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use swarm_agent::{AgentConfig, mock::MockAgent}; 38 | use super::*; 39 | 40 | #[tokio::test] 41 | async fn test_geometric_swarm() { 42 | let config = AgentConfig::default(); 43 | let mut agents: Vec<_> = (0..8) 44 | .map(|_| MockAgent::new(config.clone())) 45 | .collect(); 46 | 47 | let tasks = vec![ 48 | "Task 1".to_string(), 49 | "Task 2".to_string(), 50 | "Task 3".to_string(), 51 | ]; 52 | 53 | let result = geometric_swarm(&mut agents, &tasks).await.unwrap(); 54 | assert!(!result.is_empty()); 55 | // Should process tasks at indices following geometric progression (1, 2, 4) 56 | assert!(result.len() <= tasks.len()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /swarms/src/architectures/graph_swarm.rs: -------------------------------------------------------------------------------- 1 | //! Graph Swarm architecture implementation 2 | //! 3 | //! This module implements the Graph Swarm pattern where agents are organized in a 4 | //! graph structure with defined connections between nodes, similar to the Python 5 | //! implementation in docs.swarms.world. 6 | 7 | use swarm_agent::Agent; 8 | use std::collections::{HashMap, HashSet}; 9 | 10 | /// Represents a node in the agent graph 11 | #[derive(Debug)] 12 | struct GraphNode { 13 | connections: HashSet, 14 | } 15 | 16 | /// Implements a Graph Swarm where agents are connected in a network structure 17 | pub async fn graph_swarm( 18 | agents: &mut [A], 19 | tasks: &[String], 20 | adjacency_list: Option>>, 21 | ) -> Result, String> { 22 | let mut results = Vec::new(); 23 | 24 | if agents.is_empty() || tasks.is_empty() { 25 | return Err("Agents and tasks lists cannot be empty.".to_string()); 26 | } 27 | 28 | // Build graph structure 29 | let mut nodes: HashMap = HashMap::new(); 30 | 31 | // If no adjacency list provided, create fully connected graph 32 | let connections = match adjacency_list { 33 | Some(adj_list) => { 34 | if adj_list.len() != agents.len() { 35 | return Err("Adjacency list must match number of agents.".to_string()); 36 | } 37 | adj_list 38 | } 39 | None => { 40 | // Create fully connected graph by default 41 | (0..agents.len()) 42 | .map(|i| { 43 | (0..agents.len()) 44 | .filter(|&j| j != i) 45 | .collect::>() 46 | }) 47 | .collect() 48 | } 49 | }; 50 | 51 | // Initialize graph nodes 52 | for (i, connected_nodes) in connections.iter().enumerate() { 53 | nodes.insert( 54 | i, 55 | GraphNode { 56 | connections: connected_nodes.iter().copied().collect(), 57 | }, 58 | ); 59 | } 60 | 61 | // Process tasks through the graph network 62 | for task in tasks { 63 | let mut processed = HashSet::new(); 64 | let mut current_nodes: HashSet = vec![0].into_iter().collect(); // Start with first node 65 | 66 | while !current_nodes.is_empty() { 67 | let mut next_nodes = HashSet::new(); 68 | 69 | // Process current level nodes 70 | for &node_idx in ¤t_nodes { 71 | if processed.contains(&node_idx) { 72 | continue; 73 | } 74 | 75 | // Process task with current agent 76 | match agents[node_idx].run(task).await { 77 | Ok(response) => results.push(response), 78 | Err(e) => return Err(format!("Agent error: {}", e)), 79 | } 80 | 81 | processed.insert(node_idx); 82 | 83 | // Add connected nodes to next level 84 | if let Some(node) = nodes.get(&node_idx) { 85 | next_nodes.extend(&node.connections); 86 | } 87 | } 88 | 89 | current_nodes = next_nodes; 90 | } 91 | } 92 | 93 | Ok(results) 94 | } 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | #[cfg(test)] 103 | mod tests { 104 | use swarm_agent::{AgentConfig, mock::MockAgent}; 105 | use super::*; 106 | 107 | #[tokio::test] 108 | async fn test_graph_swarm() { 109 | let config = AgentConfig::default(); 110 | let mut agents = vec![ 111 | MockAgent::new( 112 | AgentConfig { 113 | name: "Node1".to_string(), 114 | ..config.clone() 115 | } 116 | ), 117 | MockAgent::new( 118 | AgentConfig { 119 | name: "Node2".to_string(), 120 | ..config.clone() 121 | } 122 | ), 123 | MockAgent::new( 124 | AgentConfig { 125 | name: "Node3".to_string(), 126 | ..config 127 | } 128 | ), 129 | ]; 130 | 131 | let tasks = vec!["Test task".to_string()]; 132 | 133 | // Test with custom adjacency list (1->2->3 chain) 134 | let adj_list = vec![ 135 | vec![1], // Node 0 connected to 1 136 | vec![2], // Node 1 connected to 2 137 | vec![], // Node 2 has no outgoing connections 138 | ]; 139 | 140 | let results = graph_swarm(&mut agents, &tasks, Some(adj_list)) 141 | .await 142 | .unwrap(); 143 | assert_eq!(results.len(), 3); 144 | 145 | // Test with default fully connected graph 146 | let results = graph_swarm(&mut agents, &tasks, None) 147 | .await 148 | .unwrap(); 149 | assert_eq!(results.len(), 3); 150 | } 151 | 152 | #[tokio::test] 153 | async fn test_graph_swarm_empty_input() { 154 | let mut empty_agents: Vec = vec![]; 155 | let tasks = vec!["Task".to_string()]; 156 | assert!(graph_swarm(&mut empty_agents, &tasks, None).await.is_err()); 157 | 158 | let config = AgentConfig::default(); 159 | let mut agents = vec![MockAgent::new(config)]; 160 | let empty_tasks: Vec = vec![]; 161 | assert!(graph_swarm(&mut agents, &empty_tasks, None).await.is_err()); 162 | } 163 | 164 | #[tokio::test] 165 | async fn test_graph_swarm_invalid_adjacency() { 166 | let config = AgentConfig::default(); 167 | let mut agents = vec![MockAgent::new(config)]; 168 | let tasks = vec!["Task".to_string()]; 169 | 170 | // Test with mismatched adjacency list length 171 | let invalid_adj_list = vec![vec![1], vec![0]]; // Two nodes for one agent 172 | assert!(graph_swarm(&mut agents, &tasks, Some(invalid_adj_list)) 173 | .await 174 | .is_err()); 175 | } 176 | 177 | } -------------------------------------------------------------------------------- /swarms/src/architectures/grid.rs: -------------------------------------------------------------------------------- 1 | use swarm_agent::Agent; 2 | 3 | /// Implements a grid swarm where agents are arranged in a square grid pattern 4 | pub async fn grid_swarm( 5 | agents: &mut [A], 6 | tasks: &[String], 7 | ) -> Result, String> { 8 | let mut results = Vec::new(); 9 | 10 | if agents.is_empty() || tasks.is_empty() { 11 | return Err("Agents and tasks lists cannot be empty.".to_string()); 12 | } 13 | 14 | // Calculate grid size (assuming square grid) 15 | let grid_size = (agents.len() as f64).sqrt() as usize; 16 | if grid_size * grid_size != agents.len() { 17 | return Err("Number of agents must form a perfect square.".to_string()); 18 | } 19 | 20 | let mut task_iter = tasks.iter(); 21 | for i in 0..grid_size { 22 | for j in 0..grid_size { 23 | if let Some(task) = task_iter.next() { 24 | match agents[i * grid_size + j].run(task).await { 25 | Ok(response) => results.push(response), 26 | Err(e) => return Err(format!("Agent error: {}", e)), 27 | } 28 | } 29 | } 30 | } 31 | 32 | Ok(results) 33 | } 34 | 35 | 36 | 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use swarm_agent::{AgentConfig, mock::MockAgent}; 41 | use super::*; 42 | 43 | #[tokio::test] 44 | async fn test_grid_swarm() { 45 | let config = AgentConfig::default(); 46 | let mut agents: Vec<_> = (0..4) 47 | .map(|_| MockAgent::new(config.clone())) 48 | .collect(); 49 | 50 | let tasks = vec![ 51 | "Task 1".to_string(), 52 | "Task 2".to_string(), 53 | "Task 3".to_string(), 54 | "Task 4".to_string(), 55 | ]; 56 | 57 | let result = grid_swarm(&mut agents, &tasks).await.unwrap(); 58 | assert_eq!(result.len(), 4); // 2x2 grid, 4 tasks 59 | } 60 | 61 | #[tokio::test] 62 | async fn test_grid_swarm_invalid_size() { 63 | let config = AgentConfig::default(); 64 | let mut agents: Vec<_> = (0..3) 65 | .map(|_| MockAgent::new(config.clone())) 66 | .collect(); 67 | 68 | let tasks = vec!["Task 1".to_string()]; 69 | 70 | let result = grid_swarm(&mut agents, &tasks).await; 71 | assert!(result.is_err()); // 3 agents can't form a square grid 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /swarms/src/architectures/harmonic.rs: -------------------------------------------------------------------------------- 1 | use swarm_agent::Agent; 2 | 3 | /// Implements a harmonic swarm where agents are arranged according to harmonic series 4 | pub async fn harmonic_swarm( 5 | agents: &mut [A], 6 | tasks: &[String], 7 | ) -> Result, String> { 8 | let mut results = Vec::new(); 9 | 10 | if agents.is_empty() || tasks.is_empty() { 11 | return Err("Agents and tasks lists cannot be empty.".to_string()); 12 | } 13 | 14 | let mut task_iter = tasks.iter(); 15 | 16 | // Process tasks using harmonic series indices (1/1, 1/2, 1/3, ...) 17 | for i in 1..=agents.len() { 18 | let index = (agents.len() as f64 / i as f64) as usize; 19 | if index < agents.len() { 20 | if let Some(task) = task_iter.next() { 21 | match agents[index].run(task).await { 22 | Ok(response) => results.push(response), 23 | Err(e) => return Err(format!("Agent error: {}", e)), 24 | } 25 | } 26 | } 27 | } 28 | 29 | Ok(results) 30 | } 31 | 32 | 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use swarm_agent::{AgentConfig, mock::MockAgent}; 37 | use super::*; 38 | 39 | #[tokio::test] 40 | async fn test_harmonic_swarm() { 41 | let config = AgentConfig::default(); 42 | let mut agents: Vec<_> = (0..6) 43 | .map(|_| MockAgent::new(config.clone())) 44 | .collect(); 45 | 46 | let tasks = vec![ 47 | "Task 1".to_string(), 48 | "Task 2".to_string(), 49 | "Task 3".to_string(), 50 | ]; 51 | 52 | let result = harmonic_swarm(&mut agents, &tasks).await.unwrap(); 53 | assert!(!result.is_empty()); 54 | // Should process tasks at indices following harmonic series 55 | assert!(result.len() <= tasks.len()); 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /swarms/src/architectures/linear.rs: -------------------------------------------------------------------------------- 1 | use swarm_agent::Agent; 2 | 3 | /// Implements a linear swarm where agents process tasks sequentially 4 | pub async fn linear_swarm( 5 | agents: &mut [A], 6 | tasks: &[String], 7 | ) -> Result, String> { 8 | let mut results = Vec::new(); 9 | 10 | if agents.is_empty() || tasks.is_empty() { 11 | return Err("Agents and tasks lists cannot be empty.".to_string()); 12 | } 13 | 14 | // Each agent processes one task in sequence 15 | let mut task_iter = tasks.iter(); 16 | for agent in agents.iter_mut() { 17 | if let Some(task) = task_iter.next() { 18 | match agent.run(task).await { 19 | Ok(response) => results.push(response), 20 | Err(e) => return Err(format!("Agent error: {}", e)), 21 | } 22 | } 23 | } 24 | 25 | Ok(results) 26 | } 27 | 28 | 29 | 30 | #[cfg(test)] 31 | mod tests { 32 | use swarm_agent::{AgentConfig, mock::MockAgent}; 33 | use super::*; 34 | 35 | #[tokio::test] 36 | async fn test_linear_swarm() { 37 | let config = AgentConfig::default(); 38 | let mut agents = vec![ 39 | MockAgent::new(config.clone()), 40 | MockAgent::new(config.clone()), 41 | ]; 42 | 43 | let tasks = vec!["Task 1".to_string(), "Task 2".to_string()]; 44 | 45 | let result = linear_swarm(&mut agents, &tasks).await.unwrap(); 46 | assert_eq!(result.len(), 2); // Each agent processes one task 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /swarms/src/architectures/mesh.rs: -------------------------------------------------------------------------------- 1 | use swarm_agent::Agent; 2 | 3 | /// Implements a mesh swarm where agents work on tasks from a shared queue 4 | pub async fn mesh_swarm( 5 | agents: &mut [A], 6 | tasks: &[String], 7 | ) -> Result, String> { 8 | let mut results = Vec::new(); 9 | 10 | if agents.is_empty() || tasks.is_empty() { 11 | return Err("Agents and tasks lists cannot be empty.".to_string()); 12 | } 13 | 14 | // Process tasks using all agents in a mesh pattern 15 | let mut task_queue: Vec<_> = tasks.iter().collect(); 16 | while !task_queue.is_empty() { 17 | for agent in agents.iter_mut() { 18 | if let Some(task) = task_queue.first() { 19 | match agent.run(task).await { 20 | Ok(response) => results.push(response), 21 | Err(e) => return Err(format!("Agent error: {}", e)), 22 | } 23 | } 24 | } 25 | if !task_queue.is_empty() { 26 | task_queue.remove(0); 27 | } 28 | } 29 | 30 | Ok(results) 31 | } 32 | 33 | 34 | 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use swarm_agent::{AgentConfig, mock::MockAgent}; 39 | use super::*; 40 | 41 | #[tokio::test] 42 | async fn test_mesh_swarm() { 43 | let config = AgentConfig::default(); 44 | let mut agents = vec![ 45 | MockAgent::new(config.clone()), 46 | MockAgent::new(config.clone()), 47 | ]; 48 | 49 | let tasks = vec!["Task 1".to_string(), "Task 2".to_string()]; 50 | 51 | let result = mesh_swarm(&mut agents, &tasks).await.unwrap(); 52 | assert_eq!(result.len(), 4); // 2 agents * 2 tasks 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /swarms/src/architectures/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod linear; 2 | pub mod circular; 3 | pub mod fibonacci; 4 | pub mod geometric; 5 | pub mod graph_swarm; 6 | pub mod grid; 7 | pub mod harmonic; 8 | pub mod mesh; 9 | pub mod patterns; 10 | pub mod prime; 11 | pub mod pyramid; 12 | pub mod queue_swarm; 13 | pub mod round_robin; 14 | pub mod star; 15 | pub mod tree_swarm; -------------------------------------------------------------------------------- /swarms/src/architectures/patterns.rs: -------------------------------------------------------------------------------- 1 | //! Mathematical and pattern-based swarm architectures 2 | 3 | use swarm_agent::Agent; 4 | use std::f64::consts::PI; 5 | 6 | /// Power-law distribution swarm 7 | pub async fn power_swarm( 8 | agents: &mut [A], 9 | tasks: &[String], 10 | ) -> Result, String> { 11 | let mut results = Vec::new(); 12 | 13 | if agents.is_empty() || tasks.is_empty() { 14 | return Err("Agents and tasks lists cannot be empty.".to_string()); 15 | } 16 | 17 | let agents_len = agents.len(); 18 | for (i, agent) in agents.iter_mut().enumerate() { 19 | let power_idx = 2_u32.pow(i as u32) as usize; 20 | if power_idx < agents_len && !tasks.is_empty() { 21 | match agent.run(&tasks[0]).await { 22 | Ok(response) => results.push(response), 23 | Err(e) => return Err(format!("Agent error: {}", e)), 24 | } 25 | } 26 | } 27 | 28 | Ok(results) 29 | } 30 | 31 | /// Logarithmic distribution swarm 32 | pub async fn log_swarm( 33 | agents: &mut [A], 34 | tasks: &[String], 35 | ) -> Result, String> { 36 | let mut results = Vec::new(); 37 | 38 | if agents.is_empty() || tasks.is_empty() { 39 | return Err("Agents and tasks lists cannot be empty.".to_string()); 40 | } 41 | 42 | let agents_len = agents.len(); 43 | for (i, agent) in agents.iter_mut().enumerate() { 44 | let log_idx = ((i + 1) as f64).ln() as usize; 45 | if log_idx < agents_len && !tasks.is_empty() { 46 | match agent.run(&tasks[0]).await { 47 | Ok(response) => results.push(response), 48 | Err(e) => return Err(format!("Agent error: {}", e)), 49 | } 50 | } 51 | } 52 | 53 | Ok(results) 54 | } 55 | 56 | /// Exponential distribution swarm 57 | pub async fn exponential_swarm( 58 | agents: &mut [A], 59 | tasks: &[String], 60 | ) -> Result, String> { 61 | let mut results = Vec::new(); 62 | 63 | if agents.is_empty() || tasks.is_empty() { 64 | return Err("Agents and tasks lists cannot be empty.".to_string()); 65 | } 66 | 67 | let agents_len = agents.len(); 68 | for (i, agent) in agents.iter_mut().enumerate() { 69 | let exp_idx = ((i as f64) * 0.5).exp() as usize; 70 | if exp_idx < agents_len && !tasks.is_empty() { 71 | match agent.run(&tasks[0]).await { 72 | Ok(response) => results.push(response), 73 | Err(e) => return Err(format!("Agent error: {}", e)), 74 | } 75 | } 76 | } 77 | 78 | Ok(results) 79 | } 80 | 81 | /// Staircase pattern swarm 82 | pub async fn staircase_swarm( 83 | agents: &mut [A], 84 | task: &str, 85 | ) -> Result, String> { 86 | let mut results = Vec::new(); 87 | 88 | if agents.is_empty() { 89 | return Err("Agents list cannot be empty.".to_string()); 90 | } 91 | 92 | let step_size = agents.len() / 5; 93 | if step_size == 0 { 94 | return Err("Not enough agents for staircase pattern".to_string()); 95 | } 96 | 97 | for i in 0..agents.len() { 98 | let step_idx = (i / step_size) * step_size; 99 | if step_idx < agents.len() { 100 | match agents[step_idx].run(task).await { 101 | Ok(response) => results.push(response), 102 | Err(e) => return Err(format!("Agent error: {}", e)), 103 | } 104 | } 105 | } 106 | 107 | Ok(results) 108 | } 109 | 110 | /// Sigmoid pattern swarm 111 | pub async fn sigmoid_swarm(agents: &mut [A], task: &str) -> Result, String> { 112 | let mut results = Vec::new(); 113 | 114 | if agents.is_empty() { 115 | return Err("Agents list cannot be empty.".to_string()); 116 | } 117 | 118 | for i in 0..agents.len() { 119 | let sigmoid = 1.0 / (1.0 + (-((i as f64) - (agents.len() as f64 / 2.0))).exp()); 120 | let idx = (sigmoid * (agents.len() as f64 - 1.0)) as usize; 121 | 122 | match agents[idx].run(task).await { 123 | Ok(response) => results.push(response), 124 | Err(e) => return Err(format!("Agent error: {}", e)), 125 | } 126 | } 127 | 128 | Ok(results) 129 | } 130 | 131 | /// Sinusoidal pattern swarm 132 | pub async fn sinusoidal_swarm( 133 | agents: &mut [A], 134 | task: &str, 135 | ) -> Result, String> { 136 | let mut results = Vec::new(); 137 | 138 | if agents.is_empty() { 139 | return Err("Agents list cannot be empty.".to_string()); 140 | } 141 | 142 | for i in 0..agents.len() { 143 | let sin_val = ((i as f64) * 2.0 * PI / (agents.len() as f64)).sin(); 144 | let idx = ((sin_val + 1.0) / 2.0 * (agents.len() as f64 - 1.0)) as usize; 145 | 146 | match agents[idx].run(task).await { 147 | Ok(response) => results.push(response), 148 | Err(e) => return Err(format!("Agent error: {}", e)), 149 | } 150 | } 151 | 152 | Ok(results) 153 | } 154 | 155 | 156 | 157 | 158 | 159 | 160 | #[cfg(test)] 161 | mod tests { 162 | use swarm_agent::{AgentConfig, mock::MockAgent}; 163 | use super::*; 164 | 165 | #[tokio::test] 166 | async fn test_pattern_swarms() { 167 | let config = AgentConfig::default(); 168 | let mut agents: Vec<_> = (0..5) 169 | .map(|_| MockAgent::new(config.clone())) 170 | .collect(); 171 | 172 | let tasks = vec!["Test task".to_string()]; 173 | 174 | // Test each pattern 175 | let patterns = [ 176 | power_swarm(&mut agents, &tasks).await, 177 | log_swarm(&mut agents, &tasks).await, 178 | exponential_swarm(&mut agents, &tasks).await, 179 | ]; 180 | 181 | for pattern in patterns { 182 | let result = pattern.unwrap(); 183 | assert!(!result.is_empty()); 184 | } 185 | 186 | // Test single task patterns 187 | let single_task = "Single test task"; 188 | let single_patterns = [ 189 | staircase_swarm(&mut agents, single_task).await, 190 | sigmoid_swarm(&mut agents, single_task).await, 191 | sinusoidal_swarm(&mut agents, single_task).await, 192 | ]; 193 | 194 | for pattern in single_patterns { 195 | let result = pattern.unwrap(); 196 | assert!(!result.is_empty()); 197 | } 198 | } 199 | 200 | } -------------------------------------------------------------------------------- /swarms/src/architectures/prime.rs: -------------------------------------------------------------------------------- 1 | use swarm_agent::Agent; 2 | 3 | /// Implements a prime swarm where agents are arranged according to prime number indices 4 | pub async fn prime_swarm( 5 | agents: &mut [A], 6 | tasks: &[String], 7 | ) -> Result, String> { 8 | let mut results = Vec::new(); 9 | 10 | if agents.is_empty() || tasks.is_empty() { 11 | return Err("Agents and tasks lists cannot be empty.".to_string()); 12 | } 13 | 14 | // First few prime numbers 15 | let primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]; 16 | 17 | // Process tasks using prime number indices 18 | let mut task_iter = tasks.iter(); 19 | for &prime in &primes { 20 | if prime < agents.len() { 21 | if let Some(task) = task_iter.next() { 22 | match agents[prime].run(task).await { 23 | Ok(response) => results.push(response), 24 | Err(e) => return Err(format!("Agent error: {}", e)), 25 | } 26 | } 27 | } 28 | } 29 | 30 | Ok(results) 31 | } 32 | 33 | 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use swarm_agent::{AgentConfig, mock::MockAgent}; 38 | use super::*; 39 | 40 | #[tokio::test] 41 | async fn test_prime_swarm() { 42 | let config = AgentConfig::default(); 43 | let mut agents: Vec<_> = (0..10) 44 | .map(|_| MockAgent::new(config.clone())) 45 | .collect(); 46 | 47 | let tasks = vec![ 48 | "Task 1".to_string(), 49 | "Task 2".to_string(), 50 | "Task 3".to_string(), 51 | ]; 52 | 53 | let result = prime_swarm(&mut agents, &tasks).await.unwrap(); 54 | assert!(!result.is_empty()); 55 | // Should process tasks at prime indices (2, 3, 5, 7) 56 | assert!(result.len() <= tasks.len()); 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /swarms/src/architectures/pyramid.rs: -------------------------------------------------------------------------------- 1 | use swarm_agent::Agent; 2 | 3 | /// Implements a pyramid swarm where agents are arranged in a hierarchical structure 4 | pub async fn pyramid_swarm( 5 | agents: &mut [A], 6 | tasks: &[String], 7 | ) -> Result, String> { 8 | let mut results = Vec::new(); 9 | 10 | if agents.is_empty() || tasks.is_empty() { 11 | return Err("Agents and tasks lists cannot be empty.".to_string()); 12 | } 13 | 14 | // Calculate pyramid levels 15 | let mut level = 0; 16 | let mut level_size = 1; 17 | let mut total_agents = 0; 18 | while total_agents + level_size <= agents.len() { 19 | total_agents += level_size; 20 | level += 1; 21 | level_size += 1; 22 | } 23 | 24 | if level == 0 { 25 | return Err("Not enough agents for pyramid structure".to_string()); 26 | } 27 | 28 | // Process tasks through pyramid levels 29 | let mut task_iter = tasks.iter().cycle(); 30 | let mut agent_idx = 0; 31 | 32 | for current_level in 0..level { 33 | let agents_in_level = current_level + 1; 34 | 35 | for _ in 0..agents_in_level { 36 | if agent_idx < agents.len() { 37 | if let Some(task) = task_iter.next() { 38 | match agents[agent_idx].run(task).await { 39 | Ok(response) => results.push(response), 40 | Err(e) => return Err(format!("Agent error: {}", e)), 41 | } 42 | } 43 | agent_idx += 1; 44 | } 45 | } 46 | } 47 | 48 | Ok(results) 49 | } 50 | 51 | 52 | 53 | #[cfg(test)] 54 | mod tests { 55 | use swarm_agent::{AgentConfig, mock::MockAgent}; 56 | use super::*; 57 | 58 | #[tokio::test] 59 | async fn test_pyramid_swarm() { 60 | let config = AgentConfig::default(); 61 | let mut agents = vec![ 62 | MockAgent::new(config.clone()), // Top level 63 | MockAgent::new(config.clone()), // Second level 64 | MockAgent::new(config.clone()), // Second level 65 | ]; 66 | 67 | let tasks = vec![ 68 | "Task 1".to_string(), 69 | "Task 2".to_string(), 70 | "Task 3".to_string(), 71 | ]; 72 | 73 | let result = pyramid_swarm(&mut agents, &tasks).await.unwrap(); 74 | assert_eq!(result.len(), 3); // One task per agent in pyramid 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /swarms/src/architectures/queue_swarm.rs: -------------------------------------------------------------------------------- 1 | //! Queue Swarm architecture implementation 2 | //! 3 | //! This module implements the Queue Swarm pattern where tasks are processed in a 4 | //! FIFO (First In, First Out) order, similar to the Python implementation in 5 | //! docs.swarms.world. 6 | 7 | use swarm_agent::Agent; 8 | 9 | /// Implements a Queue Swarm where tasks are processed in FIFO order 10 | pub async fn queue_swarm( 11 | agents: &mut [A], 12 | tasks: &[String], 13 | ) -> Result, String> { 14 | let mut results = Vec::new(); 15 | 16 | if agents.is_empty() || tasks.is_empty() { 17 | return Err("Agents and tasks lists cannot be empty.".to_string()); 18 | } 19 | 20 | // Process tasks in FIFO order using available agents 21 | let mut agent_idx = 0; 22 | for task in tasks { 23 | // Get next available agent (round-robin if needed) 24 | if agent_idx >= agents.len() { 25 | agent_idx = 0; 26 | } 27 | 28 | // Process task with current agent 29 | match agents[agent_idx].run(task).await { 30 | Ok(response) => results.push(response), 31 | Err(e) => return Err(format!("Agent error: {}", e)), 32 | } 33 | 34 | agent_idx += 1; 35 | } 36 | 37 | Ok(results) 38 | } 39 | 40 | 41 | 42 | 43 | #[cfg(test)] 44 | mod tests { 45 | use swarm_agent::{AgentConfig, mock::MockAgent}; 46 | use super::*; 47 | 48 | #[tokio::test] 49 | async fn test_queue_swarm() { 50 | let config = AgentConfig::default(); 51 | let mut agents = vec![ 52 | MockAgent::new( 53 | AgentConfig { 54 | name: "QueueProcessor1".to_string(), 55 | ..config.clone() 56 | } 57 | ), 58 | MockAgent::new( 59 | AgentConfig { 60 | name: "QueueProcessor2".to_string(), 61 | ..config 62 | } 63 | ), 64 | ]; 65 | 66 | let tasks = vec![ 67 | "Task1".to_string(), 68 | "Task2".to_string(), 69 | "Task3".to_string(), 70 | ]; 71 | 72 | let results = queue_swarm(&mut agents, &tasks).await.unwrap(); 73 | assert_eq!(results.len(), 3); 74 | } 75 | 76 | #[tokio::test] 77 | async fn test_queue_swarm_empty_input() { 78 | let mut empty_agents: Vec = vec![]; 79 | let tasks = vec!["Task".to_string()]; 80 | assert!(queue_swarm(&mut empty_agents, &tasks).await.is_err()); 81 | 82 | let config = AgentConfig::default(); 83 | let mut agents = vec![MockAgent::new(config)]; 84 | let empty_tasks: Vec = vec![]; 85 | assert!(queue_swarm(&mut agents, &empty_tasks).await.is_err()); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /swarms/src/architectures/round_robin.rs: -------------------------------------------------------------------------------- 1 | //! Round Robin swarm architecture implementation 2 | //! 3 | //! This module implements the Round Robin swarm pattern where tasks are distributed 4 | //! evenly among agents in a circular fashion, similar to the Python implementation 5 | //! in docs.swarms.world. 6 | 7 | use swarm_agent::Agent; 8 | 9 | /// Implements a Round Robin swarm where tasks are distributed evenly among agents 10 | pub async fn round_robin_swarm( 11 | agents: &mut [A], 12 | tasks: &[String], 13 | ) -> Result, String> { 14 | let mut results = Vec::new(); 15 | 16 | if agents.is_empty() || tasks.is_empty() { 17 | return Err("Agents and tasks lists cannot be empty.".to_string()); 18 | } 19 | 20 | // Distribute tasks evenly among agents in round-robin fashion 21 | for (task_idx, task) in tasks.iter().enumerate() { 22 | let agent_idx = task_idx % agents.len(); 23 | match agents[agent_idx].run(task).await { 24 | Ok(response) => results.push(response), 25 | Err(e) => return Err(format!("Agent error: {}", e)), 26 | } 27 | } 28 | 29 | Ok(results) 30 | } 31 | 32 | 33 | #[cfg(test)] 34 | mod tests { 35 | use swarm_agent::{AgentConfig, mock::MockAgent}; 36 | use super::*; 37 | 38 | #[tokio::test] 39 | async fn test_round_robin_swarm() { 40 | let config = AgentConfig::default(); 41 | let mut agents = vec![ 42 | MockAgent::new( 43 | AgentConfig { 44 | name: "Agent1".to_string(), 45 | ..config.clone() 46 | } 47 | ), 48 | MockAgent::new( 49 | AgentConfig { 50 | name: "Agent2".to_string(), 51 | ..config 52 | } 53 | ), 54 | ]; 55 | 56 | let tasks = vec![ 57 | "Task1".to_string(), 58 | "Task2".to_string(), 59 | "Task3".to_string(), 60 | ]; 61 | 62 | let results = round_robin_swarm(&mut agents, &tasks).await.unwrap(); 63 | assert_eq!(results.len(), 3); 64 | } 65 | 66 | #[tokio::test] 67 | async fn test_round_robin_empty_input() { 68 | let mut empty_agents: Vec = vec![]; 69 | let tasks = vec!["Task".to_string()]; 70 | assert!(round_robin_swarm(&mut empty_agents, &tasks).await.is_err()); 71 | 72 | let config = AgentConfig::default(); 73 | let mut agents = vec![MockAgent::new(config)]; 74 | let empty_tasks: Vec = vec![]; 75 | assert!(round_robin_swarm(&mut agents, &empty_tasks).await.is_err()); 76 | } 77 | 78 | } 79 | 80 | -------------------------------------------------------------------------------- /swarms/src/architectures/star.rs: -------------------------------------------------------------------------------- 1 | use swarm_agent::Agent; 2 | 3 | /// Implements a star swarm where a central agent processes tasks first, followed by others 4 | pub async fn star_swarm( 5 | agents: &mut [A], 6 | tasks: &[String], 7 | ) -> Result, String> { 8 | let mut results = Vec::new(); 9 | 10 | if agents.len() < 2 { 11 | return Err("Star swarm requires at least 2 agents (1 center + 1 peripheral)".to_string()); 12 | } 13 | if tasks.is_empty() { 14 | return Err("Tasks list cannot be empty.".to_string()); 15 | } 16 | 17 | // Central agent processes each task first 18 | for task in tasks { 19 | // Central agent (first in the list) processes the task 20 | match agents[0].run(task).await { 21 | Ok(response) => results.push(response), 22 | Err(e) => return Err(format!("Central agent error: {}", e)), 23 | } 24 | 25 | // Other agents process the same task 26 | for agent in agents[1..].iter_mut() { 27 | match agent.run(task).await { 28 | Ok(response) => results.push(response), 29 | Err(e) => return Err(format!("Peripheral agent error: {}", e)), 30 | } 31 | } 32 | } 33 | 34 | Ok(results) 35 | } 36 | 37 | 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use swarm_agent::{AgentConfig, mock::MockAgent}; 42 | use super::*; 43 | 44 | #[tokio::test] 45 | async fn test_star_swarm() { 46 | let config = AgentConfig::default(); 47 | 48 | let mut agents = vec![ 49 | MockAgent::new(config.clone()), // Central agent 50 | MockAgent::new(config.clone()), // Peripheral agent 1 51 | MockAgent::new(config), // Peripheral agent 2 52 | ]; 53 | 54 | let tasks = vec!["Task 1".to_string()]; 55 | 56 | let result = star_swarm(&mut agents, &tasks).await.unwrap(); 57 | assert_eq!(result.len(), 3); // 1 central + 2 peripheral agents * 1 task 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /swarms/src/architectures/tree_swarm.rs: -------------------------------------------------------------------------------- 1 | //! Tree Swarm architecture implementation 2 | //! 3 | //! This module implements the Tree Swarm pattern where agents are organized in a 4 | //! hierarchical tree structure, similar to the Python implementation in 5 | //! docs.swarms.world. 6 | 7 | use swarm_agent::Agent; 8 | use std::collections::{HashMap, HashSet}; 9 | 10 | /// Represents a node in the agent tree 11 | #[derive(Debug)] 12 | struct TreeNode { 13 | children: Vec, 14 | parent: Option, 15 | } 16 | 17 | /// Implements a Tree Swarm where agents are organized in a hierarchical structure 18 | pub async fn tree_swarm( 19 | agents: &mut [A], 20 | tasks: &[String], 21 | parent_child_pairs: Option>, // (parent_idx, child_idx) 22 | ) -> Result, String> { 23 | let mut results = Vec::new(); 24 | 25 | if agents.is_empty() || tasks.is_empty() { 26 | return Err("Agents and tasks lists cannot be empty.".to_string()); 27 | } 28 | 29 | // Build tree structure 30 | let mut nodes: HashMap = HashMap::new(); 31 | 32 | // If no parent-child pairs provided, create a balanced binary tree 33 | let relationships = match parent_child_pairs { 34 | Some(pairs) => { 35 | if pairs 36 | .iter() 37 | .any(|(p, c)| *p >= agents.len() || *c >= agents.len()) 38 | { 39 | return Err("Invalid parent-child indices.".to_string()); 40 | } 41 | pairs 42 | } 43 | None => { 44 | // Create balanced binary tree relationships 45 | (0..agents.len()) 46 | .flat_map(|i| { 47 | let left = 2 * i + 1; 48 | let right = 2 * i + 2; 49 | let mut pairs = Vec::new(); 50 | if left < agents.len() { 51 | pairs.push((i, left)); 52 | } 53 | if right < agents.len() { 54 | pairs.push((i, right)); 55 | } 56 | pairs 57 | }) 58 | .collect() 59 | } 60 | }; 61 | 62 | // Initialize tree nodes 63 | for i in 0..agents.len() { 64 | nodes.insert( 65 | i, 66 | TreeNode { 67 | children: Vec::new(), 68 | parent: None, 69 | }, 70 | ); 71 | } 72 | 73 | // Build relationships 74 | for (parent_idx, child_idx) in relationships { 75 | if let Some(parent_node) = nodes.get_mut(&parent_idx) { 76 | parent_node.children.push(child_idx); 77 | } 78 | if let Some(child_node) = nodes.get_mut(&child_idx) { 79 | child_node.parent = Some(parent_idx); 80 | } 81 | } 82 | 83 | // Process tasks through the tree hierarchy 84 | for task in tasks { 85 | let mut processed = HashSet::new(); 86 | let mut current_level: HashSet = vec![0].into_iter().collect(); // Start with root node 87 | 88 | while !current_level.is_empty() { 89 | let mut next_level = HashSet::new(); 90 | 91 | // Process current level nodes 92 | for &node_idx in ¤t_level { 93 | if processed.contains(&node_idx) { 94 | continue; 95 | } 96 | 97 | // Process task with current agent 98 | match agents[node_idx].run(task).await { 99 | Ok(response) => results.push(response), 100 | Err(e) => return Err(format!("Agent error: {}", e)), 101 | } 102 | 103 | processed.insert(node_idx); 104 | 105 | // Add child nodes to next level 106 | if let Some(node) = nodes.get(&node_idx) { 107 | next_level.extend(&node.children); 108 | } 109 | } 110 | 111 | current_level = next_level; 112 | } 113 | } 114 | 115 | Ok(results) 116 | } 117 | 118 | 119 | 120 | 121 | #[cfg(test)] 122 | mod tests { 123 | use swarm_agent::{AgentConfig, mock::MockAgent}; 124 | use super::*; 125 | 126 | #[tokio::test] 127 | async fn test_tree_swarm() { 128 | let config = AgentConfig::default(); 129 | let mut agents = vec![ 130 | MockAgent::new( 131 | AgentConfig { 132 | name: "Root".to_string(), 133 | ..config.clone() 134 | } 135 | ), 136 | MockAgent::new( 137 | AgentConfig { 138 | name: "LeftChild".to_string(), 139 | ..config.clone() 140 | } 141 | ), 142 | MockAgent::new( 143 | AgentConfig { 144 | name: "RightChild".to_string(), 145 | ..config 146 | } 147 | ), 148 | ]; 149 | 150 | let tasks = vec!["Test task".to_string()]; 151 | 152 | // Test with custom parent-child relationships 153 | let relationships = vec![ 154 | (0, 1), // Root -> LeftChild 155 | (0, 2), // Root -> RightChild 156 | ]; 157 | 158 | let results = tree_swarm(&mut agents, &tasks, Some(relationships)) 159 | .await 160 | .unwrap(); 161 | assert_eq!(results.len(), 3); 162 | 163 | // Test with default balanced binary tree 164 | let results = tree_swarm(&mut agents, &tasks, None) 165 | .await 166 | .unwrap(); 167 | assert_eq!(results.len(), 3); 168 | } 169 | 170 | #[tokio::test] 171 | async fn test_tree_swarm_empty_input() { 172 | let mut empty_agents: Vec = vec![]; 173 | let tasks = vec!["Task".to_string()]; 174 | assert!(tree_swarm(&mut empty_agents, &tasks, None).await.is_err()); 175 | 176 | let config = AgentConfig::default(); 177 | let mut agents = vec![MockAgent::new(config)]; 178 | let empty_tasks: Vec = vec![]; 179 | assert!(tree_swarm(&mut agents, &empty_tasks, None).await.is_err()); 180 | } 181 | 182 | #[tokio::test] 183 | async fn test_tree_swarm_invalid_relationships() { 184 | let config = AgentConfig::default(); 185 | let mut agents = vec![MockAgent::new(config)]; 186 | let tasks = vec!["Task".to_string()]; 187 | 188 | // Test with invalid parent index 189 | let invalid_relationships = vec![(1, 0)]; // Parent index 1 doesn't exist 190 | assert!(tree_swarm(&mut agents, &tasks, Some(invalid_relationships)) 191 | .await 192 | .is_err()); 193 | } 194 | 195 | } -------------------------------------------------------------------------------- /swarms/src/lib.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use serde::{Deserialize, Serialize}; 3 | use swarm_agent::Agent; 4 | 5 | use uuid::Uuid; 6 | 7 | /// Configuration for a swarm 8 | #[derive(Debug, Clone, Serialize, Deserialize)] 9 | pub struct SwarmConfig { 10 | pub name: String, 11 | pub description: Option, 12 | pub max_loops: usize, 13 | pub autosave: bool, 14 | pub logging: bool, 15 | } 16 | 17 | impl Default for SwarmConfig { 18 | fn default() -> Self { 19 | Self { 20 | name: "default-swarm".to_string(), 21 | description: None, 22 | max_loops: 200, 23 | autosave: false, 24 | logging: true, 25 | } 26 | } 27 | } 28 | 29 | /// Core trait defining swarm capabilities 30 | #[async_trait] 31 | pub trait Swarm { 32 | type AgentType: Agent; 33 | 34 | /// Get the swarm's configuration 35 | fn config(&self) -> &SwarmConfig; 36 | 37 | /// Get a reference to the swarm's agents 38 | fn agents(&self) -> &[Self::AgentType]; 39 | 40 | /// Get a mutable reference to the swarm's agents 41 | fn agents_mut(&mut self) -> &mut [Self::AgentType]; 42 | 43 | /// Add an agent to the swarm 44 | fn add_agent(&mut self, agent: Self::AgentType); 45 | 46 | /// Remove an agent from the swarm by ID 47 | fn remove_agent(&mut self, agent_id: Uuid) -> Option; 48 | 49 | /// Reset all agents in the swarm 50 | fn reset(&mut self); 51 | 52 | /// Run the swarm on a task 53 | async fn run(&mut self, task: &str) -> Result, String>; 54 | } 55 | 56 | pub mod mock; 57 | pub mod architectures; -------------------------------------------------------------------------------- /swarms/src/mock.rs: -------------------------------------------------------------------------------- 1 | use swarm_agent::{Agent, AgentConfig, mock::MockAgent}; 2 | use crate::{Swarm, SwarmConfig}; 3 | use uuid::Uuid; 4 | use async_trait::async_trait; 5 | use serde::{Deserialize, Serialize}; 6 | 7 | /// Basic implementation of a swarm 8 | #[derive(Debug, Clone, Serialize, Deserialize)] 9 | pub struct MockSwarm { 10 | config: SwarmConfig, 11 | agents: Vec, 12 | conversation_history: Vec<(String, String)>, // (agent_name, message) 13 | } 14 | 15 | #[async_trait] 16 | impl Swarm for MockSwarm { 17 | type AgentType = A; 18 | 19 | fn config(&self) -> &SwarmConfig { 20 | &self.config 21 | } 22 | 23 | fn agents(&self) -> &[A] { 24 | &self.agents 25 | } 26 | 27 | fn agents_mut(&mut self) -> &mut [A] { 28 | &mut self.agents 29 | } 30 | 31 | fn add_agent(&mut self, agent: A) { 32 | self.agents.push(agent); 33 | } 34 | 35 | fn remove_agent(&mut self, agent_id: Uuid) -> Option { 36 | if let Some(pos) = self.agents.iter().position(|a| a.id() == agent_id) { 37 | Some(self.agents.remove(pos)) 38 | } else { 39 | None 40 | } 41 | } 42 | 43 | fn reset(&mut self) { 44 | self.conversation_history.clear(); 45 | } 46 | 47 | async fn run(&mut self, task: &str) -> Result, String> { 48 | let mut results = Vec::new(); 49 | let agent_count = self.agents.len(); 50 | 51 | for i in 0..agent_count { 52 | let response = self.agents[i].run(task).await?; 53 | let agent_name = self.agents[i].name().to_string(); 54 | self.log_conversation(agent_name, response.clone()); 55 | results.push(response); 56 | } 57 | 58 | Ok(results) 59 | } 60 | } 61 | 62 | 63 | impl MockSwarm { 64 | pub fn new(config: SwarmConfig, agents: Vec) -> Self { 65 | Self { 66 | config, 67 | agents, 68 | conversation_history: Vec::new(), 69 | } 70 | } 71 | 72 | pub fn with_agents(agents: Vec) -> Self { 73 | Self::new(SwarmConfig::default(), agents) 74 | } 75 | 76 | pub fn log_conversation(&mut self, agent_name: String, message: String) { 77 | if self.config.logging { 78 | self.conversation_history.push((agent_name, message)); 79 | } 80 | } 81 | 82 | pub fn conversation_history(&self) -> &[(String, String)] { 83 | &self.conversation_history 84 | } 85 | 86 | pub fn get_agent_by_name(&self, name: &str) -> Option<&A> { 87 | self.agents.iter().find(|agent| agent.name() == name) 88 | } 89 | 90 | pub fn get_agent_by_id(&self, id: Uuid) -> Option<&A> { 91 | self.agents.iter().find(|agent| agent.id() == id) 92 | } 93 | } 94 | 95 | 96 | #[tokio::test] 97 | async fn test_base_swarm() { 98 | let agent_config = AgentConfig::default(); 99 | let agents = vec![ 100 | MockAgent::new(agent_config.clone()), 101 | MockAgent::new(agent_config), 102 | ]; 103 | 104 | let mut swarm = MockSwarm::with_agents(agents); 105 | let results = swarm.run("test task").await.unwrap(); 106 | //println!("results: {:?} {}", results, results.len()); 107 | 108 | assert_eq!(results.len(), 2); 109 | assert_eq!(swarm.conversation_history().len(), 2); 110 | } 111 | 112 | #[test] 113 | fn test_swarm_agent_management() { 114 | let agent_config = AgentConfig::default(); 115 | let agent = MockAgent::new(agent_config); 116 | let agent_id = agent.id(); 117 | 118 | let mut swarm = MockSwarm::with_agents(vec![agent]); 119 | 120 | // Test agent retrieval 121 | assert!(swarm.get_agent_by_id(agent_id).is_some()); 122 | 123 | // Test agent removal 124 | let removed = swarm.remove_agent(agent_id); 125 | assert!(removed.is_some()); 126 | assert!(swarm.agents().is_empty()); 127 | } 128 | 129 | --------------------------------------------------------------------------------