Skip to main content

ferrin_spec/language_model/
tool.rs

1//! Tool definitions passed to language models.
2
3use serde::Deserialize;
4use serde::Serialize;
5
6use crate::json::JsonObject;
7use crate::json::JsonValue;
8use crate::shared::ProviderOptions;
9use crate::shared::ToolName;
10
11/// A tool made available to the model.
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13#[serde(tag = "type", rename_all = "lowercase")]
14#[non_exhaustive]
15pub enum ToolDefinition {
16    /// A function tool executed by the application (or by the provider when
17    /// it reports `provider_executed`).
18    Function {
19        /// Tool name.
20        name: ToolName,
21        /// Description shown to the model.
22        #[serde(default, skip_serializing_if = "Option::is_none")]
23        description: Option<String>,
24        /// JSON Schema (draft-07) of the input.
25        input_schema: JsonValue,
26        /// Whether the provider should enforce the schema strictly.
27        #[serde(default, skip_serializing_if = "Option::is_none")]
28        strict: Option<bool>,
29        /// Example inputs.
30        #[serde(default, skip_serializing_if = "Vec::is_empty")]
31        input_examples: Vec<JsonObject>,
32        /// Provider-specific options for this tool.
33        #[serde(default, skip_serializing_if = "Option::is_none")]
34        provider_options: Option<ProviderOptions>,
35    },
36    /// A tool defined and executed by the provider (web search, code
37    /// interpreter, ...).
38    Provider {
39        /// Tool id in `<provider>.<tool>` form.
40        id: String,
41        /// Name under which the tool appears in results.
42        name: ToolName,
43        /// Provider-specific arguments.
44        #[serde(default)]
45        args: JsonObject,
46    },
47}
48
49impl ToolDefinition {
50    /// Creates a function tool with a schema and optional description.
51    #[must_use]
52    pub fn function(
53        name: impl Into<ToolName>,
54        description: Option<String>,
55        input_schema: JsonValue,
56    ) -> Self {
57        Self::Function {
58            name: name.into(),
59            description,
60            input_schema,
61            strict: None,
62            input_examples: Vec::new(),
63            provider_options: None,
64        }
65    }
66
67    /// Creates a provider tool.
68    #[must_use]
69    pub fn provider(id: impl Into<String>, name: impl Into<ToolName>, args: JsonObject) -> Self {
70        Self::Provider {
71            id: id.into(),
72            name: name.into(),
73            args,
74        }
75    }
76
77    /// Returns the tool name.
78    #[must_use]
79    pub fn name(&self) -> &ToolName {
80        match self {
81            Self::Function { name, .. } | Self::Provider { name, .. } => name,
82        }
83    }
84
85    /// Returns `true` for [`ToolDefinition::Provider`].
86    #[must_use]
87    pub fn is_provider_tool(&self) -> bool {
88        matches!(self, Self::Provider { .. })
89    }
90}