llm_wire/tool

Declares the tools a model may call and checks the calls it makes.

Declare a tool from a Blueprint codec written in your code, or from a JSON Schema received at runtime, such as an MCP inputSchema:

import llm_wire
import llm_wire/tool

let weather = tool.new("get_weather", "Current weather", weather_codec)
let request =
  llm_wire.request("gpt-5", [llm_wire.user("Weather in Paris?")])
  |> llm_wire.with_tools([weather])

new is for definitions in source code and panics, naming the tool, on a definition bug such as an invalid name or a codec without a schema. from_contract and from_json_schema take runtime data and return a typed ToolError instead.

A returned call is admitted against its declaration before the caller sees it. By default an unknown tool or invalid arguments fail the response; with llm_wire.with_tool_call_checks(config, ReportInvalidToolCalls) every call is returned and each failing one is listed as a ToolCallIssue in llm_wire.NeedsTools. Answer such a call with describe_issue(issue) as its result. decode_arguments turns a call’s arguments into your value.

Types

Why a tool name falls outside ^[a-zA-Z0-9_-]{1,64}$, the rule every built-in provider accepts.

pub type NameProblem {
  EmptyName
  InvalidCharacter(character: String)
  NameTooLong(length: Int)
}

Constructors

  • EmptyName
  • InvalidCharacter(character: String)

    The first character outside ASCII letters, digits, _ and -.

  • NameTooLong(length: Int)

    The name has more than 64 characters.

A tool declaration: a name, a description and an input schema.

pub type Tool =
  @internal Tool

How a response treats a call to an unknown tool or with invalid arguments.

pub type ToolCallChecks {
  RejectInvalidToolCalls
  ReportInvalidToolCalls
}

Constructors

  • RejectInvalidToolCalls

    Fail the response with error.Protocol. The default.

  • ReportInvalidToolCalls

    Return every call and list each failing one as a ToolCallIssue.

Why one returned call cannot be dispatched as declared.

pub type ToolCallIssue {
  UnknownTool(call_id: String)
  InvalidArguments(call_id: String, failure: error.ValueFailure)
}

Constructors

  • UnknownTool(call_id: String)

    The call names a tool the request did not declare.

  • InvalidArguments(call_id: String, failure: error.ValueFailure)

    The arguments are not JSON, fail the schema, or fail native decoding.

Why a runtime tool declaration was refused.

pub type ToolError {
  InvalidName(name: String, problem: NameProblem)
  InvalidSchema(contract.LoadError)
}

Constructors

  • InvalidName(name: String, problem: NameProblem)
  • InvalidSchema(contract.LoadError)

    The JSON Schema document is not valid JSON or uses keywords outside Blueprint’s profile.

Values

pub fn check_name(name: String) -> Result(Nil, NameProblem)

Check a name against the tool-name rule every built-in provider accepts.

pub fn decode_arguments(
  call: message.ToolCall,
  input: codec.Codec(a),
) -> Result(a, error.ValueFailure)

Decode a call’s arguments with input, validating them against the codec’s schema. Parsing uses Blueprint’s default 1 MiB byte limit. This does not impose a document-depth or value-count policy.

pub fn describe_error(error: ToolError) -> String
pub fn describe_issue(issue: ToolCallIssue) -> String

Text for the tool result that answers a failing call, for the model to read.

pub fn description(tool: Tool) -> String
pub fn from_contract(
  name: String,
  description: String,
  input: contract.Contract,
) -> Result(Tool, ToolError)

Declare a schema-only tool from a contract built at runtime.

pub fn from_json_schema(
  name: String,
  description: String,
  schema: json.Json,
) -> Result(Tool, ToolError)

Declare a schema-only tool from a JSON Schema document, such as an MCP tool’s inputSchema. A document without $schema is read as Draft 2020-12.

pub fn name(tool: Tool) -> String
pub fn new(
  name: String,
  description: String,
  input: codec.Codec(a),
) -> Tool

Declare a tool whose input is input. Panics, naming the tool, when the name is outside the tool-name rule or the codec has no usable schema; both are bugs in source code.

pub fn schema(tool: Tool) -> codec.Schema

The tool’s input schema, as providers receive it before projection.

✨ Search Document