Skip to main content

FunctionTool

Struct FunctionTool 

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

A concrete, locally executable tool built from a closure.

This is the Rust analogue of upstream’s FunctionTool / the @tool decorator (formerly AIFunction / @ai_function).

Implementations§

Source§

impl FunctionTool

Source

pub fn new<F, Fut>( name: impl Into<String>, description: impl Into<String>, parameters: Value, func: F, ) -> Self
where F: Fn(Value) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Value>> + Send + 'static,

Create a function tool from a hand-written JSON Schema.

  • parameters is the JSON Schema for the arguments object.
  • func receives the parsed JSON arguments and returns a JSON result.

Prefer FunctionTool::typed when the arguments can be expressed as a #[derive(Deserialize, JsonSchema)] struct.

Source

pub fn typed<Args, Ret, F, Fut>( name: impl Into<String>, description: impl Into<String>, f: F, ) -> Self
where Args: DeserializeOwned + JsonSchema + Send + 'static, Ret: Serialize, F: Fn(Args) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Ret>> + Send + 'static,

Create a function tool whose parameters schema and argument deserialization are derived from a Rust type, instead of a hand-written serde_json::Value schema.

Args must implement schemars::JsonSchema (to derive the parameters schema) and serde::de::DeserializeOwned (to parse the model-supplied arguments); Ret need only implement serde::Serialize – return serde_json::Value directly (as in the example below), or any other serializable type.

§Parameters schema

The schema is generated once, at construction, via schemarsSchemaGenerator (the machinery behind its schema_for! macro, which cannot itself target a type parameter), then lightly post-processed for OpenAI-style function parameters: the top-level $schema and title keys are stripped. For a “simple” struct (only primitive/string/number/bool/Vec/Option fields) this leaves exactly {"type": "object", "properties": {...}, "required": [...]} – a field is listed in required unless it is an Option<_> or carries #[serde(default)]. Nested structs and enums keep schemars’ own representation: a top-level definitions map with $refs into it (schemars 0.8’s convention for referenceable types). This is not inlined – every provider converter in this workspace forwards ToolDefinition::parameters to the wire unmodified, so a $ref/definitions pair round-trips exactly like any other JSON-Schema keyword this crate doesn’t otherwise interpret.

§Argument errors

If the model-supplied JSON arguments don’t deserialize into Args (e.g. a required field is missing or mistyped), Tool::invoke returns Err(Error::Tool) rather than panicking or silently substituting a default – the same Result-propagation shape used for every other tool-execution failure (a closure error from FunctionTool::new, an FunctionTool::max_invocations limit, …), which the function-invocation loop turns into an error crate::types::FunctionResultContent exactly as it would for any of those.

§Example
use agent_framework_core::tools::FunctionTool;

#[derive(serde::Deserialize, schemars::JsonSchema)]
struct WeatherArgs {
    city: String,
    #[serde(default)]
    units: Option<String>,
}

let _tool = FunctionTool::typed(
    "get_weather",
    "Get the weather.",
    |args: WeatherArgs| async move {
        Ok(serde_json::json!({ "city": args.city, "temp": 21 }))
    },
);
Source

pub fn with_approval_mode(self, mode: ApprovalMode) -> Self

Builder: set the human-in-the-loop approval mode (default ApprovalMode::NeverRequire). Carried through to the ToolDefinition produced by FunctionTool::into_definition.

Source

pub fn max_invocations(self, max: usize) -> Self

Builder: cap the number of times this function may be invoked.

Once FunctionTool::invocation_count reaches max, further calls to Tool::invoke return Err(Error::Tool) instead of running the function again – mirrors Python’s AIFunction(max_invocations=...) (_tools.py:599-600, 687-690). None (the default) means no limit.

Unlike Python, which raises ValueError at construction for a value less than 1, a value of 0 is accepted here: it simply means the limit is already reached, so every invocation errors immediately (the same terminal state Python’s validation exists to prevent constructing in the first place).

The counter is shared by every Clone of this FunctionTool (see the note on FunctionTool’s fields), not reset per clone.

Source

pub fn max_invocation_exceptions(self, max: usize) -> Self

Builder: cap the number of invocation failures this function tolerates.

Every Tool::invoke call that returns Err – whether from argument deserialization (see FunctionTool::typed), the wrapped closure itself, or result serialization – increments FunctionTool::invocation_exception_count. Once that count reaches max, further calls return Err(Error::Tool) immediately without re-attempting the function. None (the default) means no limit. Mirrors Python’s AIFunction(max_invocation_exceptions=...) (_tools.py:601-602, 691-698); see FunctionTool::max_invocations for how the 0 case differs from Python’s constructor-time validation.

Source

pub fn invocation_count(&self) -> usize

The number of times Tool::invoke has run the wrapped function (i.e. got past any FunctionTool::max_invocations/ FunctionTool::max_invocation_exceptions gate). Mirrors Python’s public invocation_count attribute.

Source

pub fn invocation_exception_count(&self) -> usize

The number of those invocations that returned Err. Mirrors Python’s public invocation_exception_count attribute.

Source

pub fn into_definition(self) -> ToolDefinition

Convert into a ToolDefinition for use in chat options.

Trait Implementations§

Source§

impl Clone for FunctionTool

Source§

fn clone(&self) -> FunctionTool

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Tool for FunctionTool

Source§

fn invoke<'life0, 'async_trait>( &'life0 self, arguments: Value, ) -> Pin<Box<dyn Future<Output = Result<Value>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Run the wrapped function, first enforcing FunctionTool::max_invocations and FunctionTool::max_invocation_exceptions (mirrors Python’s AIFunction.__call__, _tools.py:683-707): a limit that has already been reached errors before the function runs and before FunctionTool::invocation_count is bumped again, so calling an already-exhausted function any number of further times does not drift its counters.

The invocation slot is reserved atomically (fetch_update), because the function-invocation loop executes a model’s parallel calls to the same tool concurrently — a plain check-then-increment would let two racing calls both slip under max_invocations.

Source§

fn name(&self) -> &str

The tool name exposed to the model.
Source§

fn description(&self) -> &str

A human/model-readable description.
Source§

fn parameters_schema(&self) -> Value

The JSON Schema describing the tool’s parameters.
Source§

fn invoke_in_context<'life0, 'life1, 'async_trait>( &'life0 self, arguments: Value, _ctx: &'life1 FunctionInvocationContext, ) -> Pin<Box<dyn Future<Output = Result<Value>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Execute the tool with access to the surrounding FunctionInvocationContext (the agent session, middleware metadata, …). Read more

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = !

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<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