WardrikCore.Tool (wardrik_core v0.1.0-rc.3)

Copy Markdown

A tool an agent may call.

WardrikCore.Tool.new!(
  name: "order_status",
  description: "Say where an order is.",
  schema: [order_id: [type: :string, required: true]],
  run: fn %{order_id: id}, _context -> {:ok, MyApp.Orders.status(id)} end,
  annotations: [read_only: true]
)

Return values

run takes the checked arguments and the WardrikCore.Context. It returns:

  • {:ok, answer} or {:error, reason}.
  • {:ok, answer, context} or {:error, reason, context}, such as with a cost measured.
  • {:park, reason} - waits for a person.

An answer can carry labels, such as "outside" for text from a stranger:

{:ok, %ReqLLM.ToolResult{output: page, metadata: %{labels: ["outside"]}}}

Annotations

  • :read_only - it changes nothing.
  • :destructive - what it changes can't be undone.
  • :idempotent - a call is safe to repeat.
  • :open_world - it reaches outside your systems, such as the web.
  • :timeout - how long a call may take, in milliseconds.
  • :resources - what a call acts on, as fn args -> [args["path"]] end.
  • :labels - labels every answer carries.

A read_only or idempotent call is retried, and repeated after a crash. Any other call lost in a crash parks as :in_doubt.

Summary

Functions

Adds annotations, such as read_only: true. Replaces any with the same key.

Returns the annotation key, or default if the tool doesn't set it.

Runs the tool call names, after checking its arguments. Returns {:error, reason} if there's no such tool or the arguments don't match.

Returns the private value under key, or default.

Builds a tool. Raises if a required option is missing.

Puts value in the private data under key. Use your own module as the key.

Returns whether a call to the tool is safe to repeat: it's read_only or idempotent.

Updates the private value under key with fun. Puts default if there's none yet.

Types

answer()

@type answer() ::
  {:ok, term()}
  | {:ok, term(), WardrikCore.Context.t()}
  | {:error, term()}
  | {:error, term(), WardrikCore.Context.t()}
  | {:park, term()}

t()

@type t() :: %WardrikCore.Tool{
  annotations: %{optional(atom()) => term()},
  description: String.t(),
  name: String.t(),
  private: map(),
  req_llm: ReqLLM.Tool.t(),
  run: (map(), WardrikCore.Context.t() -> answer()),
  schema: keyword() | map()
}

Functions

annotate(tool, new)

@spec annotate(t(), keyword() | map()) :: t()

Adds annotations, such as read_only: true. Replaces any with the same key.

annotation(tool, key, default \\ nil)

@spec annotation(t(), atom(), term()) :: term()

Returns the annotation key, or default if the tool doesn't set it.

call(tools, call, context)

Runs the tool call names, after checking its arguments. Returns {:error, reason} if there's no such tool or the arguments don't match.

get_private(struct, key, default \\ nil)

@spec get_private(t(), term(), term()) :: term()

Returns the private value under key, or default.

new!(opts)

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

Builds a tool. Raises if a required option is missing.

Options

  • :name - required.
  • :description - required. What the model reads to decide when to call it.
  • :run - required. A function of the arguments and the context.
  • :schema - the arguments, as a NimbleOptions keyword list or a JSON Schema map. [] by default.
  • :annotations - see above.

put_private(struct, key, value)

@spec put_private(t(), term(), term()) :: t()

Puts value in the private data under key. Use your own module as the key.

repeatable?(tool)

@spec repeatable?(t()) :: boolean()

Returns whether a call to the tool is safe to repeat: it's read_only or idempotent.

update_private(struct, key, default, fun)

@spec update_private(t(), term(), term(), (term() -> term())) :: t()

Updates the private value under key with fun. Puts default if there's none yet.