ExAgent.Tool (ExAgent v2.2.0)

View Source

A tool the model may call.

ExAgent.Tool bundles everything: the serialisable ToolDefinition (name, description, JSON-Schema parameters) and the actual callable that runs when the model invokes it. Use definition/1 to project the shape a provider sends to the model.

Tools are normally built via the deftool macro (see ExAgent.Tools), which derives the JSON-Schema from the function's @spec. They can also be built by hand with new/1.

execution_binding is private, data-only adapter identity used by persisted continuation fingerprints, never by definition/1. Local tools retain nil. MCP creates a validated descriptor or marks missing host identity :unbound; the latter supports ordinary calls and rejects persisted execution before IO. Do not strip this field or put credentials in it to make a tool resumable.

Summary

Functions

Serialisable projection sent to the model: name + description + params.

Build a tool by hand.

Prepare a tool's local JSON Schema validator before requesting the model.

Validate arguments without invoking the callable or changing the original map.

Check that a successful result payload can be encoded as JSON, preserving it.

Types

kind()

@type kind() :: :function | :output | :external | :unapproved

t()

@type t() :: %ExAgent.Tool{
  call: (ExAgent.RunContext.t(), map() -> term()) | (map() -> term()) | nil,
  delegation: term(),
  description: String.t() | nil,
  execution_binding: map() | :unbound | nil,
  kind: kind(),
  max_retries: non_neg_integer(),
  name: String.t(),
  parameters_json_schema: map() | boolean(),
  prepared_validator: term(),
  takes_ctx: boolean()
}

validation_error()

@type validation_error() :: %{
  path: String.t(),
  keyword: String.t(),
  message: String.t()
}

Functions

definition(tool)

@spec definition(t()) :: map()

Serialisable projection sent to the model: name + description + params.

new(opts)

@spec new(keyword()) :: t()

Build a tool by hand.

prepare(tool)

@spec prepare(t()) ::
  {:ok, t()} | {:error, {:invalid_tool_schema, [validation_error()]}}

Prepare a tool's local JSON Schema validator before requesting the model.

The opaque prepared_validator field is internal, is not serialized by definition/1, and is reused only for the exact immutable schema it was built from. No process-global cache is used. Draft 2020-12 (default) and draft 7 are supported with embedded/local references; executable casts, module references, and fetching external schemas are not supported.

Nested schemas must use the root dialect. The reference preflight checks candidate targets conservatively across embedded resources. Inert defaults are omitted only from the private build projection; referenced defaults are kept verbatim and remain subject to JSV's identifier-scanning restrictions.

validate_args(tool, args)

@spec validate_args(t(), term()) :: {:ok, map()} | {:error, [validation_error()]}

Validate arguments without invoking the callable or changing the original map.

Atom and string object keys are compared as JSON strings; collisions and values outside the JSON data model are rejected. Values are never coerced and defaults are never inserted. Error paths are JSON pointers (the root is "").

validate_result(tool, result)

@spec validate_result(t(), term()) :: {:ok, term()} | {:error, [validation_error()]}

Check that a successful result payload can be encoded as JSON, preserving it.

Pass the payload after unwrapping {:ok, payload}. Jason-encodable structs and atoms are supported; duplicate JSON object keys and encoding failures reject. This does not impose a result schema or retry an already executed callable.