limit-agent 0.0.28

Agent runtime for AI applications with tool registry, parallel execution, and Docker sandbox support.
Documentation

limit-agent

Crates.io Docs.rs License: MIT

Agent runtime for AI applications with tool registry and Docker sandbox.

Build autonomous AI agents that can execute tools, run code in isolated containers, and maintain state across conversations.

Part of the Limit ecosystem.

Why This Exists

Building AI agents requires a flexible tool execution system that's both powerful and safe. limit-agent provides a production-ready runtime with Docker sandboxing, parallel execution, and persistent state—so you can focus on your agent's logic, not infrastructure.

Features

  • Tool Registry: Define, register, and execute tools dynamically with async/await
  • Docker Sandbox: Isolated execution environment for untrusted code
  • Parallel Execution: Run multiple tools concurrently for better performance
  • Event-driven: Subscribe to agent lifecycle events for logging and monitoring
  • State Management: Persist and restore agent state across sessions
  • LLM Integration: Works seamlessly with limit-llm

Installation

Add to your Cargo.toml:

[dependencies]
limit-agent = "0.0.27"

Requirements: Rust 1.70+, tokio runtime, Docker (optional, for sandbox)

Quick Start

Define a Custom Tool

use async_trait::async_trait;
use limit_agent::{Tool, AgentError};
use serde_json::{json, Value};

struct WeatherTool;

#[async_trait]
impl Tool for WeatherTool {
    fn name(&self) -> &str {
        "get_weather"
    }
    
    async fn execute(&self, args: Value) -> Result<Value, AgentError> {
        let location = args["location"].as_str().unwrap_or("Unknown");
        // Fetch weather data from API...
        Ok(json!({
            "location": location,
            "temp": 22,
            "condition": "sunny"
        }))
    }
}

Register and Execute

use limit_agent::ToolRegistry;
# use async_trait::async_trait;
# use limit_agent::{Tool, AgentError};
# use serde_json::{json, Value};
# struct WeatherTool;
# #[async_trait]
# impl Tool for WeatherTool {
#     fn name(&self) -> &str { "get_weather" }
#     async fn execute(&self, args: Value) -> Result<Value, AgentError> {
#         Ok(json!({"temp": 22}))
#     }
# }

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut registry = ToolRegistry::new();
    
    // Register tools
    registry.register(WeatherTool);
    
    // Execute tool by name
    let result = registry
        .execute("get_weather", json!({ "location": "São Paulo" }))
        .await?;
    
    println!("Weather: {:?}", result);
    
    Ok(())
}

Parallel Execution

Execute multiple tools concurrently for better performance:

# use limit_agent::ToolRegistry;
# use serde_json::json;
# #[tokio::main]
# async fn main() -> Result<(), Box<dyn std::error::Error>> {
let registry = ToolRegistry::new();
// ... register tools ...

// Execute multiple tools in parallel
let results = registry.execute_all(vec![
    ("get_weather", json!({ "location": "Tokyo" })),
    ("get_weather", json!({ "location": "London" })),
    ("read_file", json!({ "path": "/tmp/data.txt" })),
]).await?;

for result in results {
    println!("{:?}", result);
}
# Ok(())
# }

Docker Sandbox

Run untrusted code in isolated Docker containers:

use limit_agent::sandbox::{DockerSandbox, SandboxConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let sandbox = DockerSandbox::new(SandboxConfig {
        image: "python:3.11-slim".to_string(),
        memory_mb: 256,
        timeout_secs: 30,
        network_disabled: true,
    })?;
    
    // Execute code safely in container
    let output = sandbox.run_code(r#"
        print("Hello from sandbox!")
        x = 2 + 2
        print(f"Result: {x}")
    "#).await?;
    
    println!("{}", output.stdout);
    
    Ok(())
}

Sandbox Security Features

Feature Description
Network isolation Container has no network access
Memory limit Configurable memory ceiling (default: 256MB)
Timeout Execution time limit (default: 30s)
Read-only mount Project directory mounted read-only
Non-root user Container runs as unprivileged user

Event System

Subscribe to agent lifecycle events for logging, monitoring, or debugging:

use limit_agent::events::{EventBus, Event};

let events = EventBus::new();

events.subscribe(|event| {
    match event {
        Event::ToolStarted { name, args } => {
            println!("Tool {} started with {:?}", name, args);
        }
        Event::ToolCompleted { name, result, duration } => {
            println!("Tool {} completed in {:?}", name, duration);
        }
        Event::Error { tool, message } => {
            eprintln!("Error in {}: {}", tool, message);
        }
        _ => {}
    }
});

State Management

Persist and restore agent state across sessions:

use limit_agent::state::StateManager;

let state = StateManager::new("~/.limit/agent-state/")?;

// Save current state
state.save("session-123", &agent_state)?;

// Restore state later
let restored = state.load("session-123")?;

Core Types

Type Description
Tool Trait for defining executable tools
ToolRegistry Registry for managing and executing tools
DockerSandbox Isolated execution environment
StateManager Persist/restore agent state
EventBus Event subscription system

Built-in Tools

  • EchoTool — Simple echo for testing the tool pipeline

API Reference

See docs.rs/limit-agent for full API documentation.

Examples

# Run examples
cargo run --example basic
cargo run --example parallel
cargo run --example sandbox

License

MIT © Mário Idival