saorsa-agent 0.1.0

AI coding agent runtime with tool execution
Documentation

saorsa-agent

Agent runtime for the Saorsa AI framework, providing a complete environment for AI agents to execute tools and interact with the system.

Overview

The saorsa-agent crate implements the core agent loop that enables AI models to:

  • Execute tools in a controlled environment
  • Manage tool sessions and state
  • Handle tool execution errors and recoveries
  • Provide a unified interface for multiple LLM providers

Features

Agent Core

  • Tool Registry: Manages available tools and their schemas
  • Session Management: Maintains context across tool calls
  • Error Recovery: Handles tool failures gracefully
  • Streaming Support: Processes streaming responses from LLM providers

Tool Suite

The agent comes with a comprehensive suite of built-in tools:

File Operations Tools

Read Tool (read)

Read file contents with optional line range filtering.

Usage:

{
  "file_path": "/path/to/file.txt"
}

With line range:

{
  "file_path": "/path/to/file.txt",
  "line_range": "10-20"
}

Examples:

  • Read entire file: {"file_path": "src/main.rs"}
  • Read lines 5-10: {"file_path": "src/main.rs", "line_range": "5-10"}
  • Read from line 20 onwards: {"file_path": "src/main.rs", "line_range": "20-"}
Write Tool (write)

Write content to files with automatic directory creation.

Usage:

{
  "file_path": "/path/to/file.txt",
  "content": "File content here"
}
Edit Tool (edit)

Perform surgical text replacements in files.

Usage:

{
  "file_path": "/path/to/file.txt",
  "old_text": "old text",
  "new_text": "new text",
  "replace_all": false
}
Grep Tool (grep)

Search file contents using regex patterns.

Usage:

{
  "pattern": "fn main",
  "path": "/path/to/search",
  "case_insensitive": false
}
Find Tool (find)

Locate files by name patterns.

Usage:

{
  "pattern": "*.rs",
  "path": "/path/to/search"
}
Ls Tool (ls)

List directory contents with metadata.

Usage:

{
  "path": "/path/to/directory",
  "recursive": false
}

System Operations Tools

Bash Tool (bash)

Execute bash commands in a controlled environment.

Usage:

{
  "command": "echo 'Hello, World!'"
}

With working directory:

{
  "command": "ls -la",
  "working_directory": "/tmp"
}

With timeout:

{
  "command": "sleep 2",
  "timeout_ms": 1000
}

Quick Start

Basic Agent Usage

use saorsa_agent::{Agent, ToolRegistry};
use saorsa_ai::AnthropicProvider;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create an agent
    let agent = Agent::new();
    
    // Add your LLM provider
    let anthropic = AnthropicProvider::new()?;
    agent.add_provider("anthropic", Box::new(anthropic));
    
    // Start an agent session
    let mut session = agent.start_session(
        "You are a helpful assistant that can use tools.",
        "anthropic",
    )?;
    
    // Process user messages
    let response = session.process_message(
        "List the files in the current directory",
    ).await?;
    
    println!("Response: {}", response);
    
    Ok(())
}

Using Specific Tools

use saorsa_agent::tools::{ReadTool, BashTool};

// Read a file
let read_tool = ReadTool;
let result = read_tool.execute(
    &serde_json::json!({
        "file_path": "Cargo.toml"
    }),
    std::env::current_dir()?,
    None,
)?;

println!("File content: {}", result);

// Execute a bash command
let bash_tool = BashTool;
let result = bash_tool.execute(
    "ls -la src/",
    std::env::current_dir()?,
    None,
)?;

println!("Command output: {}", result);

Agent Configuration

Tool Registry

The agent maintains a registry of available tools:

use saorsa_agent::Agent;

let agent = Agent::new();
let registry = agent.tool_registry();

// List all available tools
for name in registry.tool_names() {
    println!("Tool: {}", name);
}

// Get a specific tool
if let Some(tool) = registry.get_tool("read") {
    println!("Tool schema: {}", tool.schema());
}

Custom Tools

You can add custom tools to the registry:

use saorsa_agent::{Tool, ToolRegistry};

struct CustomTool;

impl Tool for CustomTool {
    fn name(&self) -> &'static str {
        "custom"
    }
    
    fn description(&self) -> &'static str {
        "A custom tool implementation"
    }
    
    fn schema(&self) -> &str {
        r#"
        {
          "type": "object",
          "properties": {
            "input": {"type": "string"}
          }
        }
        "#
    }
    
    fn execute(&self, input: &serde_json::Value, _context: ToolContext) -> Result<String, ToolError> {
        // Your tool implementation here
        Ok("Custom tool result".to_string())
    }
}

// Add to registry
let mut registry = ToolRegistry::new();
registry.register_tool(Box::new(CustomTool));

Error Handling

All tool operations return a Result:

use saorsa_agent::ToolError;

match read_tool.execute(input, context, timeout) {
    Ok(output) => println!("Success: {}", output),
    Err(ToolError::FileNotFound(path)) => eprintln!("File not found: {}", path),
    Err(ToolError::PermissionDenied(path)) => eprintln!("Permission denied: {}", path),
    Err(e) => eprintln!("Error: {}", e),
}

Security Considerations

  • File Operations: Restricted to the working directory tree
  • Command Execution: Runs in a sandboxed environment with timeout limits
  • Input Validation: All tool inputs are validated against JSON schema
  • Logging: All tool executions are logged for auditability

Development

Running Tests

cargo test --all-features

Integration Tests

Run the tool suite integration tests:

cargo test tool_integration -- --nocapture

License

This project is licensed under either of:

at your option.