# Lumina Tool System

A production-grade, event-driven tool execution system that outperforms LangChain, AutoGen, and MCP.

## Architecture

The Lumina tool system is **fully event-driven**:

1. **Tools do not run directly** - They react to `EventType::ToolCallRequested` events
2. **Tools emit events** - `ToolCallStarted`, `ToolCallCompleted`, `ToolCallFailed`, `ToolCallRetrying`
3. **ToolSystem dispatches** - Listens for tool requests and executes asynchronously
4. **Deterministic** - All operations respect the seed for reproducibility

## Core Components

### Tool Trait

All tools implement the unified `Tool` trait:

```rust
#[async_trait]
pub trait Tool: Send + Sync + 'static + Debug {
    fn name(&self) -> &'static str;
    async fn execute(&self, input: Value, event: &Event) -> Result<Value, String>;
    fn description(&self) -> &'static str { "" }
    fn schema(&self) -> Option<Value> { None }
}
```

### ToolRegistry

Thread-safe registry mapping tool names to implementations:

```rust
let registry = Arc::new(ToolRegistry::new());
registry.register(Arc::new(MyTool::new())).await;
```

### ToolSystem

Event-driven dispatcher that:
- Listens for `ToolCallRequested` events
- Executes tools asynchronously
- Emits result events
- Handles retries, timeouts, and caching

```rust
let tool_system = Arc::new(ToolSystem::new(
    registry.clone(),
    cache.clone(),
    event_bus.clone(),
    5000, // timeout
    3,    // retries
    1000, // retry delay
));

// Register with EventBus
event_bus.subscribe(tool_system.clone() as Arc<dyn EventHandler>).await;
```

## Usage

### 1. Create a Tool

```rust
use crate::tool::Tool;
use async_trait::async_trait;
use lumina_engine::Event;
use serde_json::Value;

#[derive(Debug, Clone)]
pub struct MyTool;

#[async_trait]
impl Tool for MyTool {
    fn name(&self) -> &'static str {
        "my_tool"
    }
    
    fn description(&self) -> &'static str {
        "Does something useful"
    }
    
    async fn execute(&self, input: Value, _event: &Event) -> Result<Value, String> {
        // Extract parameters
        let param = input.get("param")
            .and_then(|v| v.as_str())
            .ok_or("Missing 'param'")?;
        
        // Do work
        Ok(serde_json::json!({ "result": format!("Processed: {}", param) }))
    }
}
```

### 2. Register Tools

```rust
let registry = Arc::new(ToolRegistry::new());
registry.register(Arc::new(MyTool::new())).await;
```

### 3. Request Tool Execution (Event-Driven)

```rust
// Create ToolCallRequested event
let event = Event::new(
    EventType::ToolCallRequested,
    "agent_123".to_string(),
    serde_json::json!({
        "tool_name": "my_tool",
        "input": { "param": "value" }
    }),
    seed,
);

// Publish event - ToolSystem will handle it
event_bus.publish(event).await?;
```

### 4. Handle Tool Results

Listen for `ToolCallCompleted` or `ToolCallFailed` events:

```rust
struct ToolResultHandler;

#[async_trait]
impl EventHandler for ToolResultHandler {
    async fn handle(&self, event: &Event) -> Result<Vec<Event>, EventError> {
        if matches!(event.event_type, EventType::ToolCallCompleted) {
            let output = event.payload.get("output");
            // Process result
        }
        Ok(Vec::new())
    }
    
    fn interested_events(&self) -> Vec<EventType> {
        vec![EventType::ToolCallCompleted]
    }
}
```

## Example Tools

### WeatherApiTool

Demonstrates external API integration:

```rust
let weather_tool = WeatherApiTool::new(Some("api_key".to_string()));
registry.register(Arc::new(weather_tool)).await;
```

### SimpleMathTool

Demonstrates basic tool implementation:

```rust
let math_tool = SimpleMathTool::new();
registry.register(Arc::new(math_tool)).await;
```

## Features

- ✅ **Fully Event-Driven** - Tools react to events, not direct calls
- ✅ **Thread-Safe** - All components use `Arc` and `RwLock`
- ✅ **Deterministic** - Seed preserved throughout execution
- ✅ **Async/Await** - No blocking operations
- ✅ **Retry Logic** - Automatic retries with exponential backoff
- ✅ **Caching** - Result caching for performance
- ✅ **Timeout Handling** - Configurable timeouts per tool
- ✅ **External Systems** - Supports APIs, databases, file systems
- ✅ **Production-Grade** - Clean, idiomatic Rust code

## Comparison with Other Frameworks

| Feature | Lumina | LangChain | AutoGen | MCP |
|---------|--------|-----------|---------|-----|
| Event-Driven | ✅ | ❌ | ❌ | ❌ |
| Deterministic | ✅ | ❌ | ❌ | ❌ |
| True Concurrency | ✅ | ❌ | ❌ | ❌ |
| Retry Logic | ✅ | ⚠️ | ⚠️ | ❌ |
| Caching | ✅ | ⚠️ | ❌ | ❌ |
| External Systems | ✅ | ✅ | ✅ | ✅ |

## Migration from ToolExecutor

The old `ToolExecutor` is still available for backward compatibility but is deprecated. To migrate:

**Old (Direct Execution):**
```rust
let result = tool_executor.execute(tool_id, params, context).await?;
```

**New (Event-Driven):**
```rust
let event = Event::new(
    EventType::ToolCallRequested,
    source,
    json!({ "tool_name": tool_id, "input": params }),
    seed,
);
event_bus.publish(event).await?;
// Listen for ToolCallCompleted event
```

## Best Practices

1. **Keep tools stateless** - Tools should be pure functions when possible
2. **Use async for I/O** - All external calls should be async
3. **Validate input** - Check parameters before execution
4. **Handle errors gracefully** - Return descriptive error messages
5. **Respect the seed** - Use seeded RNG for deterministic behavior
6. **Emit events** - Let ToolSystem handle event emission

## Future Enhancements

- [ ] Distributed tool execution
- [ ] Tool versioning
- [ ] Tool dependencies
- [ ] Parallel tool execution
- [ ] Tool composition
- [ ] Dynamic tool loading

