ToolBuilder

Struct ToolBuilder 

Source
pub struct ToolBuilder { /* private fields */ }
Expand description

Builder for creating tools with a fluent API.

The ToolBuilder provides a convenient, readable way to construct tools using method chaining. It’s especially useful when building tools incrementally or when the schema structure is determined dynamically.

§Builder Pattern Benefits

  • Readability: Method chains read like natural language
  • Flexibility: Add parameters conditionally
  • Type safety: Catches errors at compile time
  • Discoverability: IDE autocomplete shows available options

§Workflow

  1. Create builder with tool() or ToolBuilder::new()
  2. Add parameters with .param()
  3. Optionally set schema with .schema()
  4. Finalize with .build() and provide handler

§Examples

See the tool() function for detailed examples.

§Note on Schema Mutation

If you call .schema() after .param(), the parameters will be replaced by the new schema. Similarly, calling .param() after .schema() will reset a non-object schema to an empty object before adding the parameter. Generally, use either .schema() or .param(), not both.

Implementations§

Source§

impl ToolBuilder

Source

pub fn new(name: impl Into<String>, description: impl Into<String>) -> Self

Start building a new tool with a name and description.

This creates a builder with an empty schema. You can then add parameters using .param() or set a complete schema with .schema().

§Parameters
  • name: Tool identifier (converted to String via Into trait)
  • description: Human-readable explanation of what the tool does
§Examples
let builder = ToolBuilder::new("search", "Search for information");
// builder.param(...).build(...)

Typically you’ll use the tool() convenience function instead of calling this directly.

Source

pub fn schema(self, schema: Value) -> Self

Set the complete input schema.

This replaces any schema or parameters set previously. Use this when you have a pre-built schema object (especially useful for complex schemas with nested structures).

§Schema Format

Accepts any of the formats supported by Tool::new:

  • Simple type notation: {"param": "string"}
  • Extended schema: {"param": {"type": "string", "description": "..."}}
  • Full JSON Schema: {"type": "object", "properties": {...}, "required": [...]}
§Warning

This overwrites any parameters added via .param(). Generally, choose one approach: either use .param() for simple cases or .schema() for complex cases, but not both.

§Examples
let my_tool = tool("api_call", "Make an API call")
    .schema(json!({
        "endpoint": {
            "type": "string",
            "description": "API endpoint URL",
            "pattern": "^https://"
        },
        "method": {
            "type": "string",
            "enum": ["GET", "POST", "PUT", "DELETE"]
        }
    }))
    .build(|_| async { Ok(json!({})) });
Source

pub fn param(self, name: &str, type_str: &str) -> Self

Add a single parameter to the schema.

This is a convenience method for building schemas incrementally. Each call adds one parameter with a simple type string.

§Parameters
  • name: Parameter name (will be required in tool calls)
  • type_str: Type string like “string”, “number”, “boolean”, etc. Supported types: “string”, “number”, “integer”, “boolean”, “array”, “object”.
§Behavior
  • If the current schema is not an object (e.g., you called .schema() with a non-object value), it will be reset to an empty object first.
  • All parameters added via .param() are marked as required.
  • For optional parameters, use .schema() with extended property format.
§Method Chaining

This method consumes self and returns it, enabling method chaining:

let my_tool = tool("calculate", "Perform calculation")
    .param("operation", "string")
    .param("x", "number")
    .param("y", "number")
    .build(|_| async { Ok(json!({})) });
§Examples
// Add multiple parameters
let weather_tool = tool("get_weather", "Get weather for a location")
    .param("location", "string")
    .param("units", "string")
    .build(|args| async move {
        // Implementation
        Ok(json!({"temp": 72}))
    });
Source

pub fn build<F, Fut>(self, handler: F) -> Tool
where F: Fn(Value) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Value>> + Send + 'static,

Build the final Tool with a handler function.

This consumes the builder and produces a Tool ready for use. The handler function defines what happens when the tool is called.

§Handler Requirements

The handler must be:

  • An async function or closure
  • Accept a single Value argument (the tool’s input parameters)
  • Return a Future<Output = Result<Value>>
  • Implement Send + Sync + 'static for thread safety
§Generic Parameters
  • F: The handler function type (inferred from the closure/function you provide)
  • Fut: The future type returned by the handler (inferred automatically)
§Examples
§Simple Handler
let my_tool = tool("echo", "Echo back the input")
    .param("message", "string")
    .build(|args| async move {
        Ok(args) // Echo arguments back
    });
§Handler with External State
let counter = Arc::new(std::sync::atomic::AtomicU32::new(0));

let my_tool = tool("increment", "Increment a counter")
    .build(move |_args| {
        let counter = counter.clone();
        async move {
            let val = counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
            Ok(json!({"count": val + 1}))
        }
    });
§Handler with Error Handling
let my_tool = tool("divide", "Divide two numbers")
    .param("a", "number")
    .param("b", "number")
    .build(|args| async move {
        let a = args["a"].as_f64().ok_or_else(|| Error::tool("Invalid 'a' parameter"))?;
        let b = args["b"].as_f64().ok_or_else(|| Error::tool("Invalid 'b' parameter"))?;

        if b == 0.0 {
            return Err(Error::tool("Division by zero"));
        }

        Ok(json!({"result": a / b}))
    });

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more