| Crates.io | tool_calling |
| lib.rs | tool_calling |
| version | 0.1.0 |
| created_at | 2025-04-28 01:47:04.897883+00 |
| updated_at | 2025-04-28 01:47:04.897883+00 |
| description | Don't know yet |
| homepage | |
| repository | https://github.com/ljt019/tool_calling/ |
| max_upload_size | |
| id | 1651652 |
| size | 100,900 |
A procedural-macro framework for defining, registering, and invoking Rust functions as tools with automatic JSON Schema validation and error handling.
#[tool] to register them automatically.Option<T> for optional arguments; #[default = ...] for defaults.&T) to ensure tools use owned types like String and Vec<T>.Add this to your Cargo.toml:
[dependencies]
tool_calling = "0.1"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
Or use cargo:
cargo add tool_calling
cargo add tokio --features macros,rt-multi-thread
Note: The
tokiodependency is only required if you are calling tools asynchronously (most CLI or server contexts).
use tool_calling::{tool, ToolHandler};
use serde_json::json;
#[tool]
/// Get user info from database
fn get_user_info(user_id: u32) -> String {
match user_id {
1 => "User 1 info...".to_string(),
_ => "User not found".to_string(),
}
}
#[tokio::main]
async fn main() {
// Initialize handler
let handler = ToolHandler::default();
// Call the tool with a JSON payload
let payload = json!({
"type": "function",
"function": {
"name": "get_user_info",
"arguments": { "user_id": 1 }
}
});
let result = handler.call_tool(&payload).await.unwrap();
println!("Result: {}", result);
}
Use the #[tool] attribute to mark any free function as a tool. The macro will:
///) as the tool's description.u32/i*/usize → integer, f32/f64 → number, bool → boolean, String → string).Option<T> parameters as optional fields in the schema (allowing null).&T).use tool_calling::tool;
#[tool]
/// Get user info from database
fn get_user_info(user_id: u32) -> String {
match user_id {
1 => "User 1 info...".to_string(),
_ => "User not found".to_string(),
}
}
Optionally provide a default literal for Option<T> parameters:
use tool_calling::{tool, default};
#[tool]
/// Greet a user with optional punctuation
fn greet(
name: String,
#[default = "?" ] punctuation: Option<String>
) -> String {
let punct = punctuation.unwrap_or_else(|| "!".to_string());
format!("Hello, {}{}", name, punct)
}
use tool_calling::ToolHandler;
#[tokio::main]
async fn main() {
let handler = ToolHandler::default();
// ...
}
// List a single tool
if let Some(tool) = handler.get_tool("get_user_info") {
println!("Description: {}", tool.description);
println!("Schema: {}", serde_json::to_string_pretty(&tool.parameter_schema).unwrap());
}
// List all tools for LLM function-calling
println!("{}", serde_json::to_string_pretty(&handler.all_tools_schema()).unwrap());
use serde_json::json;
let payload = json!({
"type": "function",
"function": {
"name": "get_user_info",
"arguments": { "user_id": 1 }
}
});
match handler.call_tool(&payload).await {
Ok(res) => println!("Result: {}", res),
Err(e) => eprintln!("Error: {}", e),
}
let result = handler
.call_with_args("get_user_info", &["1".to_string()])
.await
.unwrap();
println!("Direct call result: {}", result);
Explore the examples directory for more usage scenarios:
examples/simple_example.rs — Basic sync tool.examples/async_example.rs — Async tool with tokio.examples/optional_arguments_example.rs — Tool with optional parameters and defaults.Run the full test suite:
cargo test
#[tool] — Marks a function as a tool, generating registration code and JSON Schema.#[default = <literal>] — Attach to Option<T> parameters for default values.ToolHandlerToolHandler::default() — Initializes and registers all annotated tools.get_tool(name: &str) -> Option<&Tool> — Retrieve metadata for a single tool.all_tools_schema() -> serde_json::Value — A JSON array of all tools (for LLM introspection).call_tool(input: &serde_json::Value) -> Result<String, ToolError> — Parse a function-call payload and execute.call_with_args(name: &str, args: &[String]) -> Result<String, ToolError> — Directly invoke a tool by name.ToolError variants:
NotFound(String) — Tool name not registered.BadArgs(String) — Arguments missing or failed JSON Schema validation.Execution(String) — Underlying function panicked or returned an execution error.Contributions, issues, and feature requests are welcome! Please open a GitHub issue or submit a pull request.
This project is licensed under either of:
at your option.