### ./src/stream.rs

```rust
// File: rswarm/src/stream.rs

use async_stream::try_stream;
use futures_util::{stream::Stream, StreamExt};
use reqwest::Client;
use serde_json::{json, Value};
use std::env;

use crate::constants::{OPENAI_DEFAULT_API_URL, ROLE_SYSTEM};
use crate::error::{SwarmError, SwarmResult};
use crate::types::{Agent, ChatCompletionResponse, ContextVariables, Instructions, Message};
use crate::util::function_to_json;

/// Streamer provides a streaming–based API to receive agent responses incrementally.
pub struct Streamer {
    client: Client,
    api_key: String,
}

impl Streamer {
    /// Create a new Streamer instance using the provided HTTP Client and API key.
    pub fn new(client: Client, api_key: String) -> Self {
        Self { client, api_key }
    }

    /// Begins a streaming chat completion request.
    ///
    /// The returned stream yields individual messages (using a JSON structure
    /// defined by ChatCompletionResponse) as soon as they are available.
    pub fn stream_chat(
        &self,
        agent: &Agent,
        history: &[Message],
        context_variables: &ContextVariables,
        model_override: Option<String>,
        debug: bool,
    ) -> impl Stream<Item = SwarmResult<Message>> {
        // Clone values to use in the async block.
        let client = self.client.clone();
        let api_key = self.api_key.clone();
        let model = model_override.unwrap_or_else(|| match &agent.instructions {
            Instructions::Text(_text) => agent.model.clone(),
            Instructions::Function(_func) => agent.model.clone(),
        });
        println!("{:?}", debug);
        // Build the messages vector.
        let mut messages = Vec::new();
        let system_instructions = match &agent.instructions {
            Instructions::Text(text) => text.clone(),
            Instructions::Function(func) => func(context_variables.clone()),
        };
        messages.push(Message {
            role: ROLE_SYSTEM.to_string(),
            content: Some(system_instructions),
            name: None,
            function_call: None,
        });
        messages.extend_from_slice(history);

        // Prepare any functions for the API.
        let functions: Vec<Value> = agent
            .functions
            .iter()
            .map(|func| function_to_json(func))
            .collect::<SwarmResult<Vec<Value>>>()
            .unwrap_or_default();

        // Build the request payload.
        let mut request_body = json!({
            "model": model,
            "messages": messages,
            "stream": true,
        });
        if !functions.is_empty() {
            request_body["functions"] = Value::Array(functions);
        }

        // Determine API URL from environment or default.
        let api_url =
            env::var("OPENAI_API_URL").unwrap_or_else(|_| OPENAI_DEFAULT_API_URL.to_string());

        // Use try_stream to create a stream that can yield items and errors.
        try_stream! {
            // Send POST request.
            let response = client
                .post(api_url)
                .bearer_auth(api_key)
                .json(&request_body)
                .send()
                .await
                .map_err(|e| SwarmError::NetworkError(e.to_string()))?;

            // Ensure the HTTP status is successful without consuming response.
            response.error_for_status_ref()
                .map_err(|e| SwarmError::ApiError(e.to_string()))?;

            // Now get the streaming body.
            let mut byte_stream = response.bytes_stream();
            while let Some(chunk_result) = byte_stream.next().await {
                match chunk_result {
                    Ok(chunk) => {
                        let text_chunk = String::from_utf8_lossy(&chunk);
                        // Each line is expected to be prefixed with "data: ".
                        for line in text_chunk.lines() {
                            if line.starts_with("data: ") {
                                let json_str = line[6..].trim();
                                if json_str == "[DONE]" {
                                    break;
                                }
                                // Deserialize the partial response.
                                let partial: ChatCompletionResponse = serde_json::from_str(json_str)
                                    .map_err(|e| SwarmError::DeserializationError(e.to_string()))?;
                                // Yield each message.
                                for choice in partial.choices {
                                    yield choice.message;
                                }
                            }
                        }
                    }
                    Err(e) => Err(SwarmError::StreamError(e.to_string()))?,
                }
            }
        }
    }
}

```

### ./src/tests/stream.rs

```rust
#[cfg(test)]
mod tests {
    use crate::stream::Streamer;
    use crate::types::{Agent, ContextVariables, Instructions, Message};
    #[allow(unused)]
    use crate::SwarmError;
    use futures_util::{pin_mut, StreamExt};
    use reqwest::Client;
    use std::time::Duration;
    use tokio;
    use wiremock::matchers::{method, path};
    use wiremock::{Mock, MockServer, ResponseTemplate};

    // Helper function to create a simple test agent.
    fn test_agent() -> Agent {
        Agent {
            name: "test_agent".to_string(),
            model: "gpt-4".to_string(),
            instructions: Instructions::Text("You are a helpful assistant.".to_string()),
            functions: vec![],
            function_call: None,
            parallel_tool_calls: false,
        }
    }

    #[tokio::test]
    async fn test_stream_chat_returns_messages() {
        // Start a WireMock server.
        let mock_server = MockServer::start().await;

        // Create a response body that simulates streaming chunks.
        // The first chunk returns a partial response with a choice message,
        // followed by [DONE] to indicate the end of the stream.
        let body = "data: {\"id\":\"dummy\",\"object\":\"chat.completion\",\"created\":0,\"choices\":[{\"index\":0,\"message\":{\"role\":\"assistant\",\"content\":\"Hello from stream!\",\"name\":null,\"function_call\":null},\"finish_reason\":null}]}\n\
                    data: [DONE]\n";

        let response = ResponseTemplate::new(200).set_body_raw(body, "text/event-stream");

        // Set up the stub for POST /completions.
        Mock::given(method("POST"))
            .and(path("/completions"))
            .respond_with(response)
            .mount(&mock_server)
            .await;

        // Set the environment variable to point to our WireMock server.
        std::env::set_var(
            "OPENAI_API_URL",
            format!("{}/completions", &mock_server.uri()),
        );

        // Create an HTTP client.
        let client = Client::builder()
            .timeout(Duration::from_secs(30))
            .build()
            .expect("Failed to build client");
        let api_key = "sk-test123456789".to_string();

        let streamer = Streamer::new(client, api_key);
        let agent = test_agent();
        let history: Vec<Message> = vec![Message {
            role: "user".to_string(),
            content: Some("Hello!".to_string()),
            name: None,
            function_call: None,
        }];
        let context_variables = ContextVariables::new();

        let stream = streamer.stream_chat(&agent, &history, &context_variables, None, true);
        pin_mut!(stream);

        // Await one message from the stream.
        if let Some(result) = stream.next().await {
            match result {
                Ok(message) => {
                    // Verify that the message role and content are as expected.
                    assert_eq!(message.role, "assistant");
                    assert_eq!(message.content.unwrap(), "Hello from stream!");
                }
                Err(e) => {
                    panic!("Stream returned an error: {:?}", e);
                }
            }
        } else {
            panic!("No messages returned from the stream");
        }
    }
}

```

### ./src/tests/agent.rs

```rust
#[cfg(test)]
mod tests {
    use crate::{Swarm, SwarmConfig, Agent, Instructions, SwarmError};
    use crate::types::{ContextVariables, AgentFunction, ResultType};
    use std::sync::Arc;

#[test]
fn test_create_basic_agent() {
    let agent = Agent {
        name: "test_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Text("Basic test instructions".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    assert_eq!(agent.name, "test_agent");
    assert_eq!(agent.model, "gpt-4");
    match agent.instructions {
        Instructions::Text(text) => assert_eq!(text, "Basic test instructions"),
        _ => panic!("Expected Text instructions"),
    }
    assert!(agent.functions.is_empty());
    assert!(agent.function_call.is_none());
    assert!(!agent.parallel_tool_calls);
}

#[test]
fn test_agent_with_function_instructions() {
    let instruction_fn = Arc::new(|_vars: ContextVariables| -> String {
        "Dynamic instructions".to_string()
    });

    let agent = Agent {
        name: "function_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Function(instruction_fn),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    // Test the function instructions
    let context = ContextVariables::new();
    match &agent.instructions {
        Instructions::Function(f) => assert_eq!(f(context), "Dynamic instructions"),
        _ => panic!("Expected Function instructions"),
    }
}

#[test]
fn test_agent_with_functions() {
    let test_function = AgentFunction {
        name: "test_function".to_string(),
        function: Arc::new(|_: ContextVariables| -> Result<ResultType, anyhow::Error> {
            Ok(ResultType::Value("test result".to_string()))
        }),
        accepts_context_variables: false,
    };

    let agent = Agent {
        name: "function_enabled_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Text("Test with functions".to_string()),
        functions: vec![test_function],
        function_call: Some("auto".to_string()),
        parallel_tool_calls: true,
    };

    assert_eq!(agent.functions.len(), 1);
    assert_eq!(agent.functions[0].name, "test_function");
    assert_eq!(agent.functions[0].accepts_context_variables, false);
    assert_eq!(agent.function_call, Some("auto".to_string()));
    assert!(agent.parallel_tool_calls);
}

#[test]
fn test_agent_in_swarm_registry() {
    let agent = Agent {
        name: "registry_test_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Text("Test instructions".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    let swarm = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent.clone())
        .build()
        .expect("Failed to build Swarm");

    assert!(swarm.agent_registry.contains_key(&agent.name));
    let registered_agent = swarm.agent_registry.get(&agent.name).unwrap();
    assert_eq!(registered_agent.name, "registry_test_agent");
    assert_eq!(registered_agent.model, "gpt-4");
}

#[test]
fn test_agent_empty_name() {
    let agent = Agent {
        name: "".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Text("Test instructions".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    // Try to register the agent in a Swarm
    let result = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent)
        .build();

    // Verify error
    assert!(result.is_err());
    match result {
        Err(SwarmError::ValidationError(msg)) => {
            assert!(msg.contains("Agent name cannot be empty"));
        }
        _ => panic!("Expected ValidationError for empty agent name"),
    }
}

#[test]
fn test_agent_empty_model() {
    let agent = Agent {
        name: "test_agent".to_string(),
        model: "".to_string(),
        instructions: Instructions::Text("Test instructions".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    // Try to register the agent in a Swarm
    let result = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent)
        .build();

    // Verify error
    assert!(result.is_err());
    match result {
        Err(SwarmError::ValidationError(msg)) => {
            assert!(msg.contains("Agent model cannot be empty"));
        }
        _ => panic!("Expected ValidationError for empty model"),
    }
}

#[test]
fn test_agent_invalid_model_prefix() {
    let agent = Agent {
        name: "test_agent".to_string(),
        model: "invalid-model".to_string(), // Doesn't start with valid prefix
        instructions: Instructions::Text("Test instructions".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    // Try to register the agent in a Swarm
    let result = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent)
        .build();

    // Verify error
    assert!(result.is_err());
    match result {
        Err(SwarmError::ValidationError(msg)) => {
            assert!(msg.contains("Invalid model prefix"));
        }
        _ => panic!("Expected ValidationError for invalid model prefix"),
    }
}

#[test]
fn test_agent_missing_instructions() {
    let agent = Agent {
        name: "test_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Text("".to_string()), // Empty instructions
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    // Try to register the agent in a Swarm
    let result = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent)
        .build();

    // Verify error
    assert!(result.is_err());
    match result {
        Err(SwarmError::ValidationError(msg)) => {
            assert!(msg.contains("Agent instructions cannot be empty"));
        }
        _ => panic!("Expected ValidationError for empty instructions"),
    }
}

#[test]
fn test_agent_with_invalid_model_prefix() {
    let agent = Agent {
        name: "test_agent".to_string(),
        model: "invalid-model".to_string(),
        instructions: Instructions::Text("Test instructions".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    let result = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent)
        .build();

    assert!(matches!(result, Err(SwarmError::ValidationError(_))));
    if let Err(SwarmError::ValidationError(msg)) = result {
        assert!(msg.contains("Invalid model prefix"));
    }
}

#[test]
fn test_agent_with_empty_model() {
    let agent = Agent {
        name: "test_agent".to_string(),
        model: "".to_string(),
        instructions: Instructions::Text("Test instructions".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    let result = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent)
        .build();

    assert!(matches!(result, Err(SwarmError::ValidationError(_))));
    if let Err(SwarmError::ValidationError(msg)) = result {
        assert!(msg.contains("Agent model cannot be empty"));
    }
}

#[test]
fn test_agent_with_valid_model_prefix() {
    let agent = Agent {
        name: "test_agent".to_string(),
        model: "gpt-4".to_string(), // Valid prefix
        instructions: Instructions::Text("Test instructions".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    let result = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent)
        .build();

    assert!(result.is_ok());
}

#[test]
fn test_custom_model_prefix_validation() {
    // Create a custom config with specific model prefixes
    let config = SwarmConfig {
        valid_model_prefixes: vec!["custom-".to_string()],
        ..SwarmConfig::default()
    };

    let agent = Agent {
        name: "test_agent".to_string(),
        model: "custom-model".to_string(),
        instructions: Instructions::Text("Test instructions".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    let result = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_config(config)
        .with_agent(agent)
        .build();

    assert!(result.is_ok());
}

#[test]
fn test_agent_with_valid_text_instructions() {
    let agent = Agent {
        name: "test_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Text("Valid test instructions".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    let result = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent)
        .build();

    assert!(result.is_ok());
    if let Ok(swarm) = result {
        let stored_agent = swarm.agent_registry.get("test_agent").unwrap();
        match &stored_agent.instructions {
            Instructions::Text(text) => assert_eq!(text, "Valid test instructions"),
            _ => panic!("Expected Text instructions"),
        }
    }
}

#[test]
fn test_agent_with_empty_text_instructions() {
    let agent = Agent {
        name: "test_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Text("".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    let result = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent)
        .build();

    assert!(result.is_err());
    match result {
        Err(SwarmError::ValidationError(msg)) => {
            assert!(msg.contains("Agent instructions cannot be empty"));
        }
        _ => panic!("Expected ValidationError for empty instructions"),
    }
}

#[test]
fn test_agent_with_whitespace_only_text_instructions() {
    let agent = Agent {
        name: "test_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Text("    \n\t    ".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    let result = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent)
        .build();

    assert!(result.is_err());
    match result {
        Err(SwarmError::ValidationError(msg)) => {
            assert!(msg.contains("Agent instructions cannot be empty"));
        }
        _ => panic!("Expected ValidationError for whitespace-only instructions"),
    }
}

#[test]
fn test_agent_with_multiline_text_instructions() {
    let instructions = "Line 1\nLine 2\nLine 3".to_string();
    let agent = Agent {
        name: "test_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Text(instructions.clone()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    let result = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent)
        .build();

    assert!(result.is_ok());
    if let Ok(swarm) = result {
        let stored_agent = swarm.agent_registry.get("test_agent").unwrap();
        match &stored_agent.instructions {
            Instructions::Text(text) => assert_eq!(text.as_str(), instructions.as_str()),
            _ => panic!("Expected Text instructions"),
        }
    }
}

#[test]
fn test_basic_function_instructions() {
    let instruction_fn = Arc::new(|_: ContextVariables| -> String {
        "Basic function instructions".to_string()
    });

    let agent = Agent {
        name: "test_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Function(instruction_fn),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    let context = ContextVariables::new();
    match &agent.instructions {
        Instructions::Function(f) => assert_eq!(f(context), "Basic function instructions"),
        _ => panic!("Expected Function instructions"),
    }
}

#[test]
fn test_function_instructions_with_context() {
    let instruction_fn = Arc::new(|vars: ContextVariables| -> String {
        match vars.get("test_key") {
            Some(value) => format!("Context value: {}", value),
            None => "No context value found".to_string(),
        }
    });

    let agent = Agent {
        name: "context_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Function(instruction_fn),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    let mut context = ContextVariables::new();
    context.insert("test_key".to_string(), "test_value".to_string());

    match &agent.instructions {
        Instructions::Function(f) => assert_eq!(f(context), "Context value: test_value"),
        _ => panic!("Expected Function instructions"),
    }
}

#[test]
fn test_function_instructions_in_swarm() {
    let instruction_fn = Arc::new(|_: ContextVariables| -> String {
        "Swarm function instructions".to_string()
    });

    let agent = Agent {
        name: "swarm_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Function(instruction_fn),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    let swarm = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_agent(agent)
        .build()
        .expect("Failed to build Swarm");

    let context = ContextVariables::new();
    let stored_agent = swarm.agent_registry.get("swarm_agent").unwrap();

    match &stored_agent.instructions {
        Instructions::Function(f) => assert_eq!(f(context), "Swarm function instructions"),
        _ => panic!("Expected Function instructions"),
    }
}

#[test]
fn test_complex_function_instructions() {
    let instruction_fn = Arc::new(|vars: ContextVariables| -> String {
        let mut parts = Vec::new();

        if let Some(name) = vars.get("name") {
            parts.push(format!("Name: {}", name));
        }

        if let Some(role) = vars.get("role") {
            parts.push(format!("Role: {}", role));
        }

        if parts.is_empty() {
            "Default instructions".to_string()
        } else {
            parts.join("\n")
        }
    });

    let agent = Agent {
        name: "complex_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Function(instruction_fn),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    // Test with empty context
    let empty_context = ContextVariables::new();
    match &agent.instructions {
        Instructions::Function(f) => assert_eq!(f(empty_context), "Default instructions"),
        _ => panic!("Expected Function instructions"),
    }

    // Test with partial context
    let mut partial_context = ContextVariables::new();
    partial_context.insert("name".to_string(), "Test Name".to_string());
    match &agent.instructions {
        Instructions::Function(f) => assert_eq!(f(partial_context), "Name: Test Name"),
        _ => panic!("Expected Function instructions"),
    }

    // Test with full context
    let mut full_context = ContextVariables::new();
    full_context.insert("name".to_string(), "Test Name".to_string());
    full_context.insert("role".to_string(), "Test Role".to_string());
    match &agent.instructions {
        Instructions::Function(f) => assert_eq!(f(full_context), "Name: Test Name\nRole: Test Role"),
        _ => panic!("Expected Function instructions"),
    }
}
}
```

### ./src/tests/swarm_run.rs

```rust
#![allow(unused)]
use crate::core::Swarm;
use crate::types::{Agent, ContextVariables, Instructions, Message};
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use openai_mock::routes::configure_completion_routes;
use serde_json::json;
use serde_json::Value;
use std::collections::HashMap;

/// Custom handler for the `/completions` endpoint.
/// It returns a predefined response when the prompt is "Hello!".
async fn completions_mock_handler(req_body: web::Json<Value>) -> impl Responder {
    // Extract the prompt from the request
    let prompt = req_body.get("prompt");

    if let Some(Value::String(prompt_str)) = prompt {
        if prompt_str == "Hello!" {
            // Return the predefined assistant response along with agent details
            let response = json!({
                "choices": [
                    {
                        "message": {
                            "role": "assistant",
                            "content": "Hi there! How can I assist you today?"
                        }
                    }
                ],
                "agent": {
                    "name": "test_agent",
                    "model": "gpt-4",
                    "instructions": {
                        "text": "You are a helpful assistant."
                    },
                    "functions": [],
                    "function_call": null,
                    "parallel_tool_calls": false
                }
            });
            return HttpResponse::Ok().json(response);
        }
    }

    // Default response for any other prompts
    let default_response = json!({
        "choices": [
            {
                "message": {
                    "role": "assistant",
                    "content": "I'm not sure how to respond to that."
                }
            }
        ],
        "agent": null
    });

    HttpResponse::Ok().json(default_response)
}

/// Sets up the mock server using `actix-web` on localhost:8000
/// with a custom handler for the `/completions` endpoint.
async fn setup_mock_server() -> anyhow::Result<actix_web::dev::Server> {
    let server = HttpServer::new(|| {
        App::new()
            .configure(configure_completion_routes)
            .route("/completions", web::post().to(completions_mock_handler))
    })
    .bind(("127.0.0.1", 8000))?
    .run();

    Ok(server)
}

/// Verifies that a valid Response is returned.
#[cfg(test)]
mod tests {
    use super::*;
    use actix_web::test;

    #[actix_web::test]
    async fn test_simple_conversation() -> anyhow::Result<()> {
        // Initialize the mock service
        let app = test::init_service(
            App::new()
                .configure(configure_completion_routes)
                .route("/completions", web::post().to(completions_mock_handler)),
        )
        .await;

        // Setup Agent
        let agent = Agent {
            name: "test_agent".to_string(),
            model: "gpt-4".to_string(),
            instructions: Instructions::Text("You are a helpful assistant.".to_string()),
            functions: vec![],
            function_call: None,
            parallel_tool_calls: false,
        };

        // Build Swarm with the mock server's API URL
        let swarm = Swarm::builder()
            .with_api_key("sk-test123456789".to_string()) // Can be any string for mock
            .with_api_url("http://localhost:8000".to_string())
            .with_agent(agent.clone())
            .build()?;

        // Define a simple user message
        let messages = vec![Message {
            role: "user".to_string(),
            content: Some("Hello!".to_string()),
            name: None,
            function_call: None,
        }];

        // Create request payload
        let req = test::TestRequest::post()
            .uri("/completions")
            .set_json(&json!({
                "prompt": "Hello!",
                "model": "gpt-4"
            }))
            .to_request();

        // Send request and get response
        let resp = test::call_service(&app, req).await;

        // Assert response status
        assert!(resp.status().is_success());

        // Parse response body
        let response: serde_json::Value = test::read_body_json(resp).await;

        // Assert the response contains expected content
        assert_eq!(
            response["choices"][0]["message"]["content"],
            "Hi there! How can I assist you today?"
        );
        assert_eq!(response["choices"][0]["message"]["role"], "assistant");

        Ok(())
    }
}

```

### ./src/tests/builder.rs

```rust
#[cfg(test)]
mod tests {
    use crate::{Swarm, SwarmConfig, Agent, Instructions, SwarmError};
    use crate::constants::OPENAI_DEFAULT_API_URL;
    use std::sync::Arc;
    use reqwest::Client;
    use std::time::Duration;



    #[test]
    fn test_invalid_api_url() {
        let result = Swarm::builder()
            .with_api_key("sk-test123456789".to_string())
            .with_api_url("http://invalid-url.com".to_string()) // Non-HTTPS URL
            .build();

        assert!(result.is_err());
        match result {
            Err(SwarmError::ValidationError(msg)) => {
                assert!(msg.contains("API URL must start with https://"));
            }
            _ => panic!("Expected ValidationError for invalid API URL"),
        }
    }

    #[test]
    fn test_valid_configurations() {
        // Test valid configuration ranges
        let valid_config = SwarmConfig {
            request_timeout: 30,
            connect_timeout: 10,
            max_retries: 3,
            valid_model_prefixes: vec!["gpt-".to_string()],
            api_url: "https://api.openai.com/v1".to_string(),
            ..SwarmConfig::default()
        };

        let result = Swarm::builder()
            .with_api_key("sk-test123456789".to_string())
            .with_config(valid_config)
            .build();

        assert!(result.is_ok());
    }
    #[test]
    fn test_builder_basic_config() {
        let test_api_key = "sk-test123456789".to_string();

        let swarm = Swarm::builder()
            .with_api_key(test_api_key.clone())
            .build()
            .expect("Failed to build Swarm");

        assert_eq!(swarm.api_key, test_api_key);
        assert_eq!(swarm.config.api_url, OPENAI_DEFAULT_API_URL);
    }
    #[test]
    fn test_builder_api_settings() {
        let test_api_key = "sk-test123456789".to_string();
        let test_api_url = "https://api.openai.com/v2".to_string();
        let test_api_version = "2024-01".to_string();

        let swarm = Swarm::builder()
            .with_api_key(test_api_key.clone())
            .with_api_url(test_api_url.clone())
            .with_api_version(test_api_version.clone())
            .build()
            .expect("Failed to build Swarm");

        assert_eq!(swarm.api_key, test_api_key);
        assert_eq!(swarm.config.api_url, test_api_url);
        assert_eq!(swarm.config.api_version, test_api_version);
    }
    #[test]
    fn test_builder_timeout_settings() {
        let test_api_key = "sk-test123456789".to_string();
        let test_request_timeout = 60;
        let test_connect_timeout = 20;

        let swarm = Swarm::builder()
            .with_api_key(test_api_key.clone())
            .with_request_timeout(test_request_timeout)
            .with_connect_timeout(test_connect_timeout)
            .build()
            .expect("Failed to build Swarm");

        assert_eq!(swarm.config.request_timeout, test_request_timeout);
        assert_eq!(swarm.config.connect_timeout, test_connect_timeout);
    }
    #[test]
    fn test_builder_with_agent() {
        let test_api_key = "sk-test123456789".to_string();
        let agent = Agent {
            name: "test_agent".to_string(),
            model: "gpt-4".to_string(),
            instructions: Instructions::Text("Test instructions".to_string()),
            functions: vec![],
            function_call: None,
            parallel_tool_calls: false,
        };

        let swarm = Swarm::builder()
            .with_api_key(test_api_key)
            .with_agent(agent)
            .build()
            .expect("Failed to build Swarm");

        assert!(swarm.agent_registry.contains_key("test_agent"));
        assert_eq!(swarm.agent_registry["test_agent"].model, "gpt-4");
    }
    #[test]
    fn test_builder_with_custom_client() {
        let custom_client = Client::builder()
            .timeout(Duration::from_secs(45))
            .build()
            .expect("Failed to create custom client");

        let swarm = Swarm::builder()
            .with_api_key("sk-test123456789".to_string())
            .with_client(custom_client)
            .build()
            .expect("Failed to build Swarm");

        // Since we can't check the client's timeout directly,
        // we'll just verify the client was set
        assert!(Arc::strong_count(&Arc::new(swarm.client)) >= 1);
    }
    #[test]
    fn test_builder_default_values() {
        let swarm = Swarm::builder()
            .with_api_key("sk-test123456789".to_string())
            .build()
            .expect("Failed to build Swarm");

        let default_config = SwarmConfig::default();

        assert_eq!(swarm.config.api_url, default_config.api_url);
        assert_eq!(swarm.config.api_version, default_config.api_version);
        assert_eq!(swarm.config.request_timeout, default_config.request_timeout);
        assert_eq!(swarm.config.connect_timeout, default_config.connect_timeout);
        assert_eq!(swarm.config.max_retries, default_config.max_retries);
        assert_eq!(swarm.config.max_loop_iterations, default_config.max_loop_iterations);
        assert!(swarm.agent_registry.is_empty());
    }
}
```

### ./src/tests/mod.rs

```rust
pub mod agent;
pub mod builder;
pub mod initialization;
pub mod stream;
pub mod swarm_run;

```

### ./src/tests/initialization.rs

```rust
#[cfg(test)]
mod tests {
    use crate::{Swarm, SwarmConfig, Agent, Instructions, SwarmError};
    use crate::constants::{OPENAI_DEFAULT_API_URL, MIN_REQUEST_TIMEOUT, MAX_REQUEST_TIMEOUT};
    use crate::types::ApiSettings;

#[test]
fn test_valid_swarm_initialization() {
    // Create custom config
    let config = SwarmConfig {
        api_url: "https://api.openai.com/v1".to_string(),
        api_version: "v1".to_string(),
        request_timeout: 30,
        connect_timeout: 10,
        api_settings: ApiSettings::default(),
        max_retries: 3,
        max_loop_iterations: 10,
        valid_model_prefixes: vec!["gpt-".to_string()],
        valid_api_url_prefixes: vec!["https://api.openai.com".to_string()],
        loop_control: Default::default(),
    };

    // Create test agent
    let agent = Agent {
        name: "test_agent".to_string(),
        model: "gpt-4".to_string(),
        instructions: Instructions::Text("Test instructions".to_string()),
        functions: vec![],
        function_call: None,
        parallel_tool_calls: false,
    };

    // Initialize Swarm using builder pattern
    let swarm = Swarm::builder()
        .with_api_key("sk-test123456789".to_string())
        .with_config(config.clone())
        .with_agent(agent.clone())
        .build()
        .expect("Failed to create Swarm");

    // Verify fields are correctly set
    assert_eq!(swarm.api_key, "sk-test123456789");
    assert_eq!(swarm.config.api_url, config.api_url);
    assert_eq!(swarm.config.request_timeout, config.request_timeout);
    assert_eq!(swarm.config.connect_timeout, config.connect_timeout);
    assert_eq!(swarm.config.max_retries, config.max_retries);
    assert!(swarm.agent_registry.contains_key("test_agent"));
    assert_eq!(swarm.agent_registry["test_agent"].name, agent.name);
    assert_eq!(swarm.agent_registry["test_agent"].model, agent.model);
}

#[test]
fn test_default_swarm_initialization() {
    // Test default initialization using environment variable
    std::env::set_var("OPENAI_API_KEY", "sk-test123456789");

    let swarm = Swarm::default();

    // Verify default values
    assert_eq!(swarm.api_key, "sk-test123456789");
    assert!(swarm.agent_registry.is_empty());
    assert_eq!(swarm.config.api_url, OPENAI_DEFAULT_API_URL);

    // Clean up
    std::env::remove_var("OPENAI_API_KEY");
}

#[test]
fn test_missing_api_key() {
    // Remove API key from environment if present
    std::env::remove_var("OPENAI_API_KEY");

    // Attempt to create Swarm without API key
    let result = Swarm::builder().build();

    // Verify error
    assert!(result.is_err());
    match result {
        Err(SwarmError::ValidationError(msg)) => {
            assert!(msg.contains("API key must be set"));
        }
        _ => panic!("Expected ValidationError for missing API key"),
    }
}

#[test]
fn test_invalid_configurations() {
    // Test cases with invalid configurations
    let test_cases = vec![
        (
            SwarmConfig {
                request_timeout: 0,
                ..SwarmConfig::default()
            },
            "request_timeout must be greater than 0"
        ),
        (
            SwarmConfig {
                connect_timeout: 0,
                ..SwarmConfig::default()
            },
            "connect_timeout must be greater than 0"
        ),
        (
            SwarmConfig {
                max_retries: 0,
                ..SwarmConfig::default()
            },
            "max_retries must be greater than 0"
        ),
        (
            SwarmConfig {
                valid_model_prefixes: vec![],
                ..SwarmConfig::default()
            },
            "valid_model_prefixes cannot be empty"
        ),
        (
            SwarmConfig {
                request_timeout: MIN_REQUEST_TIMEOUT - 1,
                ..SwarmConfig::default()
            },
            "request_timeout must be between"
        ),
        (
            SwarmConfig {
                request_timeout: MAX_REQUEST_TIMEOUT + 1,
                ..SwarmConfig::default()
            },
            "request_timeout must be between"
        ),
    ];

    for (config, expected_error) in test_cases {
        let result = Swarm::builder()
            .with_api_key("sk-test123456789".to_string())
            .with_config(config)
            .build();

        assert!(result.is_err());
        match result {
            Err(SwarmError::ValidationError(msg)) => {
                assert!(
                    msg.contains(expected_error),
                    "Expected error message containing '{}', got '{}'",
                    expected_error,
                    msg
                );
            }
            _ => panic!("Expected ValidationError for invalid configuration"),
        }
    }
    }
}

```

### ./src/validation.rs

```rust
//  ./src/validation.rs
/// Validation module for Swarm API requests and configurations
///
/// This module provides validation functions to ensure that API requests
/// and configurations meet the required criteria before execution.
use crate::error::{SwarmError, SwarmResult};
use crate::types::{Agent, Instructions, Message, SwarmConfig};
use url::Url;

/// Validates an API request before execution
///
/// Performs comprehensive validation of all components of an API request,
/// including the agent configuration, message history, model selection,
/// and execution parameters.
///
/// # Arguments
///
/// * `agent` - The agent configuration to validate
/// * `messages` - The message history to validate
/// * `model` - Optional model override to validate
/// * `max_turns` - Maximum number of conversation turns (must be > 0 and <= config.max_loop_iterations)
///
/// # Returns
///
/// Returns `Ok(())` if all validations pass, or a `SwarmError` describing
/// the validation failure.
///
/// # Errors
///
/// Will return `SwarmError::ValidationError` if:
/// * Model name is empty or invalid
/// * Agent name is empty
/// * Agent instructions are empty
/// * Message roles or content are empty
/// * max_turns is 0 or exceeds config.max_loop_iterations
///
///
pub fn validate_api_request(
    agent: &Agent,
    messages: &[Message],
    model: &Option<String>,
    max_turns: usize,
) -> SwarmResult<()> {
    // Validate max_turns
    if max_turns == 0 {
        return Err(SwarmError::ValidationError(
            "max_turns must be greater than 0".to_string(),
        ));
    }

    // Validate model
    if let Some(model_name) = model {
        if model_name.trim().is_empty() {
            return Err(SwarmError::ValidationError("Model name cannot be empty".to_string()));
        }
    }

    // Validate agent
    if agent.name.trim().is_empty() {
        return Err(SwarmError::ValidationError("Agent name cannot be empty".to_string()));
    }

    match &agent.instructions {
        Instructions::Text(text) => {
            if text.trim().is_empty() {
                return Err(SwarmError::ValidationError(
                    "Agent instructions cannot be empty".to_string(),
                ));
            }
        }
        Instructions::Function(_) => {} // Function-based instructions are validated at runtime
    }

    // Validate messages
    for message in messages {
        if message.role.trim().is_empty() {
            return Err(SwarmError::ValidationError("Message role cannot be empty".to_string()));
        }

        // Only validate content if there's no function call
        if message.function_call.is_none() {
            if let Some(content) = &message.content {
                if content.trim().is_empty() {
                    return Err(SwarmError::ValidationError(
                        "Message content cannot be empty".to_string(),
                    ));
                }
            }
        }
    }

    Ok(())
}

/// Validates an API URL against configuration requirements
///
/// Ensures that the provided API URL meets all security and formatting
/// requirements specified in the configuration.
///
/// # Arguments
///
/// * `url` - The URL string to validate
/// * `config` - The SwarmConfig containing validation rules
///
/// # Returns
///
/// Returns `Ok(())` if the URL is valid, or a `SwarmError` describing
/// the validation failure.
///
/// # Errors
///
/// Will return `SwarmError::ValidationError` if:
/// * URL is empty
/// * URL format is invalid
/// * URL scheme is not HTTPS
/// * URL doesn't match any allowed prefixes from config
///
pub fn validate_api_url(url: &str, config: &SwarmConfig) -> SwarmResult<()> {
    // Check if URL is empty
    if url.trim().is_empty() {
        return Err(SwarmError::ValidationError("API URL cannot be empty".to_string()));
    }

    // Parse URL
    let parsed_url = Url::parse(url)
        .map_err(|e| SwarmError::ValidationError(format!("Invalid API URL format: {}", e)))?;

    // Allow localhost URLs on any port
    if parsed_url.host_str() == Some("localhost") {
        return Ok(());
    }

    // Verify against allowed prefixes
    if !config.valid_api_url_prefixes
        .iter()
        .any(|prefix| url.starts_with(prefix))
    {
        return Err(SwarmError::ValidationError(format!(
            "API URL must start with one of: {}",
            config.valid_api_url_prefixes.join(", ")
        )));
    }

    Ok(())
}
```

### ./src/lib.rs

```rust
// ./src/lib.rs
pub mod constants;
pub mod core;
pub mod types;
pub mod util;
pub mod validation;

pub use crate::core::Swarm;
pub use crate::types::{Agent, Instructions, Message, Response, SwarmConfig};

pub mod error;
pub use error::{SwarmError, SwarmResult};

pub mod tests;

pub mod stream;

```

### ./src/util.rs

```rust
// ./src/util.rs
use crate::error::{SwarmError, SwarmResult};
/// Utility functions for the Swarm library
///
/// This module provides various helper functions for debugging, message handling,
/// XML processing, and function conversion utilities.
use crate::types::{AgentFunction, FunctionCall, Message, Steps};
use quick_xml::de::from_str as xml_from_str;
use regex::Regex;
use serde_json::{json, Value};

/// Prints debug messages when debug mode is enabled
///
/// Prefixes debug messages with "[DEBUG]" for easy identification in logs.
///
/// # Arguments
///
/// * `debug` - Boolean flag to enable/disable debug output
/// * `message` - The message to print
///
///
pub fn debug_print(debug: bool, message: &str) {
    if debug {
        println!("[DEBUG]: {}", message);
    }
}

/// Merges a delta message chunk into an existing message
///
/// Used for handling streaming responses where message content arrives in chunks.
/// Updates both content and function calls in the existing message. Particularly
/// useful when processing streaming responses from the OpenAI API.
///
/// # Arguments
///
/// * `message` - The existing message to update
/// * `delta` - The new chunk of message data to merge
///
///
pub fn merge_chunk_message(message: &mut Message, delta: &serde_json::Map<String, Value>) {
    for (key, value) in delta {
        match key.as_str() {
            "content" => {
                if let Some(content) = value.as_str() {
                    if let Some(existing_content) = &mut message.content {
                        existing_content.push_str(content);
                    } else {
                        message.content = Some(content.to_string());
                    }
                }
            }
            "function_call" => {
                if let Ok(function_call) = serde_json::from_value::<FunctionCall>(value.clone()) {
                    message.function_call = Some(function_call);
                }
            }
            _ => {}
        }
    }
}

/// Converts an AgentFunction to a JSON representation
///
/// Transforms a function definition into the format expected by the OpenAI API.
///
/// # Arguments
///
/// * `func` - The AgentFunction to convert
///
/// # Returns
///
/// Returns a Result containing the JSON Value representation of the function
///
/// # Errors
///
/// Will return an error if JSON serialization fails
///
///
pub fn function_to_json(func: &AgentFunction) -> SwarmResult<Value> {
    let parameters = json!({
        "type": "object",
        "properties": {},
        "required": [],
    });

    Ok(json!({
        "name": func.name,
        "description": "",
        "parameters": parameters,
    }))
}

/// Parses XML content into a Steps structure
///
/// Converts XML-formatted step definitions into a structured Steps object
/// that can be executed by the agent.
///
/// # Arguments
///
/// * `xml_content` - The XML string containing step definitions
///
/// # Returns
///
/// Returns a Result containing the parsed Steps structure
///
/// # Errors
///
/// Will return an error if:
/// * XML parsing fails
/// * Required attributes are missing
/// * Step structure is invalid
///
/// # Examples
///
pub fn parse_steps_from_xml(xml_content: &str) -> SwarmResult<Steps> {
    xml_from_str(xml_content)
        .map_err(|e| SwarmError::XmlError(format!("Failed to parse XML steps: {}", e)))
}

/// Extracts XML step definitions from instructions text
///
/// Searches for and extracts XML step definitions from a larger text,
/// returning both the instructions without XML and the extracted XML content.
///
/// # Arguments
///
/// * `instructions` - The full instructions text containing potential XML steps
///
/// # Returns
///
/// Returns a tuple containing:
/// * The instructions text with XML removed
/// * Optional XML content if found
///
/// # Errors
///
/// Will return an error if:
/// * Regex pattern is invalid
/// * XML content is malformed
///
///
pub fn extract_xml_steps(instructions: &str) -> SwarmResult<(String, Option<String>)> {
    let mut instructions_without_xml = instructions.to_string();
    let mut xml_steps = None;

    // Improved regex to be more robust
    let re = Regex::new(r"(?s)<steps\b[^>]*>.*?</steps>")
        .map_err(|e| SwarmError::Other(format!("Invalid regex pattern: {}", e)))?;

    if let Some(mat) = re.find(&instructions) {
        let xml_content = mat.as_str();
        instructions_without_xml.replace_range(mat.range(), "");
        xml_steps = Some(xml_content.to_string());
    }

    Ok((instructions_without_xml.trim().to_string(), xml_steps))
}

```

### ./src/error.rs

```rust
// ./src/error.rs
/// Error types for the Swarm library
///
/// This module provides a comprehensive error handling system for all operations
/// within the Swarm library, including API communication, configuration,
/// validation, and agent interactions.
use thiserror::Error;

/// Main error type for the Swarm library
///
/// Encompasses all possible error conditions that can occur during
/// Swarm operations, from API communication to agent execution.
///
/// # Examples
///
/// ```rust
/// use rswarm::SwarmError;
///
/// let error = SwarmError::ApiError("Rate limit exceeded".to_string());
/// assert_eq!(error.to_string(), "API error: Rate limit exceeded");
///
/// // Checking if an error is retriable
/// assert!(SwarmError::NetworkError("Connection refused".to_string()).is_retriable());
/// ```
#[derive(Error, Debug)]
pub enum SwarmError {
    /// Errors returned by the API
    #[error("API error: {0}")]
    ApiError(String),

    /// Configuration-related errors
    #[error("Configuration error: {0}")]
    ConfigError(String),

    /// Errors related to agent execution
    #[error("Agent error: {0}")]
    AgentError(String),

    /// Input validation errors
    #[error("Invalid input: {0}")]
    ValidationError(String),

    /// Rate limiting errors from the API
    #[error("Rate limit exceeded: {0}")]
    RateLimitError(String),

    /// Network communication errors
    #[error("Network error: {0}")]
    NetworkError(String),

    /// Timeout-related errors
    #[error("Timeout error: {0}")]
    TimeoutError(String),

    /// Authentication and authorization errors
    #[error("Authentication error: {0}")]
    AuthError(String),

    /// HTTP client errors from reqwest
    #[error(transparent)]
    ReqwestError(#[from] reqwest::Error),

    /// Environment variable errors
    #[error(transparent)]
    EnvVarError(#[from] std::env::VarError),

    /// Data serialization errors
    #[error("Serialization error: {0}")]
    SerializationError(String),

    /// Data deserialization errors
    #[error("Deserialization error: {0}")]
    DeserializationError(String),

    /// XML parsing and processing errors
    #[error("XML parsing error: {0}")]
    XmlError(String),

    /// Errors when an agent is not found in the registry
    #[error("Agent not found: {0}")]
    AgentNotFoundError(String),

    /// Function execution errors
    #[error("Function execution error: {0}")]
    FunctionError(String),

    /// Stream processing errors
    #[error("Stream processing error: {0}")]
    StreamError(String),

    /// Context variables related errors
    #[error("Context variables error: {0}")]
    ContextError(String),

    /// Maximum iterations exceeded errors
    #[error("Maximum iterations exceeded: {0}")]
    MaxIterationsError(String),

    /// JSON processing errors
    #[error(transparent)]
    JsonError(#[from] serde_json::Error),

    /// XML parsing errors from quick-xml
    #[error(transparent)]
    XmlParseError(#[from] quick_xml::DeError),

    /// Generic/catch-all errors
    #[error("Other error: {0}")]
    Other(String),

    /// Request timeout errors with duration
    #[error("Request timed out after {0} seconds")]
    RequestTimeoutError(u64),

    /// URL validation errors
    #[error("URL validation error: {0}")]
    UrlValidationError(String),
}

/// Type alias for Results using SwarmError
///
/// Provides a convenient way to return Results with SwarmError as the error type.
///
/// # Examples
///
/// ```rust
/// use rswarm::{SwarmResult, SwarmError};
///
/// fn example_function() -> SwarmResult<String> {
///     Ok("Success".to_string())
/// }
///
/// fn error_function() -> SwarmResult<()> {
///     Err(SwarmError::ValidationError("Invalid input".to_string()))
/// }
/// ```
pub type SwarmResult<T> = Result<T, SwarmError>;

impl SwarmError {
    /// Determines if the error is potentially retriable
    ///
    /// Returns true for errors that might succeed on retry, such as
    /// network errors, timeouts, and rate limit errors.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rswarm::SwarmError;
    ///
    /// let error = SwarmError::NetworkError("Connection reset".to_string());
    /// assert!(error.is_retriable());
    ///
    /// let error = SwarmError::ValidationError("Invalid input".to_string());
    /// assert!(!error.is_retriable());
    /// ```
    pub fn is_retriable(&self) -> bool {
        matches!(
            self,
            SwarmError::NetworkError(_) |
            SwarmError::TimeoutError(_) |
            SwarmError::RateLimitError(_)
        )
    }

    /// Determines if the error is related to configuration
    ///
    /// Returns true for errors that indicate configuration problems,
    /// such as invalid settings or missing credentials.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rswarm::SwarmError;
    ///
    /// let error = SwarmError::ConfigError("Invalid API URL".to_string());
    /// assert!(error.is_configuration_error());
    ///
    /// let error = SwarmError::NetworkError("Connection failed".to_string());
    /// assert!(!error.is_configuration_error());
    /// ```
    pub fn is_configuration_error(&self) -> bool {
        matches!(
            self,
            SwarmError::ConfigError(_) |
            SwarmError::AuthError(_) |
            SwarmError::EnvVarError(_)
        )
    }
}

/// Implement From for common error conversions
impl From<anyhow::Error> for SwarmError {
    fn from(err: anyhow::Error) -> Self {
        SwarmError::Other(err.to_string())
    }
}

impl From<std::io::Error> for SwarmError {
    fn from(err: std::io::Error) -> Self {
        SwarmError::Other(err.to_string())
    }
}
```

### ./src/constants.rs

```rust
pub const CTX_VARS_NAME: &str = "context_variables";
pub const OPENAI_DEFAULT_API_URL: &str = "https://api.openai.com/v1/chat/completions";
pub const ROLE_ASSISTANT: &str = "assistant";
pub const ROLE_FUNCTION: &str = "function";
pub const ROLE_SYSTEM: &str = "system";
pub const DEFAULT_REQUEST_TIMEOUT: u64 = 30; // 30 seconds timeout
pub const DEFAULT_CONNECT_TIMEOUT: u64 = 10; // 10 seconds for connection timeout
pub const VALID_API_URL_PREFIXES: [&str; 8] = [
    "https://api.openai.com",
    "https://api.azure.com/openai",
    "https://openrouter.ai/api/",
    "https://openrouter.ai/",
    "https://openrouter.ai/api/v1/",
    "https://api.deepseek.com",
    "https://api.deepseek.com/chat/",
    "https://api.deepseek.com/chat/completions",
];
pub const DEFAULT_API_VERSION: &str = "v1";
pub const DEFAULT_MAX_LOOP_ITERATIONS: u32 = 10;
pub const DEFAULT_ITERATION_DELAY_MS: u64 = 100;
pub const DEFAULT_BREAK_CONDITIONS: [&str; 1] = ["end_loop"];
pub const MIN_REQUEST_TIMEOUT: u64 = 5;
pub const MAX_REQUEST_TIMEOUT: u64 = 300;


#[derive(Clone, Debug)]
pub struct OpenAICredentials {
    pub api_key: String,
    pub model: String,
}

impl OpenAICredentials {
    pub fn new(api_key: String, model: String) -> OpenAICredentials {
        OpenAICredentials {
            api_key,
            model,
        }
    }

    // Get OPENAI_API_KEY and OPENAI_MODEL from .env
    pub fn get_openai_credentials() -> OpenAICredentials {
        let api_key = std::env::var("OPENAI_API_KEY")
            .expect("OPENAI_API_KEY must be set in environment variables");
        let model = std::env::var("OPENAI_MODEL")
            .unwrap_or_else(|_| String::from("gpt-3.5-turbo"));

        OpenAICredentials::new(api_key, model)
    }
}


```

### ./src/types.rs

```rust
// File: rswarm/src/types.rs

use crate::constants::{
    DEFAULT_API_VERSION, DEFAULT_CONNECT_TIMEOUT, DEFAULT_REQUEST_TIMEOUT, OPENAI_DEFAULT_API_URL,
    VALID_API_URL_PREFIXES,
};
use anyhow::Error;
use serde::ser::SerializeStruct;
use serde::{
    de::{self, MapAccess, Visitor},
    Deserialize, Deserializer, Serialize, Serializer,
};
use std::collections::HashMap;
use std::fmt;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::time::Duration;

/// A map of string key–value pairs used for context variables in agent interactions.
pub type ContextVariables = HashMap<String, String>;

/// Represents instructions that can be given to an agent.
///
/// Instructions can be either static text or a dynamic function that generates
/// instructions based on context variables.
#[derive(Clone)]
pub enum Instructions {
    Text(String),
    Function(Arc<dyn Fn(ContextVariables) -> String + Send + Sync>),
}

/// Represents an AI agent with its configuration and capabilities.
///
/// An agent is defined by its name, model, instructions, and available functions.
#[derive(Clone)]
pub struct Agent {
    pub name: String,
    pub model: String,
    pub instructions: Instructions,
    pub functions: Vec<AgentFunction>,
    pub function_call: Option<String>,
    pub parallel_tool_calls: bool,
}

// Custom Debug implementation for Agent.
impl fmt::Debug for Agent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Since we cannot print the functions (they may contain closures), we omit them.
        write!(
            f,
            "Agent {{ name: {}, model: {}, function_call: {:?}, parallel_tool_calls: {} }}",
            self.name, self.model, self.function_call, self.parallel_tool_calls
        )
    }
}

// Custom Serialize implementation for Agent.
impl Serialize for Agent {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state = serializer.serialize_struct("Agent", 5)?;
        state.serialize_field("name", &self.name)?;
        state.serialize_field("model", &self.model)?;
        // We cannot serialize `instructions` or `functions` since they may contain closures.
        state.serialize_field("function_call", &self.function_call)?;
        state.serialize_field("parallel_tool_calls", &self.parallel_tool_calls)?;
        state.end()
    }
}

// Custom Deserialize implementation for Agent.
impl<'de> Deserialize<'de> for Agent {
    fn deserialize<D>(deserializer: D) -> Result<Agent, D::Error>
    where
        D: Deserializer<'de>,
    {
        enum Field {
            Name,
            Model,
            FunctionCall,
            ParallelToolCalls,
        }

        impl<'de> Deserialize<'de> for Field {
            fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
            where
                D: Deserializer<'de>,
            {
                struct FieldVisitor;

                impl<'de> Visitor<'de> for FieldVisitor {
                    type Value = Field;

                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter
                            .write_str("`name`, `model`, `function_call`, or `parallel_tool_calls`")
                    }

                    fn visit_str<E>(self, value: &str) -> Result<Field, E>
                    where
                        E: de::Error,
                    {
                        match value {
                            "name" => Ok(Field::Name),
                            "model" => Ok(Field::Model),
                            "function_call" => Ok(Field::FunctionCall),
                            "parallel_tool_calls" => Ok(Field::ParallelToolCalls),
                            _ => Err(de::Error::unknown_field(value, FIELDS)),
                        }
                    }
                }

                deserializer.deserialize_identifier(FieldVisitor)
            }
        }

        struct AgentVisitor;

        impl<'de> Visitor<'de> for AgentVisitor {
            type Value = Agent;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("struct Agent")
            }

            fn visit_map<V>(self, mut map: V) -> Result<Agent, V::Error>
            where
                V: MapAccess<'de>,
            {
                let mut name = None;
                let mut model = None;
                let mut function_call = None;
                let mut parallel_tool_calls = None;

                while let Some(key) = map.next_key()? {
                    match key {
                        Field::Name => {
                            if name.is_some() {
                                return Err(de::Error::duplicate_field("name"));
                            }
                            name = Some(map.next_value()?);
                        }
                        Field::Model => {
                            if model.is_some() {
                                return Err(de::Error::duplicate_field("model"));
                            }
                            model = Some(map.next_value()?);
                        }
                        Field::FunctionCall => {
                            if function_call.is_some() {
                                return Err(de::Error::duplicate_field("function_call"));
                            }
                            function_call = Some(map.next_value()?);
                        }
                        Field::ParallelToolCalls => {
                            if parallel_tool_calls.is_some() {
                                return Err(de::Error::duplicate_field("parallel_tool_calls"));
                            }
                            parallel_tool_calls = Some(map.next_value()?);
                        }
                    }
                }

                let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
                let model = model.ok_or_else(|| de::Error::missing_field("model"))?;
                let parallel_tool_calls = parallel_tool_calls.unwrap_or(false);

                Ok(Agent {
                    name,
                    model,
                    instructions: Instructions::Text(String::new()), // Default value.
                    functions: Vec::new(),                           // Default value.
                    function_call,
                    parallel_tool_calls,
                })
            }
        }

        const FIELDS: &'static [&'static str] =
            &["name", "model", "function_call", "parallel_tool_calls"];

        deserializer.deserialize_struct("Agent", FIELDS, AgentVisitor)
    }
}

/// The result of an agent function execution.
#[derive(Clone, Debug)]
pub enum ResultType {
    Value(String),
    Agent(Agent),
    ContextVariables(ContextVariables),
}

impl ResultType {
    pub fn get_value(&self) -> String {
        match self {
            ResultType::Value(v) => v.clone(),
            _ => String::new(),
        }
    }

    pub fn get_agent(&self) -> Option<Agent> {
        if let ResultType::Agent(agent) = self {
            Some(agent.clone())
        } else {
            None
        }
    }

    pub fn get_context_variables(&self) -> ContextVariables {
        if let ResultType::ContextVariables(vars) = self {
            vars.clone()
        } else {
            HashMap::new()
        }
    }
}

/// Represents an asynchronous agent function.
///
/// The function field now returns a pinned future that will output a
/// `Result<ResultType, anyhow::Error>` when awaited.
#[derive(Clone)]
pub struct AgentFunction {
    pub name: String,
    pub function: Arc<
        dyn Fn(ContextVariables) -> Pin<Box<dyn Future<Output = Result<ResultType, Error>> + Send>>
            + Send
            + Sync,
    >,
    pub accepts_context_variables: bool,
}

/// Configuration settings for the Swarm instance.
#[derive(Clone, Debug)]
pub struct SwarmConfig {
    pub api_url: String,
    pub api_version: String,
    pub request_timeout: u64,
    pub connect_timeout: u64,
    pub max_retries: u32,
    pub max_loop_iterations: u32,
    pub valid_model_prefixes: Vec<String>,
    pub valid_api_url_prefixes: Vec<String>,
    pub loop_control: LoopControl,
    pub api_settings: ApiSettings,
}

/// Controls the execution of loops in agent interactions.
#[derive(Clone, Debug)]
pub struct LoopControl {
    pub default_max_iterations: u32,
    pub iteration_delay: Duration,
    pub break_conditions: Vec<String>,
}

impl Default for LoopControl {
    fn default() -> Self {
        LoopControl {
            default_max_iterations: 10,
            iteration_delay: Duration::from_millis(100),
            break_conditions: vec!["end_loop".to_string()],
        }
    }
}

/// API related settings for request handling.
#[derive(Clone, Debug)]
pub struct ApiSettings {
    pub retry_strategy: RetryStrategy,
    pub timeout_settings: TimeoutSettings,
}

impl Default for ApiSettings {
    fn default() -> Self {
        ApiSettings {
            retry_strategy: RetryStrategy {
                max_retries: 3,
                initial_delay: Duration::from_secs(1),
                max_delay: Duration::from_secs(30),
                backoff_factor: 2.0,
            },
            timeout_settings: TimeoutSettings {
                request_timeout: Duration::from_secs(30),
                connect_timeout: Duration::from_secs(10),
                read_timeout: Duration::from_secs(30),
                write_timeout: Duration::from_secs(30),
            },
        }
    }
}

impl Default for SwarmConfig {
    fn default() -> Self {
        SwarmConfig {
            api_url: OPENAI_DEFAULT_API_URL.to_string(),
            api_version: DEFAULT_API_VERSION.to_string(),
            request_timeout: DEFAULT_REQUEST_TIMEOUT,
            connect_timeout: DEFAULT_CONNECT_TIMEOUT,
            max_retries: 3,
            max_loop_iterations: 10,
            valid_model_prefixes: vec![
                "gpt-".to_string(),
                "deepseek-".to_string(),
                "claude-".to_string(),
                "openai-".to_string(),
                "openrouter-".to_string(),
            ],
            valid_api_url_prefixes: VALID_API_URL_PREFIXES
                .iter()
                .map(|&s| s.to_string())
                .collect(),
            loop_control: LoopControl::default(),
            api_settings: ApiSettings::default(),
        }
    }
}

/// Represents a chat message.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Message {
    pub role: String,
    pub content: Option<String>,
    pub name: Option<String>,
    pub function_call: Option<FunctionCall>,
}

/// Represents a function call inside a message.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct FunctionCall {
    pub name: String,
    pub arguments: String,
}

/// The response from a chat completion request.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ChatCompletionResponse {
    pub id: String,
    pub object: String,
    pub created: u64,
    pub choices: Vec<Choice>,
    pub usage: Option<Usage>,
}

/// A choice returned from the chat completion response.
///
/// This custom deserializer checks for the presence of a "message" field and,
/// if absent, falls back to a "delta" field.
#[derive(Serialize, Clone, Debug)]
pub struct Choice {
    pub index: u32,
    pub message: Message,
    pub finish_reason: Option<String>,
}

impl<'de> Deserialize<'de> for Choice {
    fn deserialize<D>(deserializer: D) -> Result<Choice, D::Error>
    where
        D: Deserializer<'de>,
    {
        let value = serde_json::Value::deserialize(deserializer)?;

        let index = value
            .get("index")
            .and_then(|v| v.as_u64())
            .ok_or_else(|| de::Error::missing_field("index"))? as u32;

        let finish_reason = value
            .get("finish_reason")
            .and_then(|v| v.as_str())
            .map(String::from);

        let message = if let Some(msg_val) = value.get("message") {
            serde_json::from_value(msg_val.clone()).map_err(de::Error::custom)?
        } else if let Some(delta_val) = value.get("delta") {
            let role = delta_val
                .get("role")
                .and_then(|v| v.as_str())
                .unwrap_or("")
                .to_string();
            let content = delta_val
                .get("content")
                .and_then(|v| v.as_str())
                .map(|s| s.to_string());
            Message {
                role,
                content,
                name: None,
                function_call: None,
            }
        } else {
            return Err(de::Error::missing_field("message (or delta)"));
        };

        Ok(Choice {
            index,
            message,
            finish_reason,
        })
    }
}

/// Token usage metrics for a chat completion.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Usage {
    pub prompt_tokens: u32,
    pub completion_tokens: u32,
    pub total_tokens: u32,
}

/// Represents a complete chat response.
#[derive(Clone, Debug)]
pub struct Response {
    pub messages: Vec<Message>,
    pub agent: Option<Agent>,
    pub context_variables: ContextVariables,
}

/// Represents a collection of steps parsed from XML.
#[derive(Debug, Deserialize)]
pub struct Steps {
    #[serde(rename = "step", default)]
    pub steps: Vec<Step>,
}

/// A single step in a steps definition.
#[derive(Debug, Deserialize)]
pub struct Step {
    #[serde(rename = "@number")]
    pub number: usize,
    #[serde(rename = "@action")]
    pub action: String,
    #[serde(rename = "@agent")]
    pub agent: Option<String>,
    pub prompt: String,
}

/// Strategy used for retrying failed API calls.
#[derive(Clone, Debug)]
pub struct RetryStrategy {
    pub max_retries: u32,
    pub initial_delay: Duration,
    pub max_delay: Duration,
    pub backoff_factor: f32,
}

/// Timeout settings used for API calls.
#[derive(Clone, Debug)]
pub struct TimeoutSettings {
    pub request_timeout: Duration,
    pub connect_timeout: Duration,
    pub read_timeout: Duration,
    pub write_timeout: Duration,
}

/// Represents an error response from OpenAI.
#[derive(Debug, Deserialize)]
pub struct OpenAIErrorResponse {
    pub error: OpenAIError,
}

/// The detailed OpenAI error.
#[derive(Debug, Deserialize)]
pub struct OpenAIError {
    pub message: String,
    #[serde(rename = "type")]
    pub error_type: String,
    pub param: Option<String>,
    pub code: Option<String>,
}

```

### ./src/core.rs

```rust
/*
   File: rswarm/src/core.rs

   This file implements the main Swarm struct that handles chat completions,
   message history, function calls and step execution. Note that agent function
   calls are now asynchronous and are awaited without blocking the runtime.
*/

use crate::constants::{
    CTX_VARS_NAME, MAX_REQUEST_TIMEOUT, MIN_REQUEST_TIMEOUT, OPENAI_DEFAULT_API_URL,
    ROLE_ASSISTANT, ROLE_FUNCTION, ROLE_SYSTEM,
};
use crate::error::{SwarmError, SwarmResult};
use crate::types::{
    Agent, AgentFunction, ChatCompletionResponse, ContextVariables, FunctionCall, Instructions,
    Message, OpenAIErrorResponse, Response, ResultType, Step, Steps, SwarmConfig,
};
use crate::util::{debug_print, extract_xml_steps, function_to_json, parse_steps_from_xml};
use crate::validation::{validate_api_request, validate_api_url};
use futures::StreamExt;
use reqwest::Client;
use serde_json::{json, Value};
use std::collections::HashMap;
use std::env;
use std::sync::Arc;
use std::time::Duration;

impl Default for Swarm {
    fn default() -> Self {
        Swarm::new(None, None, HashMap::new()).expect("Default initialization should never fail")
    }
}

/// Main struct for managing AI agent interactions and chat completions.
pub struct Swarm {
    pub client: Client,
    pub api_key: String,
    pub agent_registry: HashMap<String, Agent>,
    pub config: SwarmConfig,
}

/// Builder pattern implementation for creating Swarm instances.
pub struct SwarmBuilder {
    client: Option<Client>,
    api_key: Option<String>,
    agents: HashMap<String, Agent>,
    config: SwarmConfig,
}

impl SwarmBuilder {
    pub fn new() -> Self {
        let config = SwarmConfig::default();
        SwarmBuilder {
            client: None,
            api_key: None,
            agents: HashMap::new(),
            config,
        }
    }

    pub fn with_config(mut self, config: SwarmConfig) -> Self {
        self.config = config;
        self
    }

    pub fn with_api_url(mut self, api_url: String) -> Self {
        self.config.api_url = api_url;
        self
    }

    pub fn with_api_version(mut self, version: String) -> Self {
        self.config.api_version = version;
        self
    }

    pub fn with_request_timeout(mut self, timeout: u64) -> Self {
        self.config.request_timeout = timeout;
        self
    }

    pub fn with_connect_timeout(mut self, timeout: u64) -> Self {
        self.config.connect_timeout = timeout;
        self
    }

    pub fn with_max_retries(mut self, retries: u32) -> Self {
        self.config.max_retries = retries;
        self
    }

    pub fn with_max_loop_iterations(mut self, iterations: u32) -> Self {
        self.config.max_loop_iterations = iterations;
        self
    }

    pub fn with_valid_model_prefixes(mut self, prefixes: Vec<String>) -> Self {
        self.config.valid_model_prefixes = prefixes;
        self
    }

    pub fn with_valid_api_url_prefixes(mut self, prefixes: Vec<String>) -> Self {
        self.config.valid_api_url_prefixes = prefixes;
        self
    }

    pub fn with_client(mut self, client: Client) -> Self {
        self.client = Some(client);
        self
    }

    pub fn with_api_key(mut self, api_key: String) -> Self {
        self.api_key = Some(api_key);
        self
    }

    pub fn with_agent(mut self, agent: Agent) -> Self {
        self.agents.insert(agent.name.clone(), agent);
        self
    }

    pub fn with_agents(mut self, agents: &HashMap<String, Agent>) -> Self {
        for agent in agents.values() {
            self = self.with_agent(agent.clone());
        }
        self
    }

    pub fn build(self) -> SwarmResult<Swarm> {
        self.config.validate()?;

        for agent in self.agents.values() {
            agent.validate(&self.config)?;
        }

        let api_key = match self.api_key.or_else(|| env::var("OPENAI_API_KEY").ok()) {
            Some(key) => key,
            None => {
                return Err(SwarmError::ValidationError(
                    "API key must be set either in environment or passed to builder".to_string(),
                ))
            }
        };

        if api_key.trim().is_empty() {
            return Err(SwarmError::ValidationError(
                "API key cannot be empty".to_string(),
            ));
        }
        if !api_key.starts_with("sk-") {
            return Err(SwarmError::ValidationError(
                "Invalid API key format".to_string(),
            ));
        }

        let api_url = self.config.api_url.clone();

        if !api_url.starts_with("https://")
            && !api_url.starts_with("http://localhost")
            && !api_url.starts_with("http://127.0.0.1")
        {
            return Err(SwarmError::ValidationError(
                "API URL must start with https:// (except for localhost)".to_string(),
            ));
        }

        validate_api_url(&api_url, &self.config)?;

        let client = self.client.unwrap_or_else(|| {
            Client::builder()
                .timeout(Duration::from_secs(self.config.request_timeout))
                .connect_timeout(Duration::from_secs(self.config.connect_timeout))
                .build()
                .unwrap_or_else(|_| Client::new())
        });

        Ok(Swarm {
            client,
            api_key,
            agent_registry: self.agents,
            config: self.config,
        })
    }

    fn _validate(&self) -> SwarmResult<()> {
        if let Some(ref key) = self.api_key {
            if key.trim().is_empty() || !key.starts_with("sk-") {
                return Err(SwarmError::ValidationError(
                    "Invalid API key format".to_string(),
                ));
            }
        }
        self.config.validate()?;
        Ok(())
    }
}

impl Swarm {
    pub fn builder() -> SwarmBuilder {
        SwarmBuilder::new()
    }

    // For backward compatibility.
    pub fn new(
        client: Option<Client>,
        api_key: Option<String>,
        _agents: HashMap<String, Agent>,
    ) -> SwarmResult<Self> {
        let mut builder = SwarmBuilder::new();

        if let Some(client) = client {
            builder = builder.with_client(client);
        }
        if let Some(api_key) = api_key {
            builder = builder.with_api_key(api_key);
        }

        builder.build()
    }

    /// Makes an asynchronous chat completion request.
    pub async fn get_chat_completion(
        &self,
        agent: &Agent,
        history: &[Message],
        context_variables: &ContextVariables,
        model_override: Option<String>,
        stream: bool,
        debug: bool,
    ) -> SwarmResult<ChatCompletionResponse> {
        if self.api_key.is_empty() {
            return Err(SwarmError::ValidationError(
                "API key cannot be empty".to_string(),
            ));
        }

        if history.is_empty() {
            return Err(SwarmError::ValidationError(
                "Message history cannot be empty".to_string(),
            ));
        }

        let instructions = match &agent.instructions {
            Instructions::Text(text) => text.clone(),
            Instructions::Function(func) => func(context_variables.clone()),
        };

        let mut messages = vec![Message {
            role: ROLE_SYSTEM.to_string(),
            content: Some(instructions),
            name: None,
            function_call: None,
        }];

        messages.extend_from_slice(history);

        debug_print(
            debug,
            &format!("Getting chat completion with messages: {:?}", messages),
        );

        let functions: Vec<Value> = agent
            .functions
            .iter()
            .map(function_to_json)
            .collect::<SwarmResult<Vec<Value>>>()?;

        let model = model_override.unwrap_or_else(|| agent.model.clone());

        let mut request_body = json!({
            "model": model,
            "messages": messages,
        });

        if !functions.is_empty() {
            request_body["functions"] = Value::Array(functions);
        }

        if let Some(function_call) = &agent.function_call {
            request_body["function_call"] = json!(function_call);
        }

        if stream {
            request_body["stream"] = json!(true);
        }

        let url = env::var("OPENAI_API_URL")
            .map(|url| {
                if url.starts_with("http://localhost") || url.starts_with("http://127.0.0.1") {
                    Ok(url)
                } else if !url.starts_with("https://") {
                    Err(SwarmError::ValidationError(
                        "OPENAI_API_URL must start with https:// (except for localhost)"
                            .to_string(),
                    ))
                } else {
                    Ok(url)
                }
            })
            .unwrap_or_else(|_| Ok(OPENAI_DEFAULT_API_URL.to_string()))?;

        let response = self
            .client
            .post(url)
            .bearer_auth(&self.api_key)
            .json(&request_body)
            .send()
            .await
            .map_err(|e| SwarmError::NetworkError(e.to_string()))?;

        if !response.status().is_success() {
            let error_text = response.text().await.map_err(|e| {
                SwarmError::NetworkError(format!("Failed to read error response: {}", e))
            })?;
            debug_print(debug, &format!("API Error Response: {}", error_text));
            let api_error: serde_json::Result<OpenAIErrorResponse> =
                serde_json::from_str(&error_text);
            return match api_error {
                Ok(err_resp) => Err(SwarmError::ApiError(err_resp.error.message)),
                Err(_) => Err(SwarmError::ApiError(error_text)),
            };
        }

        if stream {
            let mut stream = response.bytes_stream();
            let mut full_response = ChatCompletionResponse {
                id: "".to_string(),
                object: "chat.completion".to_string(),
                created: 0,
                choices: Vec::new(),
                usage: None,
            };

            while let Some(chunk_result) = stream.next().await {
                match chunk_result {
                    Ok(data) => {
                        let text = String::from_utf8_lossy(&data);
                        for line in text.lines() {
                            if line.starts_with("data: ") {
                                let json_str = line[6..].trim();
                                if json_str == "[DONE]" {
                                    break;
                                }
                                let partial_response: serde_json::Result<ChatCompletionResponse> =
                                    serde_json::from_str(json_str);
                                if let Ok(partial) = partial_response {
                                    full_response.choices.extend(partial.choices);
                                }
                            }
                        }
                    }
                    Err(e) => {
                        return Err(SwarmError::StreamError(format!(
                            "Error reading streaming response: {}",
                            e
                        )))
                    }
                }
            }
            Ok(full_response)
        } else {
            let response_text = response.text().await.map_err(|e| {
                SwarmError::DeserializationError(format!("Failed to read response text: {}", e))
            })?;
            debug_print(debug, &format!("API Response: {}", response_text));
            serde_json::from_str::<ChatCompletionResponse>(&response_text)
                .map_err(|e| SwarmError::DeserializationError(e.to_string()))
        }
    }

    /// Asynchronously handles a function call from an agent.
    pub async fn handle_function_call(
        &self,
        function_call: &FunctionCall,
        functions: &[AgentFunction],
        context_variables: &mut ContextVariables,
        debug: bool,
    ) -> SwarmResult<Response> {
        if function_call.name.trim().is_empty() {
            return Err(SwarmError::ValidationError(
                "Function call name cannot be empty.".to_string(),
            ));
        }

        let mut function_map = HashMap::new();
        for func in functions {
            function_map.insert(func.name.clone(), func.clone());
        }

        let mut response = Response {
            messages: Vec::new(),
            agent: None,
            context_variables: HashMap::new(),
        };

        if let Some(func) = function_map.get(&function_call.name) {
            let args: ContextVariables = serde_json::from_str(&function_call.arguments)?;
            debug_print(
                debug,
                &format!(
                    "Processing function call: {} with arguments {:?}",
                    function_call.name, args
                ),
            );

            let mut args = args.clone();
            if func.accepts_context_variables {
                let serialized_context = serde_json::to_string(&context_variables)?;
                args.insert(CTX_VARS_NAME.to_string(), serialized_context);
            }

            // Await the asynchronous call.
            let raw_result = (func.function)(args).await?;
            let result = self.handle_function_result(raw_result, debug)?;
            response.messages.push(Message {
                role: ROLE_FUNCTION.to_string(),
                name: Some(function_call.name.clone()),
                content: Some(result.get_value()),
                function_call: None,
            });
            response
                .context_variables
                .extend(result.get_context_variables());
            if let Some(agent) = result.get_agent() {
                response.agent = Some(agent);
            }
        } else {
            debug_print(
                debug,
                &format!("Function {} not found.", function_call.name),
            );
            response.messages.push(Message {
                role: ROLE_ASSISTANT.to_string(),
                name: Some(function_call.name.clone()),
                content: Some(format!("Error: Function {} not found.", function_call.name)),
                function_call: None,
            });
        }
        Ok(response)
    }

    /// Handles the result of a function call.
    pub fn handle_function_result(
        &self,
        result: ResultType,
        debug: bool,
    ) -> SwarmResult<ResultType> {
        match result {
            ResultType::Value(_) | ResultType::Agent(_) => Ok(result),
            _ => {
                let error_message = format!(
                    "Failed to cast response to string: {:?}. Ensure agent functions return a string or ResultType.",
                    result
                );
                debug_print(debug, &error_message);
                Err(SwarmError::FunctionError(error_message))
            }
        }
    }

    /// Executes a single round of conversation with the agent.
    async fn single_execution(
        &self,
        agent: &Agent,
        history: &mut Vec<Message>,
        context_variables: &mut ContextVariables,
        model_override: Option<String>,
        stream: bool,
        debug: bool,
    ) -> SwarmResult<Response> {
        let completion = self
            .get_chat_completion(
                agent,
                &history.clone(),
                context_variables,
                model_override.clone(),
                stream,
                debug,
            )
            .await?;
        if completion.choices.is_empty() {
            return Err(SwarmError::ApiError(
                "No choices returned from the model".to_string(),
            ));
        }
        let choice = &completion.choices[0];
        let message = choice.message.clone();
        history.push(message.clone());

        if let Some(function_call) = &message.function_call {
            // Await the asynchronous function call handler.
            let func_response = self
                .handle_function_call(function_call, &agent.functions, context_variables, debug)
                .await?;
            history.extend(func_response.messages.clone());
            context_variables.extend(func_response.context_variables);
        }

        Ok(Response {
            messages: vec![message],
            agent: Some(agent.clone()),
            context_variables: context_variables.clone(),
        })
    }

    /// Executes a step based on the provided XML–defined step.
    async fn execute_step(
        &self,
        agent: &mut Agent,
        history: &mut Vec<Message>,
        context_variables: &mut ContextVariables,
        model_override: Option<String>,
        stream: bool,
        debug: bool,
        max_turns: usize,
        step_number: usize,
        step: &Step,
    ) -> SwarmResult<Response> {
        if step.prompt.trim().is_empty() {
            return Err(SwarmError::ValidationError(
                "Step prompt cannot be empty".to_string(),
            ));
        }
        if step.number == 0 {
            return Err(SwarmError::ValidationError(
                "Step number must be greater than 0".to_string(),
            ));
        }

        println!("Executing Step {}", step_number);

        if let Some(agent_name) = &step.agent {
            println!("Switching to agent: {}", agent_name);
            *agent = self.get_agent_by_name(agent_name)?;
        }

        match step.action.as_str() {
            "run_once" => {
                let step_message = Message {
                    role: "user".to_string(),
                    content: Some(step.prompt.clone()),
                    name: None,
                    function_call: None,
                };
                history.push(step_message);
                self.single_execution(
                    agent,
                    history,
                    context_variables,
                    model_override.clone(),
                    stream,
                    debug,
                )
                .await
            }
            "loop" => {
                let mut iteration_count = 0;
                let max_iterations = 10;
                loop {
                    iteration_count += 1;
                    let step_message = Message {
                        role: "user".to_string(),
                        content: Some(step.prompt.clone()),
                        name: None,
                        function_call: None,
                    };
                    history.push(step_message);
                    let response = self
                        .single_execution(
                            agent,
                            history,
                            context_variables,
                            model_override.clone(),
                            stream,
                            debug,
                        )
                        .await?;
                    if let Some(new_agent) = response.agent.clone() {
                        *agent = new_agent;
                    }
                    if context_variables.get("end_loop") == Some(&"true".to_string()) {
                        println!("Loop termination condition met.");
                        break;
                    }
                    if iteration_count >= max_iterations {
                        println!("Reached maximum loop iterations.");
                        break;
                    }
                    if history.len() >= max_turns {
                        println!("Max turns reached in loop, exiting.");
                        break;
                    }
                }
                Ok(Response {
                    messages: history.clone(),
                    agent: Some(agent.clone()),
                    context_variables,
                })
            }
            _ => {
                println!("Unknown action: {}", step.action);
                Err(SwarmError::ValidationError(format!(
                    "Unknown action: {}",
                    step.action
                )))
            }
        }
    }

    /// Executes a multi-turn conversation with the AI agent.
    pub async fn run(
        &self,
        mut agent: Agent,
        messages: Vec<Message>,
        mut context_variables: ContextVariables,
        model_override: Option<String>,
        stream: bool,
        debug: bool,
        max_turns: usize,
    ) -> SwarmResult<Response> {
        validate_api_request(&agent, &messages, &model_override, max_turns)?;

        if max_turns > self.config.max_loop_iterations as usize {
            return Err(SwarmError::ValidationError(format!(
                "max_turns ({}) exceeds configured max_loop_iterations ({})",
                max_turns, self.config.max_loop_iterations
            )));
        }

        let instructions = match &agent.instructions {
            Instructions::Text(text) => text.clone(),
            Instructions::Function(func) => func(context_variables.clone()),
        };

        let (instructions_without_xml, xml_steps) = extract_xml_steps(&instructions)?;

        let steps = if let Some(xml_content) = xml_steps {
            parse_steps_from_xml(&xml_content)?
        } else {
            Steps { steps: Vec::new() }
        };

        agent.instructions = Instructions::Text(instructions_without_xml);
        let mut history = messages.clone();

        if !steps.steps.is_empty() {
            for step in &steps.steps {
                let response = self
                    .execute_step(
                        &mut agent,
                        &mut history,
                        &mut context_variables,
                        model_override.clone(),
                        stream,
                        debug,
                        max_turns,
                        step.number,
                        step,
                    )
                    .await?;
                if let Some(new_agent) = response.agent {
                    agent = new_agent;
                }
            }
        } else {
            println!("No steps defined. Executing default behavior.");
            let response = self
                .single_execution(
                    &agent,
                    &mut history,
                    &mut context_variables,
                    model_override,
                    stream,
                    debug,
                )
                .await?;
            history.extend(response.messages);
            context_variables.extend(response.context_variables);
        }

        Ok(Response {
            messages: history,
            agent: Some(agent),
            context_variables,
        })
    }

    pub fn get_agent_by_name(&self, name: &str) -> SwarmResult<Agent> {
        self.agent_registry
            .get(name)
            .cloned()
            .ok_or_else(|| SwarmError::AgentNotFoundError(name.to_string()))
    }
}

impl SwarmConfig {
    pub fn validate(&self) -> SwarmResult<()> {
        if self.request_timeout == 0 {
            return Err(SwarmError::ValidationError(
                "request_timeout must be greater than 0".to_string(),
            ));
        }
        if self.connect_timeout == 0 {
            return Err(SwarmError::ValidationError(
                "connect_timeout must be greater than 0".to_string(),
            ));
        }
        if self.max_retries == 0 {
            return Err(SwarmError::ValidationError(
                "max_retries must be greater than 0".to_string(),
            ));
        }
        if self.valid_model_prefixes.is_empty() {
            return Err(SwarmError::ValidationError(
                "valid_model_prefixes cannot be empty".to_string(),
            ));
        }
        if self.request_timeout < MIN_REQUEST_TIMEOUT || self.request_timeout > MAX_REQUEST_TIMEOUT
        {
            return Err(SwarmError::ValidationError(format!(
                "request_timeout must be between {} and {} seconds",
                MIN_REQUEST_TIMEOUT, MAX_REQUEST_TIMEOUT
            )));
        }
        if self.loop_control.default_max_iterations == 0 {
            return Err(SwarmError::ValidationError(
                "default_max_iterations must be greater than 0".to_string(),
            ));
        }
        Ok(())
    }
}

impl Agent {
    pub fn validate(&self, config: &SwarmConfig) -> SwarmResult<()> {
        if self.name.trim().is_empty() {
            return Err(SwarmError::ValidationError(
                "Agent name cannot be empty".to_string(),
            ));
        }
        if self.model.trim().is_empty() {
            return Err(SwarmError::ValidationError(
                "Agent model cannot be empty".to_string(),
            ));
        }
        if !config
            .valid_model_prefixes
            .iter()
            .any(|prefix| self.model.starts_with(prefix))
        {
            return Err(SwarmError::ValidationError(format!(
                "Invalid model prefix. Model must start with one of: {:?}",
                config.valid_model_prefixes
            )));
        }
        match &self.instructions {
            Instructions::Text(text) if text.trim().is_empty() => {
                return Err(SwarmError::ValidationError(
                    "Agent instructions cannot be empty".to_string(),
                ));
            }
            Instructions::Function(_) => {} // Function instructions are validated at runtime.
            _ => {}
        }
        Ok(())
    }
}

```

