YART (Yet Another Rig Tool)
May 12, 2025 · View on GitHub
YART is a Rust library suite for creating tools with the rig::tool::Tool trait, providing a flexible procedural macro (#[rig_tool]) for generating tool implementations with JSON schema support. It is designed for the rig framework, enabling async tool definitions with optional context and arguments.
- Example Project: github.com/pupplecat/yart-example
Structure
YART is split into three crates to adhere to Rust’s proc-macro restrictions and provide a clean API:
yart-shared: Contains shared types (ToolError,ToolOutput) and utilities (derive_parameters) used by generated code and consumers.yart-macro: A proc-macro crate exporting the#[rig_tool]macro, which generatesrig::tool::Toolimplementations.yart: A wrapper crate that re-exports the#[rig_tool]macro fromyart_macroand types/functions fromyart_shared, offering a unified interface.
This structure mirrors conventions like serde/serde_derive, ensuring compatibility and modularity.
Features
- Flexible Macro:
#[rig_tool]supports 0-2 arguments (optional context, optional args).- Attributes:
description(required),name(optional, defaults to function name).
- Generated Code:
- Creates a struct implementing
rig::tool::Toolwithnew,name,definition, andcallmethods. - Generates JSON schemas for arguments using
schemars.
- Creates a struct implementing
- Async Support: Wraps async functions with
Resultreturns, handling errors viaToolError. - Unified API: Import everything via
yart(e.g.,use yart::*).
Installation
[dependencies]
yart = "0.1.1"
The yart crate depends on yart-shared and yart-macro, so you only need to include yart.
Usage
Define a tool using the #[rig_tool] macro, specifying a description and optional name. The macro generates a struct implementing rig::tool::Tool.
Example
use std::sync::Arc;
use yart::{ToolError, ToolOutput};
use serde::{Deserialize, Serialize};
use schemars::JsonSchema;
// Define argument type
#[derive(Deserialize, Serialize, JsonSchema)]
struct TestArgs {
input: String,
}
// Define output type
#[derive(Deserialize, Serialize)]
struct TestOutput {
result: String,
}
// Tool without context
#[yart::rig_tool(description = "Echoes input")]
async fn echo_tool(args: TestArgs) -> anyhow::Result<TestOutput, ToolError> {
Ok(TestOutput { result: args.input })
}
// Tool with context
#[derive(Clone)]
struct TestContext {
value: String,
}
#[yart::rig_tool(name = "context_tool", description = "Echoes input with context")]
async fn context_tool(
ctx: Arc<TestContext>,
args: TestArgs,
) -> anyhow::Result<TestOutput, ToolError> {
Ok(TestOutput {
result: format!("{}: {}", ctx.value, args.input),
})
}
#[tokio::main]
async fn main() {
// Use tool without context
let tool = EchoTool::new();
let args = TestArgs { input: "hello".to_string() };
let result = tool.call(args).await.unwrap();
let output: TestOutput = serde_json::from_value(result.result).unwrap();
println!("Output: {}", output.result); // Output: hello
// Use tool with context
let ctx = Arc::new(TestContext { value: "test".to_string() });
let tool = ContextTool::new(ctx);
let args = TestArgs { input: "world".to_string() };
let result = tool.call(args).await.unwrap();
let output: TestOutput = serde_json::from_value(result.result).unwrap();
println!("Output: {}", output.result); // Output: test: world
}
Project Structure
yart/
├── libs/
│ ├── yart/ # Wrapper crate
│ │ ├── src/lib.rs # Re-exports yart-macro and yart-shared
│ │ └── Cargo.toml
│ ├── yart-macro/ # Proc-macro crate
│ │ ├── src/lib.rs # Defines #[rig_tool] macro
│ │ └── Cargo.toml
│ └── yart-shared/ # Shared types and utilities
│ ├── src/lib.rs # Defines ToolError, ToolOutput, derive_parameters
│ └── Cargo.toml
├── README.md
└── Cargo.toml
Testing
Run tests for each crate:
# Test yart-shared
cd libs/yart-shared
cargo test
# Test yart-macro
cd libs/yart-macro
cargo test
# Test yart (integration tests)
cd libs/yart
cargo test
Limitations
- The
descriptionattribute is required; enforced at compile-time but tested manually due to proc-macro testing constraints. - Consider using
trybuildfor robust macro testing inyart-macro.
Contributing
Contributions are welcome! Please submit pull requests or open issues on the project repository.
License
MIT